1. 程式人生 > >C Primer Plus(第6版)第十一章複習題答案

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++;
		}
}