所以我第一次和C一起工作,我觉得我在使用递归时遇到了麻烦。例如,要在C#中返回递归调用的值,我可能会使用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中取消它。
答案 0 :(得分:0)
从接近结尾的这个片段:
if (s[index] == 'M')
{
val = val + 500;
index++;
length--;
convert(&(s[index]));
}
您可能需要以下内容:
if (s[index] == 'M')
val = 1000 + convert(&s[index+1]);
您知道M
映射到1,000;总值将是1000 + M
之后的值,这是表达式所声明的。请注意,s[index+1]
周围的括号不是必需的。
您需要在整个代码中进行类似的更改。您还需要查看为什么将迭代与递归混合在一起;你应该使用其中一个。
请注意,您的代码似乎不包括L
又名50。
就个人而言,我认为这不是进行转换的最佳方式。除此之外,很难发现MXMC
无效。我的代码使用包含字符串和相应值(M
和1000
; CM
和900)等的结构数组,并且一旦其中一个值用完({{ 1}}只能使用一次; CM
可以多次使用; M
可以使用一次; CD
可以多次使用 - 也可以使用,但它可以' t稍后再出现。它使用迭代而不是递归。
这是一个适度简单的改编和修复你的代码。它适用于转换“已知有效”罗马数字;它不适用于验证它们。
C
示例输出:
#include <stdio.h>
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;
}
请注意,最后一个'数字'是可怕的伪造(1000 + 500 + 900 + 1000 + 100 + 100 + 50 + 10 + 1 + 1 + 1 + 1 + 1 + 1)。