用宏编号罗马数字的整数

时间:2015-07-25 18:14:42

标签: c macros

我有以下代码将数字转换为数字罗马

#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;
}

问题是我在没有宏的版本中思考但是我发现如果不扩展代码就没有可行的方法

有人有任何想法这样做吗?

1 个答案:

答案 0 :(得分:5)

您似乎正在实现基于表的整数到罗马数字系统。您恰好在代码中而不是在数据中实现表。

如果我们在数组中编码转换,它会是什么样子。我们还可以通过将上面代码中的每个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