C ++我需要编写一个将十六进制转换为十进制并使用递归的函数,并且我不断收到运行时错误

时间:2013-06-13 22:15:12

标签: c++ recursion

这是一个类,所以它必须使用递归,我已经迭代地编写了一个工作代码,但我不能让它在递归中工作,我真的迷路了。我已经为此工作了一个星期。任何指导或建议都会非常有用。

这是我的函数,我需要将十六进制作为char指针并输出相应的十进制数。我经常遇到堆栈溢出内存分配运行时错误,任何人都可以识别出错误并引导我朝着正确的方向前进吗?

 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;
  }
}

5 个答案:

答案 0 :(得分:7)

我没有编译它,但第一眼就告诉我相应的行应该是:

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

因为在你的情况下,你无限地称呼自己(被调用,假设偏移6,如果你传递偏移 - 它仍然会传递6,因为它会在给函数赋值后减少)。 / p>

此外,后增量将为您在同一表达式中稍后调用pow(16,power)提供未定义的行为,因为(再次以power = 6为例),它可能是pow(16,6)或{ {1}}取决于编译器。

除此之外,还存在风险,即pow()在转换为int时会给出错误(向下舍入)值(可能会发现pow(16,2)返回255.9999999而你最终得到(int) 255,stackoverflow上有足够的证据和解决方案,只需搜索pow)。

编辑(回复评论):

最后,介绍了神奇的printf调试器:

pow(16,7)

答案 1 :(得分:1)

你在这里使用后增量:

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

后递增(和后递减)将递增/递减变量(即它实际上更改 offsetpower),但是inc / dec将在评估变量之后发生。

即:

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'

您实际上并不想修改offsetpower - 您希望将这些值的其他值传递给下一个hexToDecimal来电。

如果你制作方法参数const,你可以捕捉到这些错误,即:

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

我建议您在无意修改参数时const。这样编译器可以帮助您捕获许多常见错误。

答案 2 :(得分:1)

在函数参数中使用predecrement。在参数中使用--offset。 如果你使用offset--则将offset的初始值传递给函数,然后减少offset。

答案 3 :(得分:0)

这是我在很久以前写过的一篇......它可能不是最好或最快的方法,可能会使用一些错误检查,但我会将其作为练习留给读者......

    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;
}

答案 4 :(得分:0)

这是一个使用第二个递归函数调用的简单解决方案。希望它能帮助你调试你的:

#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));
}

您可能希望使用long来处理更大的十六进制数。