C程序设计语言第二版习题3-5

问题描述

编写函数itob(n, s, b) ,用于把整数n转换成以b为基数的字符串并存到字符串s中。例如, itob(n, s, 16) 表示将n转换成16进制数,并存入s中。

问题分解

  • 主函数main
  • 工具函数reverse(s) ,用来逆置字符串
  • 核心函数 itob(n, s, b)。这道题其实也是习题3-4的一个引申了,我们先来回顾3-4 的itoa函数的实现:
void itoa(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);
}

我们知道10进制整数转换成b进制的算法是: 不断用 n 对b进行求余,直到商为0,那么每次求余的结果,从后往前组合一起就是对应的b进制数。因此,itoa 可以看做把整数n转换成10进制数的itob特例,即此时b = 10, 由此我们可以假设itob的实现为:

void itob(int n, char s[], int b)
{
    int sign, i;
    sign = n;
    i = 0;
    do {
        s[i++] = ((sign < 0) ?-(n % b) : n % b) + '0'; //负数对10求余仍然是负数
    } while ((n /= b) != 0);
    if (sign < 0)
        s[i++] = '-';
    s[i] = '\0';
    reverse(s);
}

我们检验一下,当b = 2,8,10 时都是满足的,唯独b = 16时会出个问题,因为n % 16 的结果有可能大于9,大于9的时候应该使用字母表示,而不是数字了,因此我们要针对b=16情况做个改进,改进后的代码请看如下代码实现。

代码实现

#include<stdio.h>
​
void itob(int n, char s[], int b);
void reverse(char s[]);
​
int main()
{
        int n = (~0U >> 1) + 1, b = 16;
        char s[100];
        printf("The input number is: %d\n", n);
        itob(n, s, b);
        printf("The output string is: %s\n", s);
        return 0;
}
​
void itob(int n, char s[], int b)
{
    int sign, i, temp;
    sign = n;
    i = 0;
    do {
      temp = sign < 0 ?  -(n % b) : n % b;
      if(temp > 9){
        s[i++] = temp - 10 + 'a';
      }else{
        s[i++] = temp + '0';
      }
    } while ((n /= b) != 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-5

由运行结果可看出,原方法得到的结果不是预期的,改造后的得到了正确的结果。

上一篇:C程序设计语言第二版习题3-6


下一篇:C程序设计语言第二版习题3-3