Reputation: 1151
I have the following code that converts a number to number roman
#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;
}
The trouble is I'm thinking in a version without macros but I find no feasible way to do without extending the code
someone has any idea to do this?
Upvotes: 0
Views: 103
Reputation: 81976
It appears that you are implementing a table based integer to roman numbers system. You just happen to be implementing the table in code rather than in data.
Here's what it would look like if we encoded the conversions in an array. We can also simplify the logic by turning every if
statement in your code above, into a while
statement.
#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);
}
Which outputs:
1024 == MXXIV
Upvotes: 5