我有以下将数字转换为罗马数字的代码
#include <stdlib.h>
#include <stdio.h>
void roman(char *s, unsigned int n)
{
if (n == 0)
{
fputs("Roman numeral zero does not exist ", stderr);
exit(EXIT_FAILURE);
}
#define digit(loop, num, c) \
loop (n >= num) \
{*(s++) = c; \
n -= num;}
#define digits(loop, num, c1, c2) \
loop (n >= num) \
{*(s++) = c1; \
*(s++) = c2; \
n -= num;}
digit ( while, 1000, 'M' )
digits ( if, 900, 'C', 'M' )
digit ( if, 500, 'D' )
digits ( if, 400, 'C', 'D' )
digit ( while, 100, 'C' )
digits ( if, 90, 'X', 'C' )
digit ( if, 50, 'L' )
digits ( if, 40, 'X', 'L' )
digit ( while, 10, 'X' )
digits ( if, 9, 'I', 'X' )
digit ( if, 5, 'V' )
digits ( if, 4, 'I', 'V' )
digit ( while, 1, 'I' )
#undef digit
#undef digits
*s = 0;
}
int main(void)
{
char buffer[16];
unsigned int i;
for (i = 1; i <= 100; ++i)
{
roman(buffer, i);
printf("%4u: %s\n", i, buffer);
}
return EXIT_SUCCESS;
}
问题是我在考虑一个没有宏的版本,但我发现如果不扩展代码就没有可行的方法
有人知道这样做吗?
看来您正在实现一个基于表格的整数到罗马数字系统。您只是碰巧用代码而不是数据来实现该表。
如果我们将转换编码到一个数组中,它会是这样的。我们还可以通过将上面代码中的每个 if
语句转换为 while
语句来简化逻辑。
#include <assert.h>
#include <string.h>
#include <stdio.h>
static struct {
unsigned decimal;
char *roman;
} conversion_table[] = {
{1000, "M" },
{ 900, "CM"},
{ 500, "D" },
{ 400, "CD"},
{ 100, "C" },
{ 90, "XC"},
{ 50, "L" },
{ 40, "XL"},
{ 10, "X" },
{ 9, "IX"},
{ 5, "V" },
{ 4, "IV"},
{ 1, "I" },
};
void roman(char *s, unsigned int n) {
s[0] = '\0';
for (int i=0; i < sizeof(conversion_table) / sizeof(*conversion_table); ++i) {
while (n >= conversion_table[i].decimal) {
n -= conversion_table[i].decimal;
strcat(s, conversion_table[i].roman);
s += strlen(s);
}
}
}
int main() {
char s[100];
roman(s, 1024);
printf("%d == %s\n", 1024, s);
}
哪些输出:
1024 == MXXIV
我是一名优秀的程序员,十分优秀!