使用C++ unordered_map实现罗马数字转整数遇错误求助
我尝试用C++的unordered_map实现罗马数字转整数,想避免使用if-else或switch语句,编写了如下代码:
#include<bits/stdc++.h> using namespace std; int romanToInt(string s) { int result=0; unordered_map <string, int> roman; roman["I"] = 1; roman["V"] = 5; roman["X"] = 10; roman["L"] = 50; roman["C"] = 100; roman["D"] = 500; roman["M"] = 1000; for( int i=0; i < s.length(); i++ ) { result += roman[s[i]]; } return result; } int main(){ cout << romanToInt("XIII"); }
但代码无法正常运行,测试时roman["X"]能输出10,但传入s[i]或s[1]时就失效了。编译器错误信息翻译如下:
983 | operator[](key_type&& __k)
| ^~~~~~~~
d:\appdata\mingw\include\c++\11.2.0\bits\unordered_map.h:983:29: 注意:参数1无法从'__gnu_cxx::__alloc_traits<std::allocator, char>::value_type'(即'char')转换为'std::unordered_map<std::__cxx11::basic_string , int>::key_type&&'(即'std::__cxx11::basic_string &&')
983 | operator[](key_type&& __k)
| ~~~~~~~~~^
错误原因
你的unordered_map键类型声明为string,但遍历字符串时s[i]是char类型,C++无法自动将char隐式转换为string,导致operator[]调用类型不匹配,这就是编译器报错的核心原因。
另外需要注意:罗马数字存在特殊规则——当小值符号出现在大值符号左侧时,要做减法(比如IV=4、IX=9),当前代码仅做简单累加,会导致这类场景计算错误。
修复方案
方案1:修改unordered_map的键类型为char
这是最直接的修改,完美匹配s[i]的类型:
#include<bits/stdc++.h> using namespace std; int romanToInt(string s) { int result=0; unordered_map<char, int> roman; roman['I'] = 1; roman['V'] = 5; roman['X'] = 10; roman['L'] = 50; roman['C'] = 100; roman['D'] = 500; roman['M'] = 1000; for(int i=0; i < s.length(); i++ ) { // 处理特殊减法规则:当前值小于下一个值时,减去当前值 if(i < s.length()-1 && roman[s[i]] < roman[s[i+1]]) { result -= roman[s[i]]; } else { result += roman[s[i]]; } } return result; } int main(){ cout << romanToInt("XIII") << endl; // 输出13 cout << romanToInt("IV") << endl; // 输出4 }
方案2:将char转换为string后访问unordered_map
如果坚持用string作为键类型,可以把s[i]包装成string:
#include<bits/stdc++.h> using namespace std; int romanToInt(string s) { int result=0; unordered_map<string, int> roman; roman["I"] = 1; roman["V"] = 5; roman["X"] = 10; roman["L"] = 50; roman["C"] = 100; roman["D"] = 500; roman["M"] = 1000; for(int i=0; i < s.length(); i++ ) { string key(1, s[i]); // 把char转成string if(i < s.length()-1 && roman[key] < roman[string(1, s[i+1])]) { result -= roman[key]; } else { result += roman[key]; } } return result; } int main(){ cout << romanToInt("XIII") << endl; // 输出13 cout << romanToInt("IX") << endl; // 输出9 }
内容的提问来源于stack exchange,提问作者Preyum Kumar

