如何使用标准C拒绝无效数字时将罗马数字转换为int?
为了这个问题,为了简单起见(没有Unicode,没有乘法原理,没有双减法,没有上拉,没有大数等等),有效的罗马数字由
the regex定义:
^(M{0,3})(D?C{0,3}|CM|CD)(L?X{0,3}|XC|XL)(V?I{0,3}|IX|IV)$ Code example with POSIX 如果我们不需要拒绝无效数字,有许多解决方案可以转换罗马数字,例如: int roman_numeral_value(unsigned char c) { switch(toupper(c)) { case 'I': return 1; case 'V': return 5; case 'X': return 10; case 'L': return 50; case 'C': return 100; case 'D': return 500; case 'M': return 1000; default: return 0; // error } } int roman_numeral_to_int(const char *s,int size) { int total = 0,prev = 0; for (int i = size-1; i >= 0; --i) { // in reverse order int value = roman_numeral_value(s[i]); total += value < prev ? -value : value; // subtract if necessary prev = value; } return total; } It works for valid Roman numerals.但是roman_numeral_to_int()接受正则表达式拒绝的数字,例如IIIII.是否有一个类似的简单跨平台解决方案,不需要 解决方法
使用strcmp()或换句话说,往返字符串.
首先考虑反向问题,数字 – >串. 有许多方法可以有效地将整数转换为罗马数字串.我们称之为: // return false on error due to `value` range error or scant `size` bool roman_int_to_string(char *dest,size_t size,int value); 除了字母案例问题之外,规范罗马数字字符串和int之间存在一对一的关系.只需将源字符串转换为int,然后将int转换为另一个测试字符串.如果这些字符串匹配,我们就有赢家. #define ROMAN_STRING_N 20 int roman_numeral_to_int_with_validate(const char *s,int size,bool *is_canonical) { int value = roman_numeral_to_int(s,size); char test[ROMAN_STRING_N]; *is_canonical = roman_int_to_string(test,sizeof test,value); if (*is_canonical) { if (strcmp(s,test)) { // Or use a case insensitive compare as desired *is_canonical = false; } } return value; } 经验教训:我编写了一个直接验证函数.为了测试它我需要反向roman_int_to_string().随机字符串生成器迅速显示出许多令人惊讶的错误,如“CMC”和“CMCD”以及OP的“IIII”.最后,使用简单的string-to-int和int-to-string函数对然后进行字符串比较是最有弹性的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |