天天看點

C程式設計語言第二版習題3-4問題描述問題分解代碼實作編譯運作

問題描述

在數的反碼表示中,上述的 itoa 函數不能處理最大的負數,即 n 等于-2^(字長-1) 的情況。請解釋其原因。修改該函數,使它在任何機器上運作時都能列印出正确的值。

問題分解

  • 主函數main
  • 核心函數 itoa(n, s)。先來看原文的函數實作:
void itoa(int n, char s[])
{
        int i, sign;
        if((sign = n) < 0){
                n = -n;
        }
        i = 0;
        do{
                s[i++] = n % 10 + '0';
        }while((n /= 10) > 0);
​
        if(sign < 0){
                s[i++] = '-';
        }
        s[i] = '\0';
        reverse(s);
}           

先來分析itoa函數為什麼不能處理最大的負數,我們假設在int資料取值範圍位-128 ~ 127 的機器上,當n = -128時,-n = 128 > 127,此時災難發生了——得到的結果并不是我們想要的字元串。是以,問題處在 if((sign = n) < 0) 這句,那麼我們隻要将其改造一下即可。

代碼實作

#include<stdio.h>
​
void itoa(int n, char s[]);
void itoa2(int n, char s[]);
void reverse(char s[]);
​
int main()
{
        int n = (~0U >> 1) + 1;
        char s[100], s1[100], s2[100];
        printf("The input number is: %d\n", n);
        itoa(n, s);
        printf("The output string of itoa is: %s\n", s);
​
        itoa2(n, s1);
        printf("The output string of itoa2 is: %s\n", s1);
        return 0;
}
​
void itoa2(int n, char s[])
{
    int sign, i;
    sign = n;
    i = 0;
    do {
        s[i++] = ((sign < 0) ?-(n % 10) : n % 10) + '0'; //負數對10求餘仍然是負數
    } while ((n /= 10) != 0);
    if (sign < 0)
        s[i++] = '-';
    s[i] = '\0';
    reverse(s);
}
​
void itoa(int n, char s[])
{
        int i, sign;
        if((sign = n) < 0){
                n = -n;
        }
        i = 0;
        do{
                s[i++] = n % 10 + '0';
        }while((n /= 10) > 0);
​
        if(sign < 0){
                s[i++] = '-';
        }
        s[i] = '\0';
        reverse(s);
}
void reverse(char s[])
{
    int i, j, c;
    for (j = 0; s[j] != '\0'; j++)
        ;
    for (i = 0, j--; i < j; i++, j--)
    {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}           

編譯運作

C程式設計語言第二版習題3-4問題描述問題分解代碼實作編譯運作

由運作結果可看出,原方法得到的結果不是預期的,改造後的得到了正确的結果。

繼續閱讀