【C程序设计语言】第三章-控制流 | 练习

时间:2022-12-13 13:41:01

练习3-2 编写一个函数escape(s, t),将字符串t复制到字符串s中,并在复制过程中将换行符、制表符等不可见字符分别转换为\n、\t等相应可见的转移字符序列。要求使用switch。再编写一个具有相反功能的函数。

void escape(char s[], char t[])
{
int i, j;

for(i=j=0; t[i]!='\0'; ++i)
switch(t[i]){
case '\n':
s[j++] = '\\';
s[j++] = 'n';
break;
case '\t':
s[j++] = '\\';
s[j++] = 't';
break;
default:
s[j++] = t[i];
break;
}
s[j] = '\0';
}

void unescape(char s[], char t[])
{
int i, j;

for(i=j=0; t[i] != '\0'; ++i){
if(t[i] == '\\'){
if(t[++i] == 'n') /* i自增一 */
s[j++] = '\n';
else if(t[i] == 't')
s[j++] = '\t';
else
s[j++] = t[--i]; /* 循环结束时将i减一 */
}else
s[j++] = t[i];
}
s[j] = '\0';
}

练习3-3 编写函数expand(s1, s2),将字符串s1中类似于a-z一类的速记符号在字符串s2中扩展为等价的完整列表abc···xyz。该函数可以处理大小写字母和数字,并可以处理a-b-c、a-z0-9与a-z等类似的情况。作为前导和尾随的字符原样复制

void expand(char s1[], char s2[])
{
char c;
int i, j;

i = j = 0;
while((c = s1[i++]) != '\0')
if(s1[i] == '-' && s1[i+1] >=c){ /* 若等于c,不会被打印 */
++i;
while(c < s1[i]) /* 先判定,不能有等号 */
s2[j++] = c++;
}else
s2[j++] = c;
s2[j] = '\0';
}

练习3-4 在数的对二的补码表示中,我们编写的itoa函数

/* 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); /* 倒置字符串函数 */
}

不能处理最大的负数,即n等于-(2^(字长-1))的情况。请解释原因。修改函数,使它在任何机器上运行时都行打印出正确的值

#define     abs(x)      ((x)<0 ? -(x) : (x))

void itoa(int n, char s[])
{
int sign, i;

sign = n;
i = 0;
do{
s[i++] = abs(n % 10) + '0';
}while((n /= 10) != 0); /* n可以是负数,所以用!= */
if(sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s)
}

关键点:对二的补码所能表示的最大整数只能是(2^(字长-1)-1)
【C程序设计语言】第三章-控制流 | 练习
可见最大整数比最大负数要小1。所以最大的负数 2^(字长-1) 无法通过语句

n = -n;

在改进的itoa中用宏abs取 n % 10的绝对值,从而绕开 2^(字长-1) 无法转换为正数的问题

练习3-5 编写函数itob(n, s, b),将整数n转换为b为底的数,并将转换结果以字符的形式保存到字符串s中。

void itob(int n, char s[], int b)
{
int i, j, sign;

if((sign = n) < 0)
n = -n;
i = 0;
do{
j = n % b;
s[i++] = (j<9) ? j+'0' : j-10+'A';
}while((n /= 10) > 0);
if(sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}

练习3-6 修改itoa函数,使其可以接受三个参数,第三个参数为最小字段宽度。

#define     abs(x)      ((x) < 0 ? -(x) : (x))

void itoa(int n, char s[], int w)
{
int sign, i;

sign = n;
i = 0;
do{
s[i++] = abs(n % 10) + '0';
}while((n /= 10) > 0);
if(sign < 0)
s[i++] = '-';
while(i < w)
s[i++] = ' ';
s[i] = '\0';
reverse(s);
}