题目
编写函数itob(n, s, b),将整数n转换为以b为底的数,并将转换结果以字符的形式保存到字符串s中。例如itob(n, s, 16)把整数n格式化成十六进制整数保存在s中。
自我解答:
参照练习3-5中的思路,以b为底即代表不断对b求余数,需要注意的一点是考虑十六进制的情况,当余数大于9是用字母a~f来替代。解答如下:
#include <stdio.h>
#include <string.h>
#define abs(x) ((x) < 0 ? -(x) : (x))
void reverse(char s[]);
/* itoa: convert n to characters in s - modified */
void itob(int n, char s[], int b)
{
int i, sign, c;
sign = n; /* record sign */
i = 0;
do /* generate digits in reverse order */
{
c = abs(n % b);
s[i++] = c > 9 ? (c + 'a' - 10) : (c + '0'); /* get next digit */
}
while((n /= b) != 0); /* delete it */
if(sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
void reverse(char s[])
{
int c, i, j;
for(i = 0, j = strlen(s) - 1; i < j; i++, j--)
{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
int main()
{
char s1[20] = {'\0'};
int a = -214748367;
itob(a, s1, 16);
printf("%s\n", s1);
}
运行结果:-ccccccf
参考答案:
/* itob: convert n to characters in s - based b */
void itob(int n, char s[], int b)
{
int i, j, sign;
void reverse(char s[]);
if((sign = n) < 0) /* record sign */
n = -n
i = 0;
do{ /* generate digits in reverse order */
j = n % b; /* get next digit */
s[i++] = (j <= 9) ? j + '0' : j + 'a' - 10;
}while((n /= b) > 0);
if(sign < 0) /* delete it */
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
我们解答这道练习的思路是:先按逆序生成b进制数的每一位数字,再用函数reverse(参见练习1-19)对字符串s中的字符做一次颠倒而得到最终的结果。因为我们要把整数n转换为一个b进制数,所以我们要用 n % b 依次返回一个0到b-1之间的值并把这个值转换为相应的字符保存到字符串s中。然后再用n /= b调整n的值。只要n/b大于零,这一过程就将一直循环下去。
备注:
参考答案中的解答依然是参考了书中关于itoa的例子的代码,依然会存在不能处理最小负整数的情况。自我解答中是参考了 3-4中改进版本的参考答案的基础上的,所以在处理最小负数的情况依然不会有问题。