Last active
December 28, 2015 13:39
-
-
Save ButchDean/7509437 to your computer and use it in GitHub Desktop.
Code to convert a decimal into its equivalent Roman numeral string.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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