2013-06-13 9 views
6

Dies ist für eine Klasse, so muss es Rekursion verwenden, ich habe einen Arbeitscode iterativ geschrieben, aber ich kann nicht Lass es in Rekursion arbeiten und ich bin wirklich verloren. Ich arbeite seit einer Woche daran. Jede Anleitung oder Vorschläge wären sehr hilfreich.C++ Ich muss eine Funktion schreiben, die Hexadezimal in Dezimal konvertiert und Rekursion verwendet und ich bekomme Laufzeitfehler

Das ist meine Funktion, ich muss das hexadezimale Zeichen als Char-Zeiger aufnehmen und es gibt die entsprechende Dezimalzahl aus. Ich bekomme ständig entweder Stapelüberlauf oder Speicherzuweisung Laufzeitfehler, kann jemand identifizieren, was falsch ist und mich in die richtige Richtung lenken?

int hexToDecimal(const char *hex, int offset, int power){ 
    if(offset >= 0){ 
    hexChar = *(hex+offset); 

    if(isalpha(hexChar)) { 
     hexChar = toupper(hexChar); 
     hexNum = hexChar - asciiCharOffset; 
    } else { 
     hexNum = hexChar - asciiIntOffset; 
    } 
    return hexToDecimal(hex, offset--, power++) + hexNum * (int)pow(16,power); 

    } else { 
    return 0; 
    } 
} 
+0

Wie nennt man diese Funktion? Und wo definierst du 'hexChar' und' hexNum'? –

+0

Wo ist das minimale Arbeitsbeispiel, das das Problem reproduziert? Welche Art von Fehlern bekommen Sie? Sie können eine Frage wie diese nicht stellen und erwarten eine gute Antwort, keine Hellseher hier. –

+0

nenne ich es in dieser Hauptschleife: \t 'while (Eingang >> hex)' \t '' { \t \t 'int offset = Strlen (hex);' \t \t 'int Leistung = 0; ' \t \t' cout << hexToDecimal (hex, Offset, Energie); ' \t'} ' Sorry über die Formatierung. –

Antwort

7

Ich habe es nicht kompiliert, aber den ersten Blick sagt mir, dass die entsprechende Zeile sein soll:

return hexToDecimal(hex, offset-1, power+1) + hexNum * (int) pow(16,power-1);  

Da in Ihrem Fall, Sie selbst nennen ad infinitum (mit aufgerufen wird, können sagen, Offset 6, wenn Sie Offset übergeben - es wird immer noch 6 übergeben, weil es dekrementieren wird, nachdem es der Funktion den Wert gibt.

Auch das Post-Inkrement werden Sie nicht definiertes Verhalten für die pow(16,power) später in demselben Ausdruck anrufen, weil sie (am Beispiel der Leistung = 6 wieder nehmen), es pow(16,6) oder pow(16,7) auf dem Compiler abhängig sein kann.

Abgesehen davon gibt es auch das Risiko, dass pow() Ihnen einen falschen (abgerundeten) Wert bei der Konvertierung in int geben wird (es kann sich herausstellen, dass pow (16,2) 255.9999999 zurückgibt und Sie enden mit (int) 255, es gibt reichlich Beweise und Lösungen hier auf stackoverflow, suche nur nach pow).

EDIT (in Antwort auf Kommentare):

schließlich die magische printf Debugger Einführung:

int hexToDecimal(const char *hex, int offset, int power){ 
    if(offset >= 0){ 
    char hexChar = *(hex+offset); 
    int hexNum, 
     recursed; 

    if(isalpha(hexChar)) { 
     hexChar = toupper(hexChar); 
     hexNum = hexChar - asciiCharOffset; 
    } 
    else { 
     hexNum = hexChar - asciiIntOffset; 
    } 
    recursed= hexToDecimal(hexNum, offset-1, power+1); 

    printf("%d + %d * %d\n", recursed, hexNum, (int)pow(16,power-1)); 

    return recursed + hexNum * (int)pow(16,power-1); 

    } else { 
    return 0; 
    } 
} 
+0

Es funktioniert immer noch nicht richtig, aber mit dem wird es jetzt laufen, also danke, dass ich hier angefangen habe. Wenn ich AA gebe, bekomme ich 2731, BA gibt mir 3004, 0 gibt mir 1, 1 gibt mir 18, und so weiter in einer scheinbar zufälligen Reihenfolge. Aber zumindest jetzt kann ich es kompilieren und sehen, was passiert. –

+0

Ich denke, Sie wollen Pow (16, Power-1) (die letzte Ziffer ist 10 * 16^0). Bearbeitete das Ding entsprechend. – Yamodax

+0

Verdammt, du bist wie eine Art Zauberer. Es funktioniert immer noch nicht, aber jetzt sind einige der Werte viel näher. Zum Beispiel gibt AA 171 zurück, wenn es 170 zurückgeben soll. Einige sind nur einmal aus, während andere überall sind. Zum Beispiel geben sowohl -cf als auch -10 -818 zurück. Ich komme aber näher. –

1

Sie verwenden Nachinkrement hier:

return hexToDecimal(hex, offset--, power++) 

Post-Zuwachs (und Nach-Dekrementieren) wird die Variable inkrementieren/dekrementieren (dh es wird tatsächlich Änderungoffset und power), aber die Inc/Dez wird nach die Variable wird ausgewertet.

d.h .:

int i = 5; 
std::cout << "i = " << i;  // prints 'i = 5' 
std::cout << "\ni = " << i++; // still prints 'i = 5' and then changes i to be 6 
std::cout << "\ni = " << i; // prints 'i = 6' 

Sie wollen nicht wirklich offset und power ändern - Sie einen anderen Wert für diese auf den nächsten hexToDecimal Anruf übergeben werden sollen.

können Sie diese Art von Fehlern fangen, wenn Sie die Methode machen Parameter const, d.h .:

int hexToDecimal(const char*hex, const int offset, const int power); 

Ich empfehle machen Parameter const, wenn Sie nicht die Absicht haben, sie zu ändern. Auf diese Weise kann der Compiler Ihnen helfen, viele häufige Fehler zu finden.

+0

Oh, ich verstehe. Vielen Dank. Es macht Sinn, warum der andere Typ sie durch 'Offset - 1' und 'Power + 1' ersetzt hat, ich war ein wenig verloren, warum er das tat. –

0

Hier ist eine, die ich vor langer Zeit geschrieben habe ...Es ist wahrscheinlich nicht der beste oder schnellster Ansatz und könnte eine Fehlerprüfung verwenden, aber das werde ich ...

long GetValue(const char *pszStrVal) 
    { 
     long Retval = 0; 
     try { 
     char *p = (char*)pszStrVal; 
     if(p == NULL) return 0; 

     if(strstr(p, "0x")) { 
      p++;p++; 
      long x = strlen(p); 
      long pval = 1 << ((x-1)*4); 

      for(int y = 0;y < x;y++,pval = (pval >> 4)) 
      { 
       int digit = 0; 
       switch(p[y]) 
       { 
       case 'A': 
       case 'a': 
        digit = 10; 
        break; 
       case 'B': 
       case 'b': 
        digit = 11; 
        break; 
       case 'C': 
       case 'c': 
        digit = 12; 
        break; 
       case 'D': 
       case 'd': 
        digit = 13; 
        break; 
       case 'E': 
       case 'e': 
        digit = 14; 
        break; 
       case 'F': 
       case 'f': 
        digit = 15; 
        break; 
       default: 
        digit = p[y] - 0x30; 
       } 

       Retval += (pval * digit); 
      } 
     } else { 
      Retval = atoi(p); 
     } 
    } 
    catch(...) 
    { 
     Retval = 0; 
    } 
    return Retval; 
} 
1

Verwendung predecrement in der das Funktionsargument für den Leser als Übung überlassen. Verwenden Sie --offset im Argument. Wenn Sie Offset verwenden - dann wird der Anfangswert des Offsets an die Funktion übergeben und dann wird der Offset verringert.

0

Hier ist eine einfache Lösung, die einen zweiten rekursiven Funktionsaufruf verwendet. Hoffentlich wird es Ihnen helfen, Ihr debuggen:

#include <stdio.h> 
#include <ctype.h> 

int h2d_rec(const char *hex, int d); 

int h2d(const char *hex) { 
    return h2d_rec(hex, 0); 
} 

int h2d_rec(const char *hex, int d) { 
    char hexChar = *hex; 
    if (0==hexChar) { 
     return d; 
    } 
    int charNum; 
    if (isalpha(hexChar)) { 
     charNum = 10 + toupper(hexChar) - 'A'; 
    } else { 
     charNum = hexChar - '0'; 
    } 
    // Note d<<4 is the same as 16*d 
    return h2d_rec(hex+1, (d<<4) + charNum); 
} 

int main(int argc, const char **argv) { 
    const char *hex = "FF"; 

    if (1<argc) { 
     hex = argv[1]; 
    } 
    printf("%s in decimal is %d\n", hex, h2d(hex)); 
} 

Sie könnten long verwenden möchten, anstatt größere Hex-Zahlen zu behandeln.

Verwandte Themen