Skip to content

Instantly share code, notes, and snippets.

@ButchDean
Last active December 28, 2015 13:39
Show Gist options
  • Save ButchDean/7509437 to your computer and use it in GitHub Desktop.
Save ButchDean/7509437 to your computer and use it in GitHub Desktop.
Code to convert a decimal into its equivalent Roman numeral string.
#include <stdio.h>
#include <string.h>
#define MAX_ROMAN_NUMERALS 100
struct ROMAN_NUMERALS
{
char letter;
int value;
};
const struct ROMAN_NUMERALS rns[] = {{'M', 1000}, {'D', 500}, {'C', 100}, {'L', 50}, {'X', 10}, {'V', 5}, {'I', 1}};
int HowManyOfNumeral(int numeral, int *num);
const char* PostProcessRNs(unsigned char* rnString);
void ModifyRNs(char* subStr, const char* numerals, const unsigned int count, const unsigned int run);
char romanNumerals[MAX_ROMAN_NUMERALS] = {0}; // Roman numeral string.
int main()
{
int numFromArg = 0; // Number to convert.
int idx;
int rnidx;
int stringIndex = 0; // Keep track of string position in romanNumerals.
int howManyNumerals = 0; // How many times each numeral appears in the final string.
int sizeOfRomanNumerals = sizeof(rns) / sizeof(rns[0]);
printf("Enter a number - ");
scanf("%d", &numFromArg);
if(numFromArg > (1000 * MAX_ROMAN_NUMERALS))
{
printf("Numbers only up to %d supported.\n", 1000 * MAX_ROMAN_NUMERALS);
return 0;
}
else
if(numFromArg < 0)
{
puts("Negative numbers not supported.");
return 0;
}
if(numFromArg != 0)
{
for(idx = 0; idx < sizeOfRomanNumerals; idx++)
{
howManyNumerals = HowManyOfNumeral(rns[idx].value, &numFromArg);
// Fill the string.
rnidx = stringIndex;
for(; rnidx < (stringIndex + howManyNumerals); rnidx++)
{
romanNumerals[rnidx] = rns[idx].letter;
}
stringIndex = rnidx;
}
printf("Roman numeral string (after postprocess) is %s\n", PostProcessRNs(romanNumerals));
}
else
{
romanNumerals[0] = 'N';
printf("Roman numeral string (nulla) is %s\n", romanNumerals);
}
return 0;
}
int HowManyOfNumeral(int numeral, int *num)
{
int ratio;
if(*num < numeral)
return 0;
// How many times does the numeral go into num?
ratio = *num / numeral;
// Reduce num by the ratio and continue calculation.
*num -= numeral * ratio;
return ratio;
}
const char* PostProcessRNs(unsigned char* rnString)
{
const char* RN_REPEATERS[] = {"CCCC", "XXXX", "IIII", "LXXXX", "DCCCC", "VIV"};
char* ptrToSubStr;
const unsigned int memoryUpperLimit = (unsigned int)rnString + (MAX_ROMAN_NUMERALS - 1);
// **** Repeating numerals 5x
// Look for 'LXXXX' and convert to 'XC'.
if(ptrToSubStr = strstr(rnString, RN_REPEATERS[3]))
{
ModifyRNs(ptrToSubStr, "XC", memoryUpperLimit - (unsigned int)(ptrToSubStr + 5), 5);
}
// Look for 'DCCCC' and convert to 'CM'.
if(ptrToSubStr = strstr(rnString, RN_REPEATERS[4]))
{
ModifyRNs(ptrToSubStr, "CM", memoryUpperLimit - (unsigned int)(ptrToSubStr + 5), 5);
}
// **** Repeating numerals 4x
// Look for 'CCCC' and convert to 'CD'.
if(ptrToSubStr = strstr(rnString, RN_REPEATERS[0]))
{
ModifyRNs(ptrToSubStr, "CD", memoryUpperLimit - (unsigned int)(ptrToSubStr + 4), 4);
}
// Look for 'XXXX' and convert to 'XL'.
if(ptrToSubStr = strstr(rnString, RN_REPEATERS[1]))
{
ModifyRNs(ptrToSubStr, "XL", memoryUpperLimit - (unsigned int)(ptrToSubStr + 4), 4);
}
// Look for 'IIII' and convert to 'IV'.
if(ptrToSubStr = strstr(rnString, RN_REPEATERS[2]))
{
ModifyRNs(ptrToSubStr, "IV", memoryUpperLimit - (unsigned int)(ptrToSubStr + 4), 4);
}
// Look for 'VIV' and replace with 'IX'.
if(ptrToSubStr = strstr(rnString, RN_REPEATERS[5]))
{
ModifyRNs(ptrToSubStr, "IX", memoryUpperLimit - (unsigned int)(ptrToSubStr + 3), 3);
}
return rnString;
}
void ModifyRNs(char* subStr, const char* numerals, const unsigned int count, const unsigned int run)
{
*subStr = *numerals;
*(subStr + 1) = *(numerals + 1);
memmove(subStr + 2, subStr + run, count);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment