在 C 程序中,我无法跟踪使用循环生成从 1 到 1000 的罗马数字的代码?

In C program, I am having trouble tracing a code that produces roman numerals from 1 to 1000 using loops?

我正在尝试跟踪一个 C 程序,该程序将整数转换为从 1 到 1000 的字符罗马数字。我不明白这段代码如何将每个数字转换为罗马数字。我认为 romanNum[i++] 增量和临时值正在计算,但我不确定如何计算。我只能追踪循环的范围。

#include <stdio.h>
int main()
{
    int num;
    for (num = 1; num <= 1000 ; ++num) //1000 loop
    {
        int temp = num; //store single values
        char romanNum[1000]; 
        int i = 0; //to increment romanNum[i] //inside because it's getting increment inside the loop
        int j; //for looping separate values
        //1000=M, 500=D, 100=C, 50=L, 10=X, 5=V, 1=I
        while(temp>0) 
        {       
            if(temp>= 1000)//1000 (highest number)=M
            {  
                for(j=0;j<(temp/1000);j++) //0<1 
                romanNum[i++] = 'M'; //1000=M               
            temp = temp - (temp/1000) * 1000; //0
            }
            else if(temp >=500)//999..500
            {   
                if(temp < (500 + 4 * 100))//500..899
                {                   
                    for(j=0;j<(temp/500);j++)
                    romanNum[i++] = 'D';//
                temp = temp - (temp/500) * 500; //0         
                }
                else//900..999
                { 
                    romanNum[i++] = 'C'; 
                    romanNum[i++] = 'M'; 
                temp = temp - (1000-100);  //0
                }
            }
            else if(temp>=100) //499..100
            {   
                if(temp < (100 + 3 * 100))//100..399
                {
                    for(j=0;j<(temp/100);j++)
                    romanNum[i++] = 'C'; //
                temp = temp - (temp/100) * 100;
                }
                else //400..499
                {   
                    romanNum[i++] = 'L';
                    romanNum[i++] = 'D';
                temp = temp - (500-100);
                }
            }
            else if(temp >=50) //99..50
            {
                if(temp < (50 + 4 * 10))//50..89
                {
                    for(j=0;j<(temp/50);j++)
                    romanNum[i++] = 'L';
                temp = temp - (temp/50) * 50;
                }
                else //90..99
                {
                    romanNum[i++] = 'X';
                    romanNum[i++] = 'C';
                temp = temp - (100-10);
                }
            }
            else if(temp >=10)//49..10
            {
                if(temp < (10 + 3 * 10))//10..39
                {
                    for(j=0;j<(temp/10);j++)
                    romanNum[i++] = 'X';
                temp = temp - (temp/10) * 10;//0
                }
                else//40..49
                {
                    romanNum[i++] = 'X';
                    romanNum[i++] = 'L';
                temp = temp - (50-10);
                }
            }
            else if(temp >=5)//9..5
            {
                if(temp < (5 + 4 * 1))//5..8
                {
                    for(j=0;j<(temp/5);j++)
                    romanNum[i++] = 'V';
                temp = temp - (temp/5) * 5;//0
                }
                else//9
                {
                    romanNum[i++] = 'I';
                    romanNum[i++] = 'X';
                temp = temp - (10-1);//0
                }
            }
            else if(temp >=1)//4..1
            {
                if(temp < 4)//1..3
                {               
                    for(j=0;j<(temp/1);j++)
                    romanNum[i++] = 'I';
                temp = temp - (temp/1) * 1;
                }
                else//4
                {   
                    romanNum[i++] = 'I';
                    romanNum[i++] = 'V';
                temp = temp - (5-1);//0
                }
            }
        }
        printf("%d ", num);//1..1000

        for(j=0;j<i;j++)//to print romanNum
        {
            printf("%c",romanNum[j]);//I..M
        }
        printf("\n");
    }//end of 1000 loop

    return 0;

}

这段代码比它需要的更复杂(并且包含一个错误),所以这没有帮助。

通过示例可能会有所帮助。让我们假设 num2798(不会是因为 num 在最外层循环中在 1000 处达到最大值,但我认为这个值将更具说明性)。这将对应于罗马数字 MMDCCXCVIII:

2000 = MM
 700 = DCC
  90 = XC
   8 = VIII

记住 49 很奇怪:

   4 = IV (1 from 5)
  40 = XL (10 from 50)
 400 = CD (100 from 500)

   9 = IX (1 from 10)
  90 = XC (10 from 100)
 900 = CM (100 from 1000)

因此,我们首先将 2798 分配给 temp。首先我们要弄清楚输出中需要多少千('M'):

if(temp>= 1000)//1000 (highest number)=M
{  
  for(j=0;j<(temp/1000);j++) //0<1 
    romanNum[i++] = 'M'; //1000=M      

  temp = temp - (temp/1000) * 1000; //0
}

temp大于等于1000,所以我们进入for循环。 temp/1000给我们2(整数除法给出一个整数结果),所以我们需要写两个'M'romanNum

romanNum[i++] = 'M';  // this line gets executed twice.

所以我们有

romanNum[0] == 'M'
romanNum[1] == 'M'

然后我们从 2798 中减去 2000,在 temp 中留下 798。然后我们检查该结果是否大于或等于 500 ('D'):

else if(temp >=500)//999..500

是,那么我们检查它是否小于 900:

  if(temp < (500 + 4 * 100))//500..899

是的,所以我们只需要发出一个 D:

    for(j=0;j<(temp/500);j++)        // this loop is actually a bit meaningless,
      romanNum[i++] = 'D';           // since temp < 1000 at this point

并从 temp 中减去 500:

temp = temp - (temp/500) * 500;      // again, temp is < 1000, so this
                                     // could be simplified as `temp - 500`

如果大于900,我们将不得不发出CM并从[=34中减去900 =]:

else//900..999
{ 
  romanNum[i++] = 'C'; 
  romanNum[i++] = 'M'; 
  temp = temp - (1000-100);  //0
}

此时 temp298romanNum

romanNum[0] == 'M'
romanNum[1] == 'M'
romanNum[2] == 'D'

现在我们必须计算出剩余的数百个 ('C') 需要进入输出:

else if(temp>=100) //499..100

如果temp小于400,那么我们只需要发出'C':

if(temp < (100 + 3 * 100))//100..399
{
  for(j=0;j<(temp/100);j++)
    romanNum[i++] = 'C'; //
  temp = temp - (temp/100) * 100;
}

在我们的例子中是,所以我们将两个 'C' 写入 romanNum 并从 temp 中减去 200,留下 98

romanNum[0] == 'M'
romanNum[1] == 'M'
romanNum[2] == 'D'
romanNum[3] == 'C'
romanNum[4] == 'C'

否则,我们必须发出 CD(此代码发出 LD,这是不正确的):

else //400..499
{   
  romanNum[i++] = 'L';
  romanNum[i++] = 'D';
  temp = temp - (500-100);
}

应该能够从这里算出余数。同样,4s 和 9s 是特例。

对于它的价值,这段代码可以变得很多更简单:

while ( temp >= 1000 )
{
  romanNum[i++] = 'M';
  temp -= 1000;
}

if ( temp >= 900 )
{
  romanNum[i++] = 'C';
  romanNum[i++] = 'M';
  temp -= 900;
}

if ( temp >= 500 )
{
  romanNum[i++] = 'D';
  temp -= 500;
}

if ( temp >= 400 )
{
  romanNum[i++] = 'C';
  romanNum[i++] = 'D';
  temp -= 400;
}

while ( temp >= 100 )
{
  romanNum[i++] = 'C';
  temp -= 100;
}

if ( temp >= 90 )
{
  romanNum[i++] = 'X';
  romanNum[i++] = 'C';
  temp -= 90;
}

if ( temp >= 50 )
{
  romanNum[i++] = 'L';
  temp -= 50;
}

if ( temp >= 40 )
{
  romanNum[i++] = 'X';
  romanNum[i++] = 'L';
  temp -= 40;
}

while ( temp >= 10 )
{
  romanNum[i++] = 'X';
  temp -= 10;
}

if ( temp >= 9 )
{
  romanNum[i++] = 'I';
  romanNum[i++] = 'X';
  temp -= 9;
}

if ( temp >= 5 )
{
  romanNum[i++] = 'V';
  temp -= 5;
}

it ( temp >= 4 )
{
  romanNum[i++] = 'I';
  romanNum[i++] = 'V';
  temp -= 4;
}

while ( temp >= 1 )
{
  romanNum[i++] = 'I';
  temp--;
}

romanNum[i] = 0;
printf( "%s\n", romanNum );