2010-04-03 48 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