gpt4 book ai didi

c - 如何在使用标准 C 拒绝无效数字的同时将罗马数字转换为 int?

转载 作者:太空狗 更新时间:2023-10-29 16:00:52 26 4
gpt4 key购买 nike

什么是正确的Roman numerals may vary .为了简单起见(没有 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 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() 接受被正则表达式拒绝的数字,例如 IIIIII。是否有不需要 pcre_exec() 的类似简单的跨平台解决方案?或其他适用于有效罗马数字且适用于它们的外部依赖项?

最佳答案

为了创建一定程度的规则灵 active ,以下 Roman_string_to_unsigned0() 使用了一个表。

它遵循 strtol() 风格的功能,返回一个结束指针,指示解析停止的位置。反引用并针对 '\0' 进行成功测试。

该函数有一个bool subtractive 参数来控制两种主要类型的罗马数字解析:basic , subtractive .

static const struct Roman_digit {
char ch[3];
bool subtractive;
unsigned char limit;
unsigned char nextdown; // with parse success, offset to next element to try
unsigned value;
} Roman_table[] = {
{ "I", false, 4, 1, 1 }, //
{ "IV", true, 1, 2, 4 }, //
{ "V", false, 1, 2, 5 }, //
{ "IX", true, 1, 4, 9 }, //
{ "X", false, 4, 1, 10 }, //
{ "XL", true, 1, 2, 40 }, //
{ "L", false, 1, 2, 50 }, //
{ "XC", true, 1, 4, 90 }, //
{ "C", false, 4, 1, 100 }, //
{ "CD", true, 1, 2, 400 }, //
{ "D", false, 1, 2, 500 }, //
{ "CM", true, 1, 4, 900 }, //
{ "M", false, 4, 1, 1000 }, //
};
#define Roman_table_N (sizeof Roman_table / sizeof Roman_table[0])

const char *Roman_string_to_unsigned0(unsigned *dest, const char *src, bool subtractive){
*dest = 0;
for (unsigned i = Roman_table_N; i > 0;) {
const struct Roman_digit *digit = &Roman_table[i - 1];
if (!subtractive && digit->subtractive) {
i--;
continue;
}
unsigned limit = digit->limit; // repeat count
if (limit > 1 && subtractive) limit--;
size_t ch_length = strlen(digit->ch);
size_t next_i = i-1;
for (unsigned j=0; j<limit; j++) {
if (strncmp(src, digit->ch, ch_length) == 0) {
*dest += digit->value;
if (*dest < digit->value) { // Overflow detection
return (char*) src;
}
src += ch_length;
next_i = i - digit->nextdown; // With success, maybe skip down the list
} else {
break;
}
}
i = next_i;
}
return (char*) src;
}

注意:不区分大小写尚未编码。空字符串返回 0。通过此代码按从高到低的顺序工作,"XXXMMM" 未通过。

关于c - 如何在使用标准 C 拒绝无效数字的同时将罗马数字转换为 int?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43884046/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com