s = "MCMXCIV"
的最后一个测试用例不工作。输出是3099
而不是1994
。我已经将所有的罗马数字添加到整数中,但无法找出问题所在。前两个用例已正确执行,以给予预期的输出。
// code start
int romanToInt(char *s) {
int sum = 0;
if (*s == NULL) {
return NULL;
}
for (int i = 0; i < strlen(s); i++) {
if (s[i] == 'M') {
sum = sum + 1000;
}
if (s[i] == 'D') {
sum = sum + 500;
}
if (s[i] == 'C') {
sum = sum + 100;
}
if (s[i] == 'L') {
sum = sum + 50;
}
if (s[i] == 'X') {
sum = sum + 10;
}
if (s[i] == 'V') {
sum = sum + 5;
}
if (s[i] == 'I') {
sum = sum + 1;
}
if (i > 0) {
if (s[i] == 'V' && s[i - 1] == 'I') {
sum = sum + 3;
}
if (s[i] == 'X' && s[i - 1] == 'I') {
sum = sum + 8;
}
if (s[i] == 'L' && s[i - 1] == 'X') {
sum = sum + 30;
}
if (s[i] == 'C' && s[i - 1] == 'X') {
sum = sum + 80;
}
if (s[i] == 'D' && s[i - 1] == 'C') {
sum = sum + 300;
}
if (s[i] == 'M' && s[i - 1] == 'C') {
sum = sum + 800;
}
}
//sum represents the converted integer
}
return sum;
}//code end
4条答案
按热度按时间6gpjuf901#
存在多个问题:
*s
与NULL
进行比较是不正确的:NULL
是一个表示空指针的宏,*s
不是指针,它是一个字符,你可以把它与'\0'
或0
进行比较。如果NULL
被定义为0
或0L
,你的代码会偶然编译,但如果是另一个经典定义((void *)0)
,就不会编译。for
循环将立即停止一个空字符串。i < strlen(s)
可能会在每次迭代时重新计算字符串长度,这是低效的。您可以只测试ifs[i] != '\0'
。以下是修改后的版本:
这种简单的实现适用于
MCMXCIV
(1994
),但不会检测到无效数字,如MXMIV
,MVMI
,XMMIV
......这些数字也会产生1994
。经典的表示法只在接下来的2个字母前面使用I
,X
和C
,但是在Roman Numerals的漫长历史中已经发现了许多变化。罗马数字体现了人类有史以来最持久的发明之一:计数。字母
I
,V
和X
的形状看起来与史前文物上发现的Tally marks惊人地相似。在最先进的科学出版物中看到石器时代穴居人用来计数的形状让我不寒而栗。sycxhyv72#
这里有一个相当简单的程序来做这件事。注意,它不检查无效字符串。但它有一个更清晰的设计,并将实际的罗马值与计算它们的逻辑分离开来。
它使用这些规则:
它不遵循这些规则
可能还有其他一些我没有执行的规则。
验证码:
输出:
https://onlinegdb.com/poJLQy70C
htrmnn0y3#
在使用
if()
语句级联的OP方法之后,有以下内容。(注意没有不必要的花括号,并且使用了C的逗号运算符。)这利用了C的“配对”else
与“最后一个else-lessif
”。没有努力确保源字符串是有效的罗马数字。
编辑:
另一方面,交织数据和处理可能会导致头痛。
对于像这样的转换,一个经过深思熟虑的存储Map的查找表可以通过一小段代码(如以下代码)来提供。
编辑2:
花括号爱好者似乎不喜欢这个答案。
作为回应,这里是以前的版本修改,以检查和拒绝无效的罗马数字...易于维护时,设计已经健全:
输出:
nx7onnlm4#
你的基本方法是可靠的,但是你的条件顺序不正确,你可能想使用
else
来确保只有一个分支可以执行,因为字符是整数,你可以使用switch语句。然后,您可以检查是否在第一个字符和
continue
上,以跳过循环剩余部分的控制流,在循环剩余部分中,您检查前面的字符,并直接进入下一次迭代。