2013-07-18 3 views
3

이 프로그램은 방금 전에 쓴 시험 중 하나입니다. 나는 단지 이것까지 가지고 있고 어디에도 갈 수 없었다. 여기에 프롬프트가 있습니다 : "테스트 함수를 MMLXVII와 같은 로마 숫자를 10 진수 표현으로 변환하는 Decimal() 함수를 작성하십시오. 함수를 테스트하려면 Main()을 사용하십시오. toDecimal() 함수에는 2 개의 인수가 있어야합니다. 로마 숫자와 도우미 함수를 지원합니다.이 도우미 함수는 로마 숫자에 사용 된 각 문자의 숫자 값을 반환합니다. 그런 다음 문자열 인수를 다음과 같이 변환하십시오. 첫 번째 문자가 더 크면 첫 번째 문자를 합계에 추가 한 다음 두 번째 값을 사용하여 변환 함수를 다시 호출하고 둘 다 추가합니다. 첫 번째 문자가 두 번째 문자보다 작 으면 두 번째 문자에서 첫 번째 문자를 뺀 다음 결과를 문자열의 변환에 추가합니다. "IC"와 같은 문자열도 변환합니다. 문자열 arguement에 오류가 있으면 오류 처리 함수를 호출합니다. 적어도 두 가지 오류 처리 함수를 제공하고 각각에 대해 toDecimal()을 테스트합니다. CT, 다른 하나는 그것을 고칠 수 있습니다. "C++ 로마 숫자를 십진수로 변환

I, X, C, M은 연속해서 3 번 이상 반복 될 수 없다. D, L, V는 절대로 연속해서 반복 될 수 없다. 나는 V와 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; 
} 

** 여기에있는 사람들의 도움을 받았습니다. 이것은 진보/의회를 보여주는 편집입니다.

+2

작동하지 않는 기능은 무엇입니까? –

+0

여러 가지 장소에서'enum' 값을 정의한 다음 실제로는 사용하지 않습니다. –

+0

많은 것들이 작동하지 않습니다. 나는 정말로 그것을 잃어 버렸다. 나는 주석으로 처리 된 것을 위해 로마 숫자 열거 형을 내부적으로 만들었고 다른 열거 형은 "sub"를 비교할 수 있도록했다. 이유가 없기 때문에 – Svanhildr

답변

10

이것은 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; 
} 

희망이 도움이 될 수 있습니다.

+0

안녕하세요, 저는 STL을 배우고 자 열심히 노력하고 있기 때문에 오랫동안 이와 같은 것을 찾고있었습니다. 나는 로마자 형식의 로마자를 반환 할 수 있도록 어떻게 역순으로 문자열 roman (int num)을 할 수 있는지 알고 싶다. 이것은 쉽게 뒤집을 수 있습니까? 단순히 표지판을 뒤집을 수 있습니까? 나는지도와 이중 잠수정에서 길을 잃었습니다. ... –

+0

@JonWeinraub 희망이 링크는 도움이 될 수 있습니다. https://github.com/AnnieKim/LeetCode/blob/master/IntegertoRoman.h –

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; 
} 

주의 할 : 함수 즐겁게 일부 잘못된 입력 "네거티브"번호 (예컨대 IIIIIIIIIIIIIX)를 포함하여 (예컨대 IMM)가 오버 플로우 검사가없고, 그 발생을 받아 들인다. 부담없이 개선하십시오.

관련 문제