且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将罗马数字转换为Int-输出错误-为什么?

更新时间:2022-12-01 07:45:56

当我从注释中完成内容并稍微调整了代码后,我得到了:

When I done the stuff from my comment and tweaked your code a bit I got this:

//---------------------------------------------------------------------------
      int  roman_ix[256]={-1};
const int  roman_val[]={ 1 , 5 ,10 ,50 ,100,500,1000,0};
const char roman_chr[]={'I','V','X','L','C','D', 'M',0};
//---------------------------------------------------------------------------
int roman2int(char *s)
    {
    int i,x=0,v=0,v0;
    // init table (just once)
    if (roman_ix[0]<0)
        {
        for (i=0;i<256;i++) roman_ix[i]=0;
        for (i=0;roman_chr[i];i++) roman_ix[roman_chr[i]]=i;
        }
    // find end of string
    for (i=0;s[i];i++);
    // proccess string in reverse
    for (i--;i>=0;i--)
        {
        v0=v;                        // remember last digit
        v=roman_val[roman_ix[s[i]]]; // new digit
        if (!v) break;               // stop on non supported character
        if (v0>v) x-=v; else x+=v;   // add or sub
        }
    return x;
    }
//---------------------------------------------------------------------------

我对这些进行了测试:

1776 1776 MDCCLXXVI
1954 1954 MCMLIV
1990 1990 MCMXC
2014 2014 MMXIV
 300  300 CCC

第一个数字是从字符串转换而来的,第二个是它应该是的,最后一个是罗马字符串.

first number is converted from string, second is what it should be and last is the roman string.

如果256个条目表太大,则可以将其缩小到A-Z范围,该范围显着较小,但是需要在代码中再减去一个.也可以对其进行硬编码以摆脱初始化:

If 256 entry table is too big you can shrink it to range A-Z which is significantly smaller but that require one more substraction in the code. It can be also hardcoded to get rid of the initialization:

//---------------------------------------------------------------------------
int roman2int(char *s)
    {
    // init
    int i,x=0,v=0,v0;       // A  B    C    D  E  F  G  H  I  J  K   L     M  N  O  P  Q  R  S  T  U  V  W   X  Y  Z
    const int val['Z'-'A'+1]={ 0, 0, 100, 500, 0, 0, 0, 0, 1, 0, 0, 50, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10, 0, 0 };
    // find end of string
    for (i=0;s[i];i++);
    // process string in reverse
    for (i--;i>=0;i--)
        {
        if ((s[i]<'A')||(s[i]>'Z')) break; // stop on non supported character
        v0=v; v=val[s[i]-'A'];
        if (v0>v) x-=v; else x+=v;
        }
    return x;
    }
//---------------------------------------------------------------------------

当我摆脱了您的temproman1,roman2switch if/else条件,并且代码从第一次编译起就开始工作了...我假设您对它们做了一些可疑的事情(如果在if中迷路了,/else组合缺少一些边缘情况).

As I got rid of your temp and roman1,roman2 and the switch if/else conditions and the code worked from the first compilation ... I am assuming that you are doing something fishy with them (got lost in the if/else combinations missing some edge case).