无法在C中实现递归调用

所以我第一次和C一起工作,我觉得我在使用递归时遇到了麻烦。 例如,要在C#中return methodRecursiveCall(parameter)递归调用的值,我可能会使用return methodRecursiveCall(parameter) 。 在C中,我有这个声明,它是罗马数字转换器的一部分:

 int convert(char *s) { int val = 0; int index = 0; int length = strlen(s); while (length >1) { if (s[index] == 'I') { if(s[index + 1] == 'V' || s[index + 1] == 'X' || s[index + 1] == 'C' || s[index + 1] == 'D' || s[index + 1] == 'M') { val--; index++; length--; convert(&(s[index])); } else { val++; index++; length--; convert(&(s[index])); } } if (s[index] == 'V') { if(s[index + 1] == 'X' || s[index + 1] == 'C' || s[index + 1] == 'D' || s[index + 1] == 'M') { val = val - 5; index++; length--; convert(&(s[index])); } else { val = val + 5; index++; length--; convert(&(s[index])); } } if (s[index] == 'X') { if(s[index + 1] == 'C' || s[index + 1] == 'D' || s[index + 1] == 'M') { val = val - 10; index++; length--; convert(&(s[index])); } else { val = val + 10; index++; length--; convert(&(s[index])); } } if (s[index] == 'C') { if((s[index + 1]) == 'D' || (s[index + 1]) == 'M') { val = val - 100; index++; length--; convert(&(s[index])); } else { val = val + 100; index++; length--; convert(&(s[index])); } } if (s[index] == 'D') { if(s[index + 1] == 'M') { val = val - 500; index++; length--; convert(&(s[index])); } else { val = val + 500; index++; length--; convert(&(s[index])); } } if (s[index] == 'M') { val = val + 500; index++; length--; convert(&(s[index])); } } return val; } 

我的问题具体是关于convert(&(s[index])); ,这是一个递归调用。 它意味着将整个罗马数字转换为十进制,但它只转换第一个字符。 这通常是我要“回归”的地方。 但是,我不知道如何在C中取消它。

从接近结尾的这个片段:

 if (s[index] == 'M') { val = val + 500; index++; length--; convert(&(s[index])); } 

你可能想要这样的东西:

 if (s[index] == 'M') val = 1000 + convert(&s[index+1]); 

你知道M映射到1000; 总值将是1000 + M的值,这是表达式所表达的。 请注意, s[index+1]周围s[index+1]括号不是必需的。

您需要在整个代码中进行类似的更改。 您还需要查看为什么将迭代与递归混合在一起; 你应该使用其中一个。

请注意,您的代码似乎不包括L aka 50。

就个人而言,我认为这不是进行转换的最佳方式。 除此之外,很难发现MXMC无效。 我的代码使用包含字符串和相应值( M1000 ; CM和900)等的结构数组,并且一旦其中一个值用完( CM只能使用一次; M可以多次使用; CD可以使用一次; C可以多次使用 – 也可以使用它,然后它不能再出现。 它使用迭代而不是递归。


这是一个适度简单的改编和修复你的代码。 它适用于转换“已知有效”罗马数字; 它不适用于validation它们。

 #include  int convert(const char *s); int convert(const char *s) { int val = 0; int i = 0; if (s[i] == '\0') return 0; if (s[i] == 'I') { if (s[i + 1] != 'I' && s[i + 1] != '\0') val = convert(&s[i + 1]) - 1; else val = 1 + convert(&s[i + 1]); } if (s[i] == 'V') val = 5 + convert(&s[i + 1]); if (s[i] == 'X') { if (s[i + 1] == 'L' || s[i + 1] == 'C' || s[i + 1] == 'D' || s[i + 1] == 'M') val = convert(&s[i + 1]) - 10; else val = 10 + convert(&s[i + 1]); } if (s[i] == 'L') val = 50 + convert(&s[i + 1]); if (s[i] == 'C') { if ((s[i + 1]) == 'D' || (s[i + 1]) == 'M') val = convert(&s[i + 1]) - 100; else val = 100 + convert(&s[i + 1]); } if (s[i] == 'D') val = 500 + convert(&s[i + 1]); if (s[i] == 'M') val = 1000 + convert(&s[i + 1]); return val; } int main(void) { const struct roman { const char *str; int num; } test[] = { { "I", 1 }, { "II", 2 }, { "III", 3 }, { "IV", 4 }, { "V", 5 }, { "VI", 6 }, { "VII", 7 }, { "VIII", 8 }, { "VIIII", 9 }, { "IX", 9 }, { "X", 10 }, { "XI", 11 }, { "XII", 12 }, { "XIII", 13 }, { "XIV", 14 }, { "XV", 15 }, { "XVI", 16 }, { "XVII", 17 }, { "XVIII", 18 }, { "XIX", 19 }, { "XVIIII", 19 }, { "XX", 20 }, { "XXI", 21 }, { "XXX", 30 }, { "XL", 40 }, { "L", 50 }, { "LXXVIII", 78 }, { "XCVIII", 98 }, { "IC", 99 }, { "XCIX", 99 }, { "C", 100 }, { "D", 500 }, { "M", 1000 }, { "MMMDCCCLXXXVIII", 3888 }, { "MDCMMCCLXIIIIII", 3666 }, // Not good for validating! }; enum { NUM_TEST = sizeof(test) / sizeof(test[0]) }; for (int i = 0; i < NUM_TEST; i++) { int value = convert(test[i].str); printf("%s %15s = %4d vs %4d\n", (value == test[i].num) ? "== PASS ==" : "!! FAIL !!", test[i].str, value, test[i].num); } return 0; } 

样本输出:

 == PASS == I = 1 vs 1 == PASS == II = 2 vs 2 == PASS == III = 3 vs 3 == PASS == IV = 4 vs 4 == PASS == V = 5 vs 5 == PASS == VI = 6 vs 6 == PASS == VII = 7 vs 7 == PASS == VIII = 8 vs 8 == PASS == VIIII = 9 vs 9 == PASS == IX = 9 vs 9 == PASS == X = 10 vs 10 == PASS == XI = 11 vs 11 == PASS == XII = 12 vs 12 == PASS == XIII = 13 vs 13 == PASS == XIV = 14 vs 14 == PASS == XV = 15 vs 15 == PASS == XVI = 16 vs 16 == PASS == XVII = 17 vs 17 == PASS == XVIII = 18 vs 18 == PASS == XIX = 19 vs 19 == PASS == XVIIII = 19 vs 19 == PASS == XX = 20 vs 20 == PASS == XXI = 21 vs 21 == PASS == XXX = 30 vs 30 == PASS == XL = 40 vs 40 == PASS == L = 50 vs 50 == PASS == LXXVIII = 78 vs 78 == PASS == XCVIII = 98 vs 98 == PASS == IC = 99 vs 99 == PASS == XCIX = 99 vs 99 == PASS == C = 100 vs 100 == PASS == D = 500 vs 500 == PASS == M = 1000 vs 1000 == PASS == MMMDCCCLXXXVIII = 3888 vs 3888 == PASS == MDCMMCCLXIIIIII = 3666 vs 3666 

请注意,最后一个'数字'是可怕的伪造(1000 + 500 + 900 + 1000 + 100 + 100 + 50 + 10 + 1 + 1 + 1 + 1 + 1 + 1)。