这个程序是我刚刚参加的考试的一部分,我必须写。我只有这么远,无法到达任何地方。这是提示:"写一个测试函数toDecimal(),它将罗马数字(如MMLXVII)转换为它的十进制数表示。使用Main()测试功能。 toDecimal()函数应该有2个参数,罗马数字的字符串数组和辅助函数。该辅助函数将返回罗马数字中使用的每个字母的数值。然后将字符串参数转换为:查看前两个字符,如果第一个字符较大,则转换第一个字符并将其添加到求和中,然后使用第二个值再次调用转换函数并添加两个字符。如果第一个字符小于第二个字符,则从第二个字符中减去第一个字符,并将结果添加到字符串的转换中。没有验证它也会转换像" IC"这样的字符串。 VAlidate字符串争论,如果有错误,请调用错误处理函数。提供至少两个错误处理函数,并使用每个函数测试toDecimal()。一个人可能会让用户纠正,另一个人可能会纠正它。"
I,X,C,M不能连续重复3次以上,D,L,V不能连续重复。我只能从V和X中减去,X只能从L中减去并且C,C只能从D和M中减去.V,L和D永远不能被减去。
我已经失去了大约2天的睡眠时间,尝试用数百种不同的方式使用并违反规则。这是我最接近它的。
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
using namespace std;
bool checker(string roman);
// Adds each value of the roman numeral together
int toDecimal(string, bool* (*function)(string));
int convert(string roman, int i);
int main(){
string roman;
cout << "This program takes a roman numeral the user enters then converts it to decimal notation." << endl;
cout << "Enter a roman numeral: ";
cin >> roman;
transform(roman.begin(), roman.end(), roman.begin(), toupper);
cout << roman << " is equal to " << toDecimal(roman, *checker(roman)) << endl;
}
bool checker(string roman){
int length = roman.length();
for (int count = 0; count < length; count++){
string sub = roman.substr(count, count);
if(sub != "I" || sub != "V" || sub != "X" || sub != "L" || sub != "C" || sub != "D" || sub != "M"){
cout << "Error. Try Again"<< endl;
return false;
}
else if(convert(roman, count) == convert(roman, count-1) && convert(roman, count) == convert(roman, count+1)){
if (convert(roman,count) == 1 || convert(roman,count) == 10 || convert(roman,count) == 100 || convert(roman,count) == 1000)
if(convert(roman, count-1) == convert(roman, count-2) || convert(roman, count+1) == convert(roman, count+2)){
cout << "Error Try again" << endl;
return false;
}
else if (convert(roman,count) == 5 || convert(roman,count) == 50 || convert(roman,count) == 500){
cout << "Error Try again" << endl;
return false;
}
else return true;
}
}
return true;
}
int toDecimal(string s, bool*(checker) (string roman)){
/**map<char, int> roman;
roman['M'] = 1000;
roman['D'] = 500;
roman['C'] = 100;
roman['L'] = 50;
roman['X'] = 10;
roman['V'] = 5;
roman['I'] = 1;*/
checker(s);
int res = 0;
for (int i = 0; i < s.length() - 1; ++i){
int num = convert(s,i);
res += num;
/**if (roman[s[i]] < roman[s[i+1]])
res -= roman[s[i]];
else
res += roman[s[i]];
}
res += roman[s[s.size()-1]];*/}
return res;
}
int convert(string roman, int i){
enum romans {I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000};
int num = 0;
char c = roman[0];
switch(c){
case 'M':
num = M; break;
case 'D':
if(i + 1 != roman.size() && roman[i+1] == 'M'){
num = M - D;break;
}
else
num = D; break;
case 'C':
if(i + 1 != roman.size() && roman[i+1] == 'M' || roman[i+1] == 'D'){
if(roman[i+1] == 'M') num = M - C; break;
if(roman[i+1] == 'D') num = D - C; break;
}
else
num = C; break;
case 'L':
if(i + 1 != roman.size() && roman[i+1] == 'M' || roman[i+1] == 'D' || roman[i+1] == 'C'){
if(roman[i+1] == 'M') num = M - L; break;
if(roman[i+1] == 'D') num = D - L; break;
if(roman[i+1] == 'C') num = C - L; break;
}
else
num = L; break;
case 'X':
if(i + 1 != roman.size() && roman[i+1] == 'M' || roman[i+1] == 'D' || roman[i+1] == 'C'|| roman[i+1] == 'L'){
if(roman[i+1] == 'M') num = M - X; break;
if(roman[i+1] == 'D') num = D - X; break;
if(roman[i+1] == 'C') num = C - X; break;
if(roman[i+1] == 'L') num = C - X; break;
}
num = X; break;
case 'V':
if(i + 1 != roman.size() && roman[i+1] == 'M' || roman[i+1] == 'D' || roman[i+1] == 'C'|| roman[i+1] == 'L' || roman[i+1] == 'X'){
if(roman[i+1] == 'M') num = M - V; break;
if(roman[i+1] == 'D') num = D - V; break;
if(roman[i+1] == 'C') num = C - V; break;
if(roman[i+1] == 'L') num = L - V; break;
if(roman[i+1] == 'X') num = X - V; break;
}
num = V; break;
case 'I':
if ( i + 1 != roman.size() && roman[i + 1] != 'I'){
if(roman[i+1] == 'M') num = M - I; break;
if(roman[i+1] == 'D') num = D - I; break;
if(roman[i+1] == 'C') num = C - I; break;
if(roman[i+1] == 'L') num = L - I; break;
if(roman[i+1] == 'X') num = X - I; break;
}
num =1; break;
}
return num;
}
**我在这里添加了人们的帮助。这是一个显示进度/大会的编辑。
答案 0 :(得分:11)
这是我用来将Roman(小于3999)转换为Integer的代码。您可以检查它是否适用于更大的数字。
int romanToInt(string s) {
map<char, int> roman;
roman['M'] = 1000;
roman['D'] = 500;
roman['C'] = 100;
roman['L'] = 50;
roman['X'] = 10;
roman['V'] = 5;
roman['I'] = 1;
int res = 0;
for (int i = 0; i < s.size() - 1; ++i)
{
if (roman[s[i]] < roman[s[i+1]])
res -= roman[s[i]];
else
res += roman[s[i]];
}
res += roman[s[s.size()-1]];
return res;
}
希望这可以帮到你。
答案 1 :(得分:2)
Annie Kim提供的解决方案有效,但它使用std::map
,对同一个角色多次查询,我没有看到它的原因。
int convert_roman_digit(char d)
{
switch (d)
{
case 'M': return 1000;
case 'D': return 500;
case 'C': return 100;
case 'L': return 50;
case 'X': return 10;
case 'V': return 5;
case 'I': return 1;
default: throw std::invalid_argument("Invalid digit");
}
}
int roman_to_int(const std::string& roman)
{
int result = 0, last_added = 0;
for (auto it = roman.rbegin(); it != roman.rend(); ++it)
{
const int value = convert_roman_digit(*it);
if (value >= last_added)
{
result += value;
last_added = value;
}
else
{
result -= value;
}
}
return result;
}
警告:该函数乐意接受一些无效输入(例如IMM
),包括“否定”数字(例如IIIIIIIIIIIIIX
),没有溢出检查,并且它会抛出。随意改进它。
答案 2 :(得分:0)
int romanToInt(string s)
{
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;
int num = 0, prev = 0, curr;
for (int i = s.length() - 1; i >= 0; i--)
{
curr = roman[s[i]];
num += (curr >= prev ? 1 : -1) * curr;
prev = curr;
}
return num;
}