温馨提示:本文翻译自stackoverflow.com,查看原文请点击:c++ - Roman Numerals to Arabic (vinculum)
c c++

c++ - 罗马数字到阿拉伯语(vinculum)

发布于 2020-03-29 21:55:05

我目前正在从事一个将罗马数字转换为阿拉伯数字,反之亦然的项目。我还负责实现诸如vinculum之类的概念,其中如果您在罗马数字上方放置一个小节,则下面的数字将乘以1,000。

我遇到的问题是,我只能从一边进行工作,这意味着:我可以不使用Vinculum而从罗马数字转换为阿拉伯语:例如。I = 1,II = 2但是,当这可行时,我的Vinculum代码不起作用。

这是我的代码片段:

int romanToDecimal(char input[], size_t end) {

int roman = 0;

int vroman = 0;
for (int i = 0; i < strlen(input); ++i)
{
    int s1 = value(input[i]);
    int s2 = value(input[i]);

   if (input[i] == '-')
    {

        for (int j = i - 1; j >= 0; --j)
        {

            roman = (roman + value(input[j]));

        }

        roman *= 1000;



        for (int k = i + 1; k <= strlen(input); k++)
            roman += value(input[k]);

    }
    else
        roman += s1;
}

    return roman;

}

我们使用'-'代替字符顶部的栏,因为我们无法在计算机中轻松地做到这一点。因此IV-将是4000,XI-将是11,000,依此类推...

我知道执行循环的方式导致一些被转换的数字相加两次,因为if(input [i] =='-')一次循环遍历字符串中的每个字符。

好的,所以我的问题基本上是使其运作的逻辑是什么?因此,如果字符串包含“-”,它将把数字乘以1000;如果字符串不包含“-”,那么它将照常转换。现在我相信正在发生的事情是,当"if (input[i] == '-')"为false时,该部分代码仍在运行,当字符串包含'-'时,我怎么不让它完全运行?

查看更多

提问者
J J
被浏览
20
Bob__ 2020-01-31 18:47

发布的代码似乎不完整或至少有一些未使用的变量(例如end,如果它代表字符串的长度,则可以代替以下重复的变量strlen(input))或无意义的s2变量(例如)。

我不了解您的“ Vinculum”实现背后的逻辑,但简单

roman += s1;  // Where s1 = value(input[i]);

解析罗马数字显然是不够的,因为每个符号相对位置很重要。考虑例如“ IV”为4(= 5-1),而“ VI”为6(= 5 +1)。

要解析“减法”表示法,您可以存储部分结果,并将当前数字与前一个数字进行比较。类似于以下内容

#include <stdio.h>
#include <string.h>

int value_of(char ch);

long decimal_from_roman(char const *str, size_t length)
{
    long number = 0, partial = 0;
    int value = 0, last_value = 0;
    for (size_t i = 0; i < length; ++i)
    {
        if (str[i] == '-')
        {
            number += partial;
            number *= 1000;
            partial = 0;
            continue;
        }
        last_value = value;
        value = value_of(str[i]);
        if (value == 0)
        {
            fprintf(stderr, "Wrong format.\n");   
            return 0;
        }
        if (value > last_value)
        {
            partial = value - partial;
        }
        else if (value < last_value)
        {
            number += partial;
            partial = value;
        }
        else
        {
            partial += value;   
        }
    }   
    return number + partial;
}

int main(void)
{
    char const *tests[] = {
        "I", "L", "XXX", "VI", "IV", "XIV", "XXIII-",
        "MCM", "MCMXII", "CCXLVI", "DCCLXXXIX", "MMCDXXI", // 1900, 1912, 246, 789, 2421
        "CLX", "CCVII", "MIX", "MLXVI"                     // 160, 207, 1009, 1066 
    };
    int n_samples = sizeof(tests) / sizeof(*tests);

    for (int i = 0; i < n_samples; ++i)
    {
        long number = decimal_from_roman(tests[i], strlen(tests[i]));
        printf("%12ld %s\n", number, tests[i]);
    }

    return 0;
}

int value_of(char ch)
{
    switch (ch)
    {
        case 'I':
            return 1;
        case 'V':
            return 5;
        case 'X':
            return 10;
        case 'L':
            return 50;
        case 'C':
            return 100;
        case 'D':
            return 500;
        case 'M':
            return 1000;
        default:
            return 0;
    }
}

请注意,前面的代码仅检查错误的字符,而不丢弃诸如“ MMMMMMMMMMIIIIIIIIIIIIIVIV”之类的字符串。认为这只是一个起点,可以随时进行改进。