需要格式化字符串中的字符优先级

时间:2010-04-03 08:17:10

标签: c++ c string roman-numerals

我正在写一个罗马数字转换器,以获得它的乐趣。问题可以解决前面提到的字符优先级。

由于罗马数字不是位置的,即III不代表1 *任何基数^ 2 + 1 *无论基数^ 1 + 1 *什么基数^ 0。

当有人输入XIV时我当然会很难,但我需要确保在这种情况下不添加I,而是减去。我不知道该怎么做。解决这个问题的最佳方法是什么?

我将罗马符号及其各自的十进制数存储在数组中:

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

因此,通过简单地检查数组中的优先级,即如果符号小于下一个符号,即在例如'XIV'中,如果'I',那么对我来说蛮力该死的东西就不会太难了'小于'V',在这种情况下,因为我已经在数组中对它们进行了排序,然后我可以减去该值而不是添加。

但这似乎是一个非常难看的解决方案。还有更好的吗?我正在思考正则表达式的内容(请原谅我,如果这听起来像一个可怕的想法,我还没有使用过RegExp,但听起来它可以做我需要的,那就是确定字符串中的字符。)

2 个答案:

答案 0 :(得分:3)

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

e.g。对于XLIV

从V开始,添加5.
移到I,它更少,所以减去1.
移到L,它更大,加50 移到X,它更少,所以减去10。

你得到44,这是正确的。


或者,您可以将其视为基数10,除了交换1 ... 9与I,II,III,IV ... IX和10 ... 90与X,XX,XXX,LX ... .XL,L等。

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

答案 1 :(得分: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 } ;

然后对于从左到右的每个十进制数字(从数千开始),在上面的查找表中查找'digits [magnitude] [decimal]'并将teh substring附加到teh输出。请注意,没有罗马数字为零,因此简单地省略了零。

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

要了解其工作原理,请参阅Wikipedia: Roman Numerals - Symbols处罗马数字的解释,特别是“符号”部分中的最后一个表格(即进行研究 - 即使您认为自己理解某个主题!)。请注意,大于3999的数字需要非ASCII符号,因此我的表限制为1到3999,但您可以使用Unicode解决方案修复它。

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