1

重複の可能性:
整数値をローマ数字の文字列に変換する方法は?

ここで初めて質問します。私は少し取り組んできた地平線上にプロジェクトがあり、ここや他の場所で尋ねられたようなものを見つけることができないようです。目標は、上限のない整数を受け入れ、それをローマ数字に変換することです。整数には実際には上限があるため、サブ文字列に配置された3文字の各セットを示すためにアポストロフィを使用して、整数を解析する前に文字列に変換する必要があります。a)位置に基づいて表示されるものにローマ数字を割り当てるb)アポストロフィを表示して3つの各セットをカウントするループの概念化に問題があります。

これまでのところ:

for(int i=0;i<(int)input.length()/3;i++){
    temp=input.substr(i,3);
    for(int j = 0; j < (int)temp.length(); j++){
        if(j == 0){
            if(temp[j] == '9') cout<<"CM";
            else if(temp[j] >= '8') cout<<"DCCC";
            else if(temp[j] >= '7') cout<<"DCC";
            else if(temp[j] >= '6') cout<<"DC";
            else if(temp[j] >= '5') cout<<"D";
            else if(temp[j] == '4') cout<<"CD";
            else if(temp[j] == '3') cout<<"CCC";
            else if(temp[j] == '2') cout<<"CC";
            else if(temp[j] == '1') cout<<"C";  
        }
        else if(j == 1){
            if(temp[j] == '9') cout<<"XC";
            else if(temp[j] >= '8') cout<<"LXXX";
            else if(temp[j] >= '7') cout<<"LXX";
            else if(temp[j] >= '6') cout<<"LX";
            else if(temp[j] >= '5') cout<<"L";
            else if(temp[j] == '4') cout<<"XL";
            else if(temp[j] == '3') cout<<"XXX";
            else if(temp[j] == '2') cout<<"XX";
            else if(temp[j] == '1') cout<<"X";
        }
        else if(j ==2){
            if(temp[j] == '9') cout<<"IX";
            else if(temp[j] == '8') cout<<"VIII";
            else if(temp[j] == '7') cout<<"VII";
            else if(temp[j] == '6') cout<<"VI";
            else if(temp[j] >= '5') cout<<"V";
            else if(temp[j] == '4') cout<<"IV";
            else if(temp[j] == '3') cout<<"III";
            else if(temp[j] == '2') cout<<"II";
            else if(temp[j] == '1') cout<<"I";
        }
    }
}

数字はそれ自体で十分に表示されますが、ループを右から開始し、入力内の数字の実際の位置を維持しながら、3で左に移動するように指示する方法を理解するのに苦労しています(たとえば、1234 1をCではなくIとして表示します。また、アポストロフィを書き込むためのループを理解する必要があります。

4

2 に答える 2

1

ローマ数字に変換するために私が考えることができる最も簡単な方法は、可能な限り最大の数字/コンボから始めてチェックし、作業を進めることです. コンボを含めて、大きいものから小さいものへとチェックします。たとえば、「XC」は常に「L」の前にチェックされ、「LXXXX」や「LXL」などについて心配する必要はありません。

// This code requires C++11 support.  Namely, initializer lists and type inference.
// If your compiler sucks, there's equivalents for the important stuff.  What really
// really matters is the order of the value=>digits mappings, and the iteration over
// them in the for loop.

#include <vector>
#include <string>
#include <utility>

std::string romanNumeralFor(int n, int markCount = 0) {
    typedef std::pair<int, std::string> valueMapping;
    static std::vector<valueMapping> importantNumbers = {
        {1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"},
        {100,  "C"}, { 90, "XC"}, { 50, "L"}, { 40, "XL"},
        {10,   "X"}, {  9, "IX"}, {  5, "V"}, {  4, "IV"},
        {1,    "I"},
    };

    std::string result;
    bool needMark = false;
    std::string marks(markCount, '\'');
    for (auto mapping : importantNumbers) {
        int value = mapping.first;
        std::string &digits = mapping.second;
        while (n >= value) {
            result += digits;
            n -= value;
            needMark = true;
        }
        if ((value == 1000 || value == 100 || value == 10 || value == 1) && needMark) {
            result += marks;
            needMark = false;
        }
    }
    return result;
}

文字列を数値に変換する場合:

// in C++11
int n = std::stoi(str);

// in C++03
std::istringstream iss(str);
int n;
iss >> n;

そのため、文字列を 3 桁のチャンクに分割し (末尾から開始してください!)、適切なマーク数を指定して渡します。

于 2012-09-07T19:11:33.847 に答える
0

最善の解決策ではありませんが、機能します。

#include <iostream>
#include <map>
#include <algorithm>
#include <string>

void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    if(from.empty())
        return;
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length();
    }
}

int romanNumeralToInt(std::string s) {
    std::map<char,int> romanNum = {
        {'I',1}, {'V',5}, {'X',10}, {'L',50}, {'C',100},
        {'D',500}, {'M',1000}
    };
    //{"IIIII",5}, {"VV",10}, {"XXXXX",50}, {"LL",100}, {"CCCCC",500}, {"DD",1000}
    int g = 0;
    std::sort(s.begin(),s.end());
    if(s.find("IIIII") != std::string::npos)
        replaceAll(s,"IIIII","V");
    if(s.find("VV") != std::string::npos)
        replaceAll(s,"VV","X");
    if(s.find("XXXXX") != std::string::npos)
        replaceAll(s,"XXXXX","L");
    if(s.find("LL") != std::string::npos)
        replaceAll(s,"LL","C");

    for(auto& i : s) {
        if(romanNum[i] != 0)
            g += romanNum[i];
    }
    return g;
}

int main() {
    std::string st = "XXXXXIIIIIVVVXLLD";
    int a = romanNumeralToInt(st);
    std::cout << a;
}

680 を出力します。

于 2012-09-07T18:53:37.380 に答える