将罗马数字转换为阿拉伯数字再转换为罗马数字的程序有时会给出错误的结果
Program that converts from roman numerals to arabic numerals to roman sometimes gives wrong result
我有这个程序试图将阿拉伯数字转换为罗马数字,并且编译没有问题,但对于某些值,它给出了正确的答案,但对于其他情况,它没有。例如:
11 是错误的(一个 X 留在 X 的左边)
12 是错误的(一个 X 留在 X 的左边)
20个就好
22 错了(剩下 2 X)
30个就好
32 错了(剩下 2 X)
40个就好
45不好(还剩一个XL)
48 是错误的(一个 X 留在第二个 L 之前)
50个就好
51给坏(剩下一个L)
58 不好(剩下一个 L)
60就好了
char *a2roman (int valor, char *c1, char *c2, char *c3);
int main (void)
{
int ArabicNumber = 1;
int result;
char roman[15] = "";
do
{
printf ("Enter an integer in the range 1 to 3000: \n\t");
scanf ("%d", &ArabicNumber);
}
while ((ArabicNumber < 1) || (ArabicNumber > 3000));
if ((ArabicNumber <= 3000) && (ArabicNumber >= 1000))
{
result = ArabicNumber / 1000;
strcat (roman, a2roman(result, "M", " ", " "));
ArabicNumber -= (result * 1000);
}
if ((ArabicNumber < 1000) && (ArabicNumber >= 100))
{
result = ArabicNumber / 100;
strcat (roman, a2roman(result, "C", "D", "M"));
ArabicNumber -= (result * 100);
}
if ((ArabicNumber < 100) && (ArabicNumber >= 10))
{
result = ArabicNumber / 10;
strcat (roman, a2roman(result, "X", "L", "C"));
ArabicNumber -= (result * 10);
}
if ((ArabicNumber < 10) && (ArabicNumber >= 1))
{
strcat (roman, a2roman(ArabicNumber, "I", "V", "X"));
}
printf ("The Roman numeral is: \n\t%s\n\n", roman);
printf ("\t\t...Press any key to finish.");
getch();
return 0;
}
char *a2roman (int value, char *c1, char *c2, char *c3)
{
int i;
static char rRoman[15] = "";
/* Si "valor" = 1, 2, 3 */
if ((value >= 1) && (value <= 3))
{
for (i = 0; i < value; i++)
strcat (rRoman, c1);
}
/* Si "valor" = 5, 6, 7, 8 */
if ((value >= 5) && (value <= 8))
{
strcat (rRoman, c2);
for (i = 0; i < (value - 5); i++)
strcat (rRoman, c1);
}
/* Si "valor" = 4 */
if (value == 4)
{
strcat (rRoman, c1);
strcat (rRoman, c2);
}
/* Si "valor" = 9 */
if (value == 9)
{
strcat (rRoman, c1);
strcat (rRoman, c3);
}
return (rRoman);
}
a2roman
中的静态缓冲区构建了完整的结果,但每次从 main
调用它时,部分结果也会连接到打印出的缓冲区,因此如果 a2roman
被多次调用。
一个解决方案是在通过使 roman
成为指针并分配 return 值来构建完整结果之后直接使用 a2roman
中的 return 值从 a2roman
到它每次 a2roman
被称为:
char* roman = NULL;
...
roman = a2roman(result, "M", " ", " ");
...
roman = a2roman(result, "C", "D", "M");
...
printf ("The Roman numeral is: \n\t%s\n\n", roman);
但是,如果您想要转换多个数字,由于静态缓冲区,您仍然会遇到问题。如果你有指向它的指针,你可以在数字之间清除它,比如 *roman = 0;
但这对我来说仍然感觉很乱。
另一种解决方案是传入要在其中构造数字的缓冲区。
以下示例展示了如何执行此操作,并且还清理了一些用于将数字分解为数字的逻辑。你的方法有效,但我想我还不如展示另一种方法并节省几行。
#include <stdio.h>
#include <string.h>
void addDigit(char* out, int digit, const char* c1, const char* c2, const char* c3)
{
if ((digit >= 1) && (digit <= 3))
{
for (int i = 0; i < digit; i++)
{
strcat(out, c1);
}
}
if ((digit >= 5) && (digit <= 8))
{
strcat(out, c2);
for (int i = 0; i < (digit - 5); i++)
{
strcat(out, c1);
}
}
if (digit == 4)
{
strcat(out, c1);
strcat(out, c2);
}
if (digit == 9)
{
strcat(out, c1);
strcat(out, c3);
}
}
void convertNumber(char* out, int num)
{
if ((num <= 3000) && (num >= 1000))
{
addDigit(out, num / 1000, "M", " ", " ");
num %= 1000;
}
if ((num < 1000) && (num >= 100))
{
addDigit(out, num / 100, "C", "D", "M");
num %= 100;
}
if ((num < 100) && (num >= 10))
{
addDigit(out, num / 10, "X", "L", "C");
num %= 10;
}
if ((num < 10) && (num >= 1))
{
addDigit(out, num, "I", "V", "X");
}
}
int main(void)
{
for (int i = 1; i < 100; i += 3)
{
char buf[32] = { 0 };
convertNumber(buf, i);
printf("%4d = %s\n", i, buf);
}
for (int i = 101; i < 3000; i += 101)
{
char buf[32] = { 0 };
convertNumber(buf, i);
printf("%4d = %s\n", i, buf);
}
return 0;
}
输出:
1 = I
4 = IV
7 = VII
10 = X
13 = XIII
16 = XVI
19 = XIX
22 = XXII
25 = XXV
28 = XXVIII
31 = XXXI
34 = XXXIV
37 = XXXVII
40 = XL
43 = XLIII
46 = XLVI
49 = XLIX
52 = LII
55 = LV
58 = LVIII
61 = LXI
64 = LXIV
67 = LXVII
70 = LXX
73 = LXXIII
76 = LXXVI
79 = LXXIX
82 = LXXXII
85 = LXXXV
88 = LXXXVIII
91 = XCI
94 = XCIV
97 = XCVII
101 = CI
202 = CCII
303 = CCCIII
404 = CDIV
505 = DV
606 = DCVI
707 = DCCVII
808 = DCCCVIII
909 = CMIX
1010 = MX
1111 = MCXI
1212 = MCCXII
1313 = MCCCXIII
1414 = MCDXIV
1515 = MDXV
1616 = MDCXVI
1717 = MDCCXVII
1818 = MDCCCXVIII
1919 = MCMXIX
2020 = MMXX
2121 = MMCXXI
2222 = MMCCXXII
2323 = MMCCCXXIII
2424 = MMCDXXIV
2525 = MMDXXV
2626 = MMDCXXVI
2727 = MMDCCXXVII
2828 = MMDCCCXXVIII
2929 = MMCMXXIX
我有这个程序试图将阿拉伯数字转换为罗马数字,并且编译没有问题,但对于某些值,它给出了正确的答案,但对于其他情况,它没有。例如:
11 是错误的(一个 X 留在 X 的左边) 12 是错误的(一个 X 留在 X 的左边)
20个就好
22 错了(剩下 2 X)
30个就好
32 错了(剩下 2 X)
40个就好
45不好(还剩一个XL) 48 是错误的(一个 X 留在第二个 L 之前)
50个就好
51给坏(剩下一个L) 58 不好(剩下一个 L)
60就好了
char *a2roman (int valor, char *c1, char *c2, char *c3);
int main (void)
{
int ArabicNumber = 1;
int result;
char roman[15] = "";
do
{
printf ("Enter an integer in the range 1 to 3000: \n\t");
scanf ("%d", &ArabicNumber);
}
while ((ArabicNumber < 1) || (ArabicNumber > 3000));
if ((ArabicNumber <= 3000) && (ArabicNumber >= 1000))
{
result = ArabicNumber / 1000;
strcat (roman, a2roman(result, "M", " ", " "));
ArabicNumber -= (result * 1000);
}
if ((ArabicNumber < 1000) && (ArabicNumber >= 100))
{
result = ArabicNumber / 100;
strcat (roman, a2roman(result, "C", "D", "M"));
ArabicNumber -= (result * 100);
}
if ((ArabicNumber < 100) && (ArabicNumber >= 10))
{
result = ArabicNumber / 10;
strcat (roman, a2roman(result, "X", "L", "C"));
ArabicNumber -= (result * 10);
}
if ((ArabicNumber < 10) && (ArabicNumber >= 1))
{
strcat (roman, a2roman(ArabicNumber, "I", "V", "X"));
}
printf ("The Roman numeral is: \n\t%s\n\n", roman);
printf ("\t\t...Press any key to finish.");
getch();
return 0;
}
char *a2roman (int value, char *c1, char *c2, char *c3)
{
int i;
static char rRoman[15] = "";
/* Si "valor" = 1, 2, 3 */
if ((value >= 1) && (value <= 3))
{
for (i = 0; i < value; i++)
strcat (rRoman, c1);
}
/* Si "valor" = 5, 6, 7, 8 */
if ((value >= 5) && (value <= 8))
{
strcat (rRoman, c2);
for (i = 0; i < (value - 5); i++)
strcat (rRoman, c1);
}
/* Si "valor" = 4 */
if (value == 4)
{
strcat (rRoman, c1);
strcat (rRoman, c2);
}
/* Si "valor" = 9 */
if (value == 9)
{
strcat (rRoman, c1);
strcat (rRoman, c3);
}
return (rRoman);
}
a2roman
中的静态缓冲区构建了完整的结果,但每次从 main
调用它时,部分结果也会连接到打印出的缓冲区,因此如果 a2roman
被多次调用。
一个解决方案是在通过使 roman
成为指针并分配 return 值来构建完整结果之后直接使用 a2roman
中的 return 值从 a2roman
到它每次 a2roman
被称为:
char* roman = NULL;
...
roman = a2roman(result, "M", " ", " ");
...
roman = a2roman(result, "C", "D", "M");
...
printf ("The Roman numeral is: \n\t%s\n\n", roman);
但是,如果您想要转换多个数字,由于静态缓冲区,您仍然会遇到问题。如果你有指向它的指针,你可以在数字之间清除它,比如 *roman = 0;
但这对我来说仍然感觉很乱。
另一种解决方案是传入要在其中构造数字的缓冲区。
以下示例展示了如何执行此操作,并且还清理了一些用于将数字分解为数字的逻辑。你的方法有效,但我想我还不如展示另一种方法并节省几行。
#include <stdio.h>
#include <string.h>
void addDigit(char* out, int digit, const char* c1, const char* c2, const char* c3)
{
if ((digit >= 1) && (digit <= 3))
{
for (int i = 0; i < digit; i++)
{
strcat(out, c1);
}
}
if ((digit >= 5) && (digit <= 8))
{
strcat(out, c2);
for (int i = 0; i < (digit - 5); i++)
{
strcat(out, c1);
}
}
if (digit == 4)
{
strcat(out, c1);
strcat(out, c2);
}
if (digit == 9)
{
strcat(out, c1);
strcat(out, c3);
}
}
void convertNumber(char* out, int num)
{
if ((num <= 3000) && (num >= 1000))
{
addDigit(out, num / 1000, "M", " ", " ");
num %= 1000;
}
if ((num < 1000) && (num >= 100))
{
addDigit(out, num / 100, "C", "D", "M");
num %= 100;
}
if ((num < 100) && (num >= 10))
{
addDigit(out, num / 10, "X", "L", "C");
num %= 10;
}
if ((num < 10) && (num >= 1))
{
addDigit(out, num, "I", "V", "X");
}
}
int main(void)
{
for (int i = 1; i < 100; i += 3)
{
char buf[32] = { 0 };
convertNumber(buf, i);
printf("%4d = %s\n", i, buf);
}
for (int i = 101; i < 3000; i += 101)
{
char buf[32] = { 0 };
convertNumber(buf, i);
printf("%4d = %s\n", i, buf);
}
return 0;
}
输出:
1 = I
4 = IV
7 = VII
10 = X
13 = XIII
16 = XVI
19 = XIX
22 = XXII
25 = XXV
28 = XXVIII
31 = XXXI
34 = XXXIV
37 = XXXVII
40 = XL
43 = XLIII
46 = XLVI
49 = XLIX
52 = LII
55 = LV
58 = LVIII
61 = LXI
64 = LXIV
67 = LXVII
70 = LXX
73 = LXXIII
76 = LXXVI
79 = LXXIX
82 = LXXXII
85 = LXXXV
88 = LXXXVIII
91 = XCI
94 = XCIV
97 = XCVII
101 = CI
202 = CCII
303 = CCCIII
404 = CDIV
505 = DV
606 = DCVI
707 = DCCVII
808 = DCCCVIII
909 = CMIX
1010 = MX
1111 = MCXI
1212 = MCCXII
1313 = MCCCXIII
1414 = MCDXIV
1515 = MDXV
1616 = MDCXVI
1717 = MDCCXVII
1818 = MDCCCXVIII
1919 = MCMXIX
2020 = MMXX
2121 = MMCXXI
2222 = MMCCXXII
2323 = MMCCCXXIII
2424 = MMCDXXIV
2525 = MMDXXV
2626 = MMDCXXVI
2727 = MMDCCXXVII
2828 = MMDCCCXXVIII
2929 = MMCMXXIX