Как преобразовать целочисленное значение в римскую цифровую строку?

Как преобразовать целое число в его строковое представление в римских цифрах в C?

Самый простой способ – это, вероятно, создать три массива для сложных случаев и использовать простую функцию, такую ​​как:

// convertToRoman: // In: val: value to convert. // res: buffer to hold result. // Out: n/a // Cav: caller responsible for buffer size. void convertToRoman (unsigned int val, char *res) { char *huns[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; char *tens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; char *ones[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; int size[] = { 0, 1, 2, 3, 2, 1, 2, 3, 4, 2}; // Add 'M' until we drop below 1000. while (val >= 1000) { *res++ = 'M'; val -= 1000; } // Add each of the correct elements, adjusting as we go. strcpy (res, huns[val/100]); res += size[val/100]; val = val % 100; strcpy (res, tens[val/10]); res += size[val/10]; val = val % 10; strcpy (res, ones[val]); res += size[val]; // Finish string off. *res = '\0'; } 

Это будет обрабатывать любое целое число без знака, хотя большие числа будут иметь очень много символов M на передней панели, и вызывающий должен обеспечить, чтобы их буфер был достаточно большим.

После того, как число было уменьшено ниже 1000, это простой поиск по 3 столам, по одному для сотен, десятков и единиц. Например, возьмите случай, когда val равно 314 .

val/100 будет 3 в этом случае, поэтому поиск массива huns даст CCC , тогда val = val % 100 дает вам 14 для поиска tens .

Тогда val/10 будет 1 в этом случае, так что поиск в tens массивов даст X , тогда val = val % 10 дает вам 4 для поиска.

Тогда val будет 4 в этом случае, так что поиск массива даст IV .

Это дает вам CCCXIV для 314 .


Отверстие для проверки переполнения буфера – это простой шаг оттуда:

 // convertToRoman: // In: val: value to convert. // res: buffer to hold result. // Out: returns 0 if not enough space, else 1. // Cav: n/a int convertToRoman (unsigned int val, char *res, size_t sz) { char *huns[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; char *tens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; char *ones[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; int size[] = { 0, 1, 2, 3, 2, 1, 2, 3, 4, 2}; // Add 'M' until we drop below 1000. while (val >= 1000) { if (sz-- < 1) return 0; *res++ = 'M'; val -= 1000; } // Add each of the correct elements, adjusting as we go. if (sz < size[val/100]) return 0; sz -= size[val/100]; strcpy (res, huns[val/100]); res += size[val/100]; val = val % 100; if (sz < size[val/10]) return 0; sz -= size[val/10]; strcpy (res, tens[val/10]); res += size[val/10]; val = val % 10; if (sz < size[val) return 0; sz -= size[val]; strcpy (res, ones[val]); res += size[val]; // Finish string off. if (sz < 1) return 0; *res = '\0'; return 1; } 

хотя в этот момент вы могли бы подумать о реорганизации обработки сотен, десятков и единиц в отдельную функцию, поскольку они настолько похожи. Я оставлю это как дополнительное упражнение.

не используйте предварительно запрограммированную карту для сложных случаев.

 /* roman.c */ #include  /* LH(1) roman numeral conversion */ int RN_LH1 (char *buf, const size_t maxlen, int n) { int S[] = { 0, 2, 4, 2, 4, 2, 4 }; int D[] = { 1000, 500, 100, 50, 10, 5, 1 }; char C[] = { 'M', 'D', 'C', 'L', 'X', 'V', 'I' }; const size_t L = sizeof(D) / sizeof(int) - 1; size_t k = 0; /* index into output buffer */ int i = 0; /* index into maps */ int r, r2; while (n > 0) { if (D[i] <= n) { r = n / D[i]; n = n - (r * D[i]); /* lookahead */ r2 = n / D[i+1]; if (i < L && r2 >= S[i+1]) { /* will violate repeat boundary on next pass */ n = n - (r2 * D[i+1]); if (k < maxlen) buf[k++] = C[i+1]; if (k < maxlen) buf[k++] = C[i-1]; } else if (S[i] && r >= S[i]) { /* violated repeat boundary on this pass */ if (k < maxlen) buf[k++] = C[i]; if (k < maxlen) buf[k++] = C[i-1]; } else while (r-- > 0 && k < maxlen) buf[k++] = C[i]; } i++; } if (k < maxlen) buf[k] = '\0'; return k; } /* gcc -Wall -ansi roman.c */ int main (int argc, char **argv) { char buf[1024] = {'\0'}; size_t len; int k; for (k = 1991; k < 2047; k++) { len = RN_LH1(buf, 1023, k); printf("%3lu % 4d %s\n", len, k, buf); } return 0; } 

вам действительно не нужно объявлять S это должно быть легко понять, почему.

Я думаю, что ValueConverter – один из самых элегантных методов преобразования целого числа в римскую цифру. Я надеюсь, что Данте не слишком злится на то, что я размещаю его код здесь:

 public class RomanNumeralizer : IValueConverter { private static IList _Pairs; static RomanNumeralizer() { var list = new List(); list.Add(new RomanNumeralPair(1000, "M")); list.Add(new RomanNumeralPair(900, "CM")); list.Add(new RomanNumeralPair(500, "D")); list.Add(new RomanNumeralPair(400, "CD")); list.Add(new RomanNumeralPair(100, "C")); list.Add(new RomanNumeralPair(90, "XC")); list.Add(new RomanNumeralPair(50, "L")); list.Add(new RomanNumeralPair(40, "XL")); list.Add(new RomanNumeralPair(10, "X")); list.Add(new RomanNumeralPair(9, "IX")); list.Add(new RomanNumeralPair(5, "V")); list.Add(new RomanNumeralPair(4, "IV")); list.Add(new RomanNumeralPair(1, "I")); _Pairs = list.AsReadOnly(); } private IList PairSet { get { return _Pairs; } } public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return ConvertToRomanNumeral(System.Convert.ToInt32(value)); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return null; } private string ConvertToRomanNumeral(int input) { StringBuilder myBuilder = new StringBuilder(); foreach (RomanNumeralPair thisPair in _Pairs) { while (input >= thisPair.Value) { myBuilder.Append(thisPair.RomanValue); input -= thisPair.Value; } } return myBuilder.ToString(); } } public class RomanNumeralPair { private string _RomanValue; private int _Value; public RomanNumeralPair(int value, string stringValue) { this._Value = value; this._RomanValue = stringValue; } public string RomanValue { get { return this._RomanValue; } } public int Value { get { return this._Value; } } } 
  static string ConvertToRoman(int num) { int d = 0; string result = ""; while (num > 0) { int n = num % 10; result = DigitToRoman(n, d) + result; d++; num = num / 10; } return result; } static string DigitToRoman(int n, int d) { string[,] map = new string[3, 3] { { "I", "V", "X" }, { "X", "L", "C" }, { "C", "D", "M" } }; string result=""; if (d <= 2) { switch (n) { case 0: result = ""; break; case 1: result = map[d, 0]; break; case 2: result = map[d, 0] + map[d, 0]; break; case 3: result = map[d, 0] + map[d, 0] + map[d, 0]; break; case 4: result = map[d, 0] + map[d, 1]; break; case 5: result = map[d, 1]; break; case 6: result = map[d, 1] + map[d, 0]; break; case 7: result = map[d, 1] + map[d, 0] + map[d, 0]; break; case 8: result = map[d, 1] + map[d, 0] + map[d, 0] + map[d, 0]; break; case 9: result = map[d, 0] + map[d, 2]; break; } } else if (d == 3 && n < 5) { while (--n >= 0) { result += "M"; } } else { return "Error! Can't convert numbers larger than 4999."; } return result; } 
Interesting Posts

Попытка разбить строку на две переменные

Есть ли общее ограничение, которое я мог бы использовать для оператора +?

Как создать связь по умолчанию для файлов с неизвестным расширением в Windows 7?

Как начать работу с Jenkins после успешной работы нескольких одновременных восходящих рабочих мест?

Вызов метода экземпляра из метода classа

Как создать полупрозрачное окно в WPF, которое позволяет событиям мыши проходить через

Как разбирать числовую строку, содержащую запятые, в целое число в java?

Самый быстрый способ сериализации и десериализации объектов .NET

Добавить зависимость в Maven

Использование iPhoto без копирования изображений?

Заклинать комментарий / раскол?

Как я могу создать резервную копию всей установки программы, а не просто вручную создавать резервные копии отдельных файлов?

C ++ Статическая инициализация члена (внутри шаблона)

Что случилось с моим пользовательским кабелем LAN?

com.jcraft.jsch.JSchException: UnknownHostKey

Давайте будем гением компьютера.