罗马数字转整数转换器遇非有效字符时终止计算的问题排查与解决咨询
问题分析与解决方案
你的代码出现问题的核心原因有两个:
1. map的[]操作符会自动插入无效键
当你使用num[str[j+1]]时,如果str[j+1]不在map的键集合中,C++的map会自动插入这个键,并将其值初始化为0。这就导致后续的num.count(str[j])判断失效——因为无效字符已经被插入到map里了,count会返回1,不会触发break。
比如你输入"iittii"转成大写后是"IITTII":
- 当j=1时,你访问
num[str[2]](也就是num['T']),map会自动添加'T'键,值为0。 - 当j=2时,
num.count('T')返回1,不会终止循环,程序会继续处理后续的无效字符,导致sum被错误累加。
2. 未处理字符串越界访问
当j是字符串的最后一个索引时,j+1会超出字符串长度,访问str[j+1]属于未定义行为,可能读取到随机内存值,进一步导致计算错误或程序异常。
修正后的代码
下面是修复后的代码,解决了上述两个问题:
#include <iostream> #include <cctype> #include <map> #include <string> #include <algorithm> using namespace std; int main(int argc, char *argv[]) { // 更简洁的map初始化方式 map<char, int> num = { {'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000} }; string str; while(getline(cin, str)){ int sum = 0; transform(str.begin(), str.end(), str.begin(), ::toupper); // 手动控制j的递增,避免重复操作和越界 for (int j = 0; j < str.length(); ) { // 查找当前字符,不插入新键 auto current_it = num.find(str[j]); if (current_it == num.end()) { // 遇到无效字符,立即终止循环 break; } int current_val = current_it->second; // 检查下一个字符是否存在且不越界 if (j + 1 < str.length()) { auto next_it = num.find(str[j+1]); if (next_it != num.end()) { int next_val = next_it->second; if (current_val < next_val) { sum += next_val - current_val; j += 2; // 跳过已处理的下一个字符 continue; } } } // 处理普通情况:无下一个字符、下一个字符无效,或当前值不小于下一个值 sum += current_val; j += 1; } cout << sum << "\n"; } return 0; }
关键改进点
- 使用
map::find()代替[]操作符:find()不会自动插入无效键,只会返回map::end()表示键不存在,确保break逻辑能正确触发。 - 手动控制循环变量
j的递增:避免在处理特殊组合(如IV)时重复递增,同时确保不会访问超出字符串长度的字符。 - 增加越界检查:在访问
j+1位置的字符前,先判断j+1 < str.length(),避免未定义行为。
测试你输入的"iittii",程序会在遇到第一个'T'时终止,输出结果为2,符合你的预期。
内容的提问来源于stack exchange,提问作者That_Guy989
相关产品推荐
相关产品推荐

