C Primer Plus(第6版)第十一章复习题答案

11.12复习题

  1. 下面字符串的声明有什么问题?
int main(void)
{
	char name[] = {'F', 'e', 's', 's'};      		//少了‘\0‘
	char name[] = {'F', 'e', 's', 's', '\0'};     	//改正后
	//当然也可以是用字符串字面量进行初始化数组,这种方式比标准初始化方法简便的多
	char name[] = "Fess";
}

  1. 下面的程序会打印什么?
#include <stdio.h>
int main(void)
{
	char note[] = "See you at the snack bar.";
	char * ptr;

	ptr = note;
	puts(ptr);			//See you at the sanck bar.
	puts(++ptr);		//ee you at the sanck bar.
	note[7] = '\0';		
	puts(note);			//See you
	puts(++ptr);		//e you

	return 0;
}

结果,在这里插入图片描述

  1. 下面 程序会打印什么?
#include <stdio.h>
#include <string.h>
int main(void)
{
	char food[] = "Yummy";
	char * ptr;		//顺便提醒一下,永远不要解引用未初始化的指针

	ptr = food + strlen(food);	//ptr指向'\0'
	while (--ptr >= food)		//先递减后使用,直至首地址
		puts(ptr);				//打印结果应该为:
		
	return 0;
}
	y
	my
	mmy
	ummy
	Yummy

猜想结束,我们来验证下:
在这里插入图片描述

#include <stdio.h>
#include <string.h>
int main(void)
{
	char goldwyn[40] = "art of it all ";
	char samuel[40] = "I read p";
	const char * quote = "the way through.";

	strcat(goldwyn, quote);
	strcat(samuel, goldwyn);
	puts(samuel);

	return 0;
}
// 猜测:i read part of it all the way through. 

我们来运行试试看:
在这里插入图片描述
Bingo!

  1. 下面的练习设计字符串、循环、指针和递增指针。首先定义了下面的函数:
#include <stdio.h>
char *pr(char *str)
{
	char *pc;

	pc = str;
	while (*pc)
		putchar(*pc++);
	do {
			putchar(*--pc);
		} while (pc - str);

	return (pc);
}

考虑下面的函数调用:x = pr("Ho Ho Ho!");
a. 将打印什么?
答:Ho Ho Ho!!oH oH oH
b. x是什么类型?
答:指向char类型的指针
c. x的值是什么?
答:'H’的地址
d. 表达式*- -pc是什么意思?与 - -*pc有何不同?
答:相当于 *(- -pc),- -(*pc)的区别,前者是先使用指针解引用后递减指针的值,后者是先解引用指针的值后递减指针指向的地址的值的大小(例如H变为G)
e. 如果用 *- -pc 替换 - -*pc,会打印什么?
答:会打印Ho Ho Ho!没了
原因是:打印完Ho Ho Ho!后pc指向末尾的空字符,此时- -*pc解引用空字符(空字符的值是0)再- -0得到-1,putchar(-1),ASCII码中没有对应的字符,所以不再屏幕上输出
运行结果如图:

在这里插入图片描述
这里的题目翻译有错,查看原英文
What would be printed if *–pc were replaced with *pc-- ?
用 *pc–替换 *–pc会发生什么
分析: pc此时指向末尾的空字符,打印空字符然后判断while循环测试条件继续打印打印!直到打印到o后,pc递减为首元素的地址,此时pc- str为0跳出while循环,
所以打印结果如下图所示:

在这里插入图片描述
f. 两个while循环用来测试什么?
答:第一个入口测试条件while使得当指针指向字符串末尾的空字符时,停止循环体
第二个出口测试条件do while中的条件(pc - str)使得当pc指向字符串首元素时停止循环体

g. 如果pr()函数的参数是空字符串,会怎样?
答:第一个while循环不会打印任何东西。第二个while循环:指针指向空字符前面的位置,将该字节解释成一个字符并打印,重复,永远都不会满足条件pc-str=0(pc==str),所以这个 过程会一直持续下去
运行结果如图:后两行是CodeBlocks下运行自带的
在这里插入图片描述
h. 必须在主调函数中做什么,才能让pr()函数正常运行?
答:必须再主调函数中定义一个指向字符串的指针如:char * pt;并且要给pr()传递一个指向char类型的指针如: pt = pr("String");(Ps:字符常量是指针)

  1. 假设有如下声明
    char sign = '$';
    sign占用多少字节的内存?'$'占用多少字节的内存?"$"占用多少字节的内存?
    答:sign是char类型的变量,char被定义为1个字节,'$'注意字符常量时储存为int类型,所以通常占2或4字节(不同系统)"$"是字符串末尾有空字符,所以占2个字节(一个字节储存’$‘的编码,一个字节储存’\0’的编码)。

  2. 下面的程序会打印出什么?

#include <stdio.h>
#include <string.h>
#define M1 "How are ya, sweetie? "
char M2[40] = "Beat the clock.";
char * M3 = "chat";
int main(void)
{
    char words[80];
    printf(M1);			//这行也打印How are ya, sweetie?
    puts(M1);			//How are ya, sweetie?
    puts(M2);			//Beat the clock.
    puts(M2 + 1);		//eat the clock.
    strcpy(words,M2);	//
    strcat(words, " Win a toy.");
    puts(words);		//Beat the clock Win a toy.
    words[4] = '\0';	
    puts(words);		//Beat
    while (*M3)			
        puts(M3++);		//chat  换行 hat 换行 at 换行 at 换行 t
    puts(--M3);			//t 
    puts(--M3);			//at
    M3 = M1;				
    puts(M3);				//How are ya, sweetie?
    
    return 0;
}
/*
预测打印的结果如下:
How are ya, sweetie?How are ya, sweetie?
Beat the clock.
eat the clock.
Beat the clock. Win a toy.
Beat
chat
hat
at
t
t
at
How are ya, sweetie?
*/

程序运行结果如图:
在这里插入图片描述
8. 下面的程序会打印出什么?

#include <stdio.h>
int main(void)
{
    char str1[] = "gawsie"; // plump and cheerful
    char str2[] = "bletonism";
    char *ps;
    int i = 0;
    
    for (ps = str1; *ps != '\0'; ps++)
    {
        if ( *ps == 'a' || *ps == 'e')	//如果*ps等于字符a或e打印a或e,
            putchar(*ps);
        else							//否则打印该字符ASCII码减一对应的字符
        	(*ps)--;
        putchar(*ps);
    }
    putchar('\n');
    while (str2[i] != '\0' )		//遍历直到末尾
    {
        printf("%c", i % 3 ? str2[i] : '*');//下标是3的倍数打印*字符,否则打印本身*
        ++i;
    }
    
    return 0;
}
/*
预测输出:
faavrhee
*le*on*sm
*/

运行结果如图所示:
在这里插入图片描述

  1. 本章定义的s_gets()函数,用指针表示法代替数组表示法便可减少一个变量i,请改写该函数。
char * s_gets(char * st, int n)
{
	char * ret_val;
	int i = 0;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		while (st[i] != '\n' && st[i] != '\0')
			i++;
		if (st[i] == '\n')
			st[i] = '\0';
		else
			while (getchar() != '\n')
				continues;
	}
	
	return ret_val;
}
用指针表示法改写
char * s_gets(char * st, int n)
{
	char * ret_val ;
	
	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{	
		while (*ret_val != '\n' && *ret_val != '\0')
			ret_val++;
		if (*ret_val == '\n')
			*ret_val = '\0';
		else 
			while (getchar() != '\n')
				continue;
	}			
	return ret_val;
}
  1. strlen()函数接受一个指向字符串的指针作为参数,并返回该字符串的长度。请编写一个这样的函数。
int strlen(const char * st)
{
	int ct = 0;
	
	while (*st++)
		ct++;

	return ct;	
}
  1. 本章定义的s_gets()函数,可以使用strchr()函数代替其中while循环来查找换行符。请改写该函数。
#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n)
{
	char * ret_val;
    char * find;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
	    find = strchr(st, '\n');		//返回'\n'所在的地址
	    if (find)
            *find = '\0';
		else
			while (getchar() != '\n')
				continue;
	}

	return ret_val;
}
  1. 设计一个函数,接受一个指向字符串的指针,返回指向该字符串第1个空字符的指针,或如果未找到空格字符,则返回空指针。
char * strch(char * st)
{	
	while (*st != ' ' && *st != '\0')
		st++;
	if (*st == ' ')
		return st;
	else return null;
}

下面是第二种方案,可以防止函数修改字符串,但是允许使用返回值改变字符串。表达式(char *)string被称为“通过强制类型转换取消const”

#include <stdio.h>	// 提供NULL的定义
char * strblk(const char * st)
{
	while (*st != ' ' &7 *st != '\0')
		st++;
	if (*st == '\0')
		return NULL;
	else
		return (char *)st;
}
  1. 重写程序清单11.21,使用ctype.h头文件中的函数,以便无论用户选择大写还是小写,该程序都能正确答案。
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define SIZE 40
#define ANSWER "GRANT"
char * s_gets(char * st, int n);
void ToUpper(char * st);
int main(void)
{
	char try[SIZE];

	puts("Who is buried in Grant's tomb?");
	s_gets(try, SIZE);

	while (strcmp(try, ANSWER) != 0)
	{
		puts("No, that's wrong. Try again.");
		s_gets(try, SIZE);
	}
	puts("That's right!");
}
char * s_gets(char * st, int n)
{
	char * ret_val;
	int i = 0;

	ret_val = fgets(st, n, stdin);
	ToUpper(ret_val);
	if (ret_val)
	{
		while (ret_val[i] != '\0' && ret_val[i] != '\n')
			i++;
		if (ret_val[i] == '\n')
			ret_val[i] = '\0';
		else
			while (getchar() != '\n')
				continue;
	}

	return ret_val;
}

void ToUpper(char * st)
{
		while (*st)
		{
			*st = toupper(*st);
			st++;
		}
}

猜你喜欢

转载自blog.csdn.net/weixin_42912350/article/details/82990238