^(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 regexec()
.正则表达式匹配使用“严格”规则表示的1..3999范围内的罗马数字.
如果我们不需要拒绝无效数字,有许多解决方案可以转换罗马数字,例如:
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.是否有一个类似的简单跨平台解决方案,不需要pcre_exec()
或其他外部依赖项,适用于有效的罗马数字,仅适用于它们?
首先考虑反向问题,数字 – >串.
有许多方法可以有效地将整数转换为罗马数字串.我们称之为:
// 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 20int 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函数对然后进行字符串比较是最有d性的.
总结以上是内存溢出为你收集整理的如何使用标准C拒绝无效数字时将罗马数字转换为int?全部内容,希望文章能够帮你解决如何使用标准C拒绝无效数字时将罗马数字转换为int?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)