2010-04-03 49 views
3

我目前正在为它的乐趣写一个罗马数字转换器。该问题符合前述的字符优先顺序。由于罗马数字不是位置的,即III不代表1 *任何基数^ 2 + 1 *任何基数^ 1 + 1 *任何基数^ 0。需要在字符串中格式化字符优先级

当然,当有人在XIV中键入内容时,我很难确定在这种情况下我没有被添加,而是被扣除。我不知道如何做到这一点。解决这个问题的最好方法是什么?

我都存储在阵列中的罗马符号和它们各自的十进制数:

const char cRomanArray[] = "IVXLCDM"; 
const int romanArray[] = { 1, 5, 10, 50, 100, 500, 1000 }; 

所以它不会太难,只需检查中的优先级对我来说,暴力破解这该死的东西数组,即如果符号小于下一个符号,即在'XIV'中如果'I'小于'V',在这种情况下,这是因为我已经在数组中排序它们,然后我可以使它会减去值而不是添加。

但这似乎是一个非常丑陋的解决方案。有没有更好的?我正在考虑沿着正则表达式的方向行事(原谅我,如果这听起来像一个可怕的想法,我还没有使用RegExp,但它听起来像它可以做我需要的东西,那就是确定字符串中的字符)

回答

3

从右侧开始。向左移动,只要数值增加(或保持不变),并在减少时减去值。

例如为XLIV

开始在V,添加5
移至I,它的少,所以减去1
移动到L,这是更大的,添加50
移至X,它的少,所以减去10

而你得到44,这是正确的。


或者,也可以与实际I,II,III,IV ... IX和10 ... 90与X把它作为基体10,除了交换1 ... 9,XX,XXX, LX .... XL,L等。

阅读I & V字符,将它们转换为1-9,然后在X &中读取L个字符,将它们转换为10-90,依此类推。

+0

阅读I&V并将它们转换为1-9不适用于IX,是吗? – Gauthier 2010-04-03 08:43:41

+0

糟糕,是的你是对的。我想你可以从右边读,直到它不符合模式,但我的第一个建议是迄今为止最简单的代码。 – 2010-04-03 09:11:50

1

罗马数字在某种意义上是定位的,仅仅是每个位置可以有多个字符代表十进制数字,符号以十进制数量变化,并且不使用作为占位符的零。

因此,使用查找表因此:

// Decimal digit lookup tables 
static const char* thousands[] = { "", "M", "MM", "MMM" } ; 
static const char* hundreds[] = { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" } ; 
static const char* tens[] = { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" } ; 
static const char* units[] = { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" } ; 
static const char** digits[] = { thousands, hundreds, tens, units } ; 

然后,对于每个十进制数从左到右,(从数千开始),查找“位[大小] [十进制]”在上述查找表和将teh子串附加到输出。请注意,没有罗马数字为零,因此省略了零。

因此,例如1234将被翻译为“M”+“CC”+“XXX”+“IV”=“MCCXXXIV”。

要了解其工作原理,请参阅Wikipedia: Roman Numerals - Symbols中罗马数字的具体说明,即“符号”部分中的最后一个表格(即进行研究 - 即使您认为您了解某个主题!)。请注意,大于3999的数字需要非ASCII符号,所以我的表格被限制在1到3999之间,但您可能会用Unicode解决方案来解决这个问题。

一旦完成了这个工作面试一次,我有一个基于上述表完全工作的实现,但省略它,因为你是为了好玩而做它,也许没有乐趣,也许它为你做了它。但是,如果你想要更多的指针或提示,甚至整个解决方案,只需询问。

+0

我认为他的罗马数字 - >十进制,而不是其他方式,但是,这就是你如何做到这一点。 – 2010-04-03 09:10:05

+0

@彼得亚历山大:哦!应该更仔细地阅读帖子。哦,你仍然可以在每个十年中使用这些表格和最大的子串搜索;但这可能是他试图避免的暴力方法。 – Clifford 2010-04-03 14:28:21