1. 程式人生 > 實用技巧 >c語言程式設計第五版課後答案譚浩強 第八章課後答案

c語言程式設計第五版課後答案譚浩強 第八章課後答案

c語言程式設計第五版課後答案譚浩強習題答案

第八章 善於利用指標

本章習題均要求使用指標方法處理。

1. 輸入3個整數,要求按由小到大的順序輸出。

解題思路: 先獲取到三個變數的地址,然後獲取三個資料,通過指標進行比較轉換即可

答案:

#include <stdio.h>

void swap(int *p_a, int *p_b)
{
	int temp = *p_a;
	*p_a = *p_b;
	*p_b = temp;
}
int main()
{
	int a, b, c, *p_a = &a, *p_b = &b, *p_c = &c;	 // 獲取每個變數空間的地址 
	printf("Please enter three numbers:");
	scanf_s("%d%d%d", p_a, p_b, p_c);
	if (*p_a > *p_b) {
		swap(p_a, p_b);//通過指標進行指向空間內的資料交換
	}
	if (*p_a > *p_c) {
		swap(p_a, p_c);
	}
	if (*p_b > *p_c) {
		swap(p_b, p_c);
	}
	printf("%d %d %d\n", *p_a, *p_b, *p_c);
	system("pause");
	return 0;
}

2. 輸入3個字串,要求按由小到大的順序輸出。

解題思路: 字串的比較可以使用strcmp函式,返回值>0表示大於,返回值小於0表示小於,返回追等於0表示相同。其他的比較排序思路與數字的排序交換沒有區別,逐個進行比較先找出最大的,然後找出第二大的。

答案:

#include <stdio.h>
int main()
{
	char str[3][32]; 
	char *p[3];
	printf("Please enter three strings:");
	for (int i = 0; i < 3; i++) {
		p[i] = str[i];
		scanf_s("%s", p[i], 32);//後邊的數字限制緩衝區邊界,防止緩衝區溢位訪問越界
	}
    //讓p[0]和p[1]/p[2]分別進行比較,找出最大的字串,i+1之後,則讓p[1]和p[2]進行比較,找出第二大
    //i迴圈總個數-1次,最後一個是不需要比較的
	for (int i = 0; i < 2; i++) {
		for (int j = i + 1; j < 3; j++) { 
			if (strcmp(p[i], p[j]) > 0) {
				char *tmp = p[i]; p[i] = p[j]; p[j] = tmp;
			}
		}
		
	}
	printf("%s %s %s\n", p[0], p[1], p[2]);
	system("pause");
	return 0;
}

3. 輸入10個整數,將其中最小的數與第一個數對換, 把最大的數與最後一個數對換。

寫3個函式:

①輸人10個數;

②進行處理;

③輸出10個數。

解題思路: 在進行數值逐個比較的同時找到最小值的空間地址以及最大值的空間地址,使用這兩個空間中的資料最終與第一和最後資料進行對換即可。

答案:

#include <stdio.h>

void input(int *arry, int len)
{
	for (int i = 0; i < len; i++) {
		scanf_s("%d", &arry[i]);
	}
}
void print(int *arry, int len)
{
	for (int i = 0; i < len; i++) {
		printf("%d ", arry[i]);
	}
	printf("\n");
}
void handle(int *arry, int len)
{
	int max_num = arry[0], min_num = arry[0];
	int *p_max = NULL, *p_min = NULL;
	for (int i = 1; i < len; i++) {
		if (min_num > arry[i]) {//逐個比對後找出最小值
			min_num = arry[i];
			p_min = &arry[i];	//逐個比對後找到最小值的空間地址
		}
		if (max_num < arry[i]) {//逐個比對後找出最大值
			max_num = arry[i];
			p_max = &arry[i];   //逐個比對後找到最大值的空間地址
		}
	}
	int tmp;
	tmp = *p_min; *p_min = arry[0]; arry[0] = tmp;  //最小值與第一個資料交換
	tmp = *p_max; *p_max = arry[len - 1]; arry[len - 1] = tmp;//最大值與最後一個數據交換
}
int main()
{
	int arry[10];
	printf("Please enter ten nums:");
	input(arry, 10);
	handle(arry, 10);
	print(arry, 10);
	system("pause");
	return 0;
}

4. 有n個整數,使前面各數順序向後移m個位置,最後m個數變成最前面m個數,見圖8.43。 寫一函式實現以上功能,在主函式中輸人n個整數和輸出調整後的n個數。

解題思路: 找出倒數第m個數據,從這裡開始儲存倒數第m位置的資料,因為倒數第m位置的資料要放到陣列最前方,將m之前的資料向後偏移一位,然後將陣列第一個位置的資料替換為儲存的m位的資料,逐個往後遞增即可。

答案:

#include <stdio.h>
void move(int *arry, int n, int m)
{
	int end_idx = n - m;//找到倒數第m個數據的位置,也就是要移動到陣列首部的資料的起始位置
	for (int i = 0; i < m; i++) {
		int *p = arry + end_idx + i;//從倒數第m個數據的位置開始逐漸向後偏移直到陣列尾部
		int tmp = *p;//獲取到這個位置的值,用於陣列前邊資料向後偏移1位之後,向陣列第i位賦值
		for (int j = end_idx + i; j > i; j--) {//從第i位開始逐個向後偏移一位
			*p = *(p - 1);
			p--;
		}
		*(arry + i) = tmp;//陣列的前第i個數字逐個替換為後邊被覆蓋的值
	}
}
int main()
{
	int number[32], n, m, i;
	printf("Please enter the number of numbers: ");
	scanf_s("%d", &n);//先確定要輸入多少個數字
	printf("Please enter %d numbers: ", n);
	for (i = 0; i < n; i++) {
		scanf_s("%d", &number[i]);//輸入指定個數的數字
	}
	printf("Number of positions to move: ");
	scanf_s("%d", &m);//確定要向後移動多少個位置
	move(number, n, m);
	for (i = 0; i < n; i++) {
		printf("%d ", number[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

5. 有n個人圍成一圈,順序排號。從第1個人開始報數(從1到3報數),凡報到3的人退出圈子,問最後留下的是原來第幾號的那位。

解題思路: 從第一個人開始,逐個報數,誰報3就退出,並且重置報數,直到最後一個人後,又重新從第一個人繼續報數,直到最終只剩一個人的時候退出即可。

答案:

#include <stdio.h>
int main()
{
	int people[128], n;
	printf("Please input how many people: ");
	scanf_s("%d", &n);
	for (int i = 0; i < n; i++) {
		people[i] = i + 1; //對每個人順序排號
	}
	int remain = n;
	int num_off = 0;
	int *p = NULL;
	while (remain > 1) {
		p = people;
		while (p != people + n) { // 每次從第一個位置開始,直到最後一個位置,報數是一直遞增的
			if ((*p) != 0) {//若這個位置人還在
				num_off++; //則報數
				if (num_off == 3) {//否則當前的人即將要報的數字是3
					*p = 0;  //則剔除這個人
					num_off = 0; //並且重新開始計數,下邊會++,所以是從1開始報數
					remain--;//剩餘人數-1
				}
			}
			p++;
		}
	}
	for (int i = 0; i < n; i++) {
		if (people[i] != 0) {
			printf("Serial number of the remaining person:%d\n", people[i]);
		}
	}

	printf("\n");
	system("pause");
	return 0;
}

6. 寫一函式,求一個字串的長度。在main函式中輸入字串,並輸出其長度。

解題思路: 字串以\0作為結尾,則從第一個字元開始向後移動遇到\0認為字串結束。

答案:

#include <stdio.h>
int mystrlen(char *str)
{
	int len = 0;
	char *ptr = str;
	while (*ptr != '\0') {
		ptr++;
		len++;
	}
	return len;
}
int main()
{
	char buf[1024];
	printf("Please enter a string: ");
	scanf_s("%s", buf, 1024);
	printf("string len:%d\n", mystrlen(buf));
	system("pause");
	return 0;
}

7. 有一字串,包含n個字元。寫一函式,將此字串中從第m個字元開始的全部字元複製成為另一個字串。

解題思路: 當字串指標移動到源字串的第m位時,則開始向另一個緩衝區中寫入剩下的資料

答案:

#include <stdio.h>
#include <string.h>

int main()
{
	char buf1[1024], buf2[1024];
	printf("Please enter a string: ");
	scanf_s("%s", buf1, 1024);
	int m;
	printf("Please enter a location to start copying: ");
	scanf_s("%d", &m);
	if (m < 0 || m > strlen(buf1)) {//檢測輸入的位置是否合法
		printf("Illegal location entered\n");
		return -1;
	}
	char *ptr1 = buf1 + m; // 從第m個位置開始複製新資料
    char *ptr2 = buf2;
	while (*ptr1 != '\0') {
		*ptr2++ = *ptr1++;
	}
	*ptr2 = '\0';//不要忘了字串結尾標誌
	printf("%s\n", buf2);
	system("pause");
	return 0;
}

8. 輸入一行文字,找出其中大寫字母、小寫字母、空格、數字以及其他字元各有多少。

解題思路: 字元可以直接進行比較,但是要注意字串中的數字是字元數字,必須以字元的形式比較,也就是加上單引號

答案:

#include <stdio.h>
#include <string.h>

int main()
{
	char buf[1024];
	printf("Please enter a string: ");
	gets_s(buf, 1024);
	int upper_count = 0, lower_count = 0, digit_count = 0, space_count = 0, other_count = 0;
	char *ptr = buf;
	while (*ptr != '\0') {
		if (*ptr >= 'A' && *ptr <= 'Z') { //大寫字母
			upper_count++;
		}else if (*ptr >= 'a' && *ptr <= 'z'){//小寫字母
			lower_count++;
		}else if (*ptr >= '0' && *ptr <= '9') {//數字字元
			digit_count++;
		}else if (*ptr== ' ') {//空格字元
			space_count++;
		}else { //其他字元
			other_count++;
		}
		ptr++;
	}
	printf("upper:%d; lower:%d; digit:%d; space:%d; other:%d\n", \
		upper_count, lower_count, digit_count, space_count, other_count);
	system("pause");
	return 0;
}

9. 寫一函式,將一個3x3的整型矩陣轉置。

解題思路: 矩陣轉置就是行變列,列變行,說白了就是 arry[i][j] 轉換為 arry[j][i] ; 但是需要注意的是,

一. 因為行列個數可能並非相同,轉換後行數或者列數變多了或者變少,因此不能直接轉換。需要重新申請空間儲存轉換後的資料。

二. 二維陣列是線性扁平化儲存的,無法確定列數的情況下傳參後,在函式中使用時需要頭指標向後偏移 列數*第n行 才能訪問到第n行的資料。例如在函式中訪問 arry[i][j] ,需要通過arry + col_num*i + j 方式進行訪問。

答案:

#include <stdio.h>
int **transform(int **arry, int row_count, int col_count)
{
	//列變行,行變列,則行的個數是以前列的個數,列的個數是以前行的個數
	int **p = NULL;
    //矩陣中有多少行,取決於以前有多少列,然後申請地址空間
	p = (int **)malloc(sizeof(int *) * col_count);
	for (int i = 0; i < col_count; i++) {
        //一行中有多少列,取決於以前有多少行,然後申請空間
		p[i] = (int *)malloc(sizeof(int) * row_count); 
	}
	for (int i = 0; i < col_count; i++) {
		for (int j = 0; j < row_count; j++) {
            //二維陣列的儲存是扁平化的, 訪問第j行第i列的資料,應該是 arry + j*列數 + i
            //j是新陣列的列,但是是源陣列的行
			p[i][j] = (arry + col_count * j)[i]; 
		}
	}
	return p;
}
int main()
{
	int arry[3][4];
	printf("Please enter a 3 x 4 matrix: \n");
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 4; j++) {
			scanf_s("%d", &arry[i][j]);
		} 
	}
	int **p = transform(arry, 3, 4);
	printf("\n");
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 3; j++) {
			printf("%d ", p[i][j]);
		}
		free(p[i]); // 釋放二級指標中每個一級指標申請的空間
		printf("\n");
	}
	free(p);//釋放總體二級指標的空間
	system("pause");
	return 0;
}

10. 將一個5x5的矩陣中最大的元素放在中心,4個角分別放4個最小的元素(順序為從左到右,從上到下依次從小到大存放),寫一函式實現之。用main函式呼叫。

解題思路: 將二維陣列當做一維陣列進行處理比較方便,而二維陣列本身就是扁平化儲存,所以直接使用首地址即可。

先遍歷找到最大值,將其與中間數字交換,而中間數字的下標就是數字總數除以2;

其次尋找四次最小值,每次尋找的時候將最小值的下標記錄起來,前提是這個數字如果已經是選中的最小數字之一,則需要跳過,也就是隻跟剩餘的數字作比較。(第二次開始遍歷找最小數字的時候,千萬不能與第一個最小數進行比較,否則永遠都只有一個最小數)。

答案:

#include <stdio.h>
#include <string.h>
void transform(int *arry, int col_row)
{
    //找到最大值
	int max = arry[0], max_idx;
	for (int i = 0; i < col_row * col_row; i++) {
		if (max < arry[i]) max = arry[i];//找出最大數
		max_idx = i;
	}
	//行列相乘得到總數量,除以2後加1則為中心點(暫時不考慮偶數的情況)
	int center_idx = (col_row * col_row) / 2;
	int tmp = arry[cen ter_idx]; arry[center_idx] = arry[max_idx]; arry[max_idx] = tmp;

	//找到四個最小值
	int min_idx[4];
	for (int i = 0; i < 4; i++) {//迴圈4次獲取到最小值
		int min_tmp = arry[col_row * col_row - 1];
		for (int j = 0; j < col_row * col_row; j++) {//遍歷所有資料,逐個比較獲取最小值
			int k = 0;
			for (; k < i; k++) {//但是要注意如果某個下標的資料已經是獲取過的最小值,則不能進行判斷(因為這個肯定是最小的)
				if (j == min_idx[k]) break;
			}
			if (k != i) { continue; }//k和i不同表示j這個座標已經是找到的最小的幾個數字之一,則找下一個判斷
			if (min_tmp > arry[j]) { // 相當於在剩下的數中找到最小的那個數字
				min_tmp = arry[j];
				min_idx[i] = j; //並且記錄這個數字的位置
			}
		}
	}
    int change_idx[4];//先計算四個角的下標,便於後邊進行交換
	change_idx[0] = 0;//第一個要置換的資料的下標,也就是左上角
	change_idx[1] = col_row - 1;//第二個要置換的資料的下標,也就是右上角
	change_idx[2] = col_row * (col_row - 1);//第一個要置換的資料的下標,也就是左下角
	change_idx[3] = (col_row * col_row) - 1;//第一個要置換的資料的下標,也就是右下角
	for (int i = 0; i < 4; i++) {
		int tmp = arry[change_idx[i]]; arry[change_idx[i]] = arry[min_idx[i]]; arry[min_idx[i]] = tmp;
	}
	return ;
}
int main()
{
	int arry[5][5];
	printf("Please enter a 5x5 matrix: \n");
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			scanf_s("%d", &arry[i][j]);
		} 
	}
	transform(*arry, 5);//將二維陣列當做一維陣列傳入處理,並且傳入行列數
	printf("\n");
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			printf("%d ", arry[i][j]);
		}
		printf("\n");
	}
	system("pause");
	return 0;
}

11. 在主函式中輸入10個等長的字串。用另一函式對它們排序。然後在主函式輸出這10個已排好序的字串。

解題思路: 排序方式與數字比較沒什麼不同,先遍歷比較找出最大的字串,與第一個字串進行交換,然後剩下的進行比較找出最大的字串與第二個交換....

需要主機的就是字串的比較採用strcmp介面,返回值大於0表示第一個字串大於第二個字串

答案:

#include<stdio.h>
#include<string.h>
void sort(char s[10][32])
{
	int i, j;
	for (i = 0; i < 10; i++){
		for (j = i; j < 10; j++){
			if (strcmp(s[i], s[j])> 0){
				char tmp[32];
				strcpy_s(tmp, 32, s[i]);
				strcpy_s(s[i], 32, s[j]);
				strcpy_s(s[j], 32, tmp);
			}
		}
	}
}
int main()
{
	char str[10][32];
	printf("Please enter ten strings:\n");
	for (int i = 0; i < 10; i++){
		scanf_s("%s", str[i], 32);
	}
	sort(str);
	printf("\n");
	for (int i = 0; i < 10; i++){
		printf("%s\n", str[i]);
	}
	system("pause");
	return 0;
}

12. 用指標陣列處理上一題目,字串不等長。

解題思路: 與數字的比較沒什麼區別,只不過需要採用strcmp進行字串的大小比較,使用指標實現需要在最早接收資料的時候就採用字串指標陣列,這樣的好處在於指標的指向可以直接通過賦值進行改變,而指標陣列中的字串的順序只需要交換不同字串的地址就可以實現

答案:

#include<stdio.h>
#include<string.h>
void sort(char *s[10])
{
	int i, j;
	for (i = 0; i < 10; i++){
		for (j = i; j < 10; j++){
			if (strcmp(s[i], s[j])> 0){
				char *tmp = s[i]; //指標的好處在於直接通過賦值可以改變指向
				s[i] = s[j];  //只要交換了字串的地址就實現了字串的交換
				s[j] = tmp;//因此通過指標指向的交換就能夠實現陣列中字串的排序
			}
		}
	}
}
int main()
{
	char *str[10];
	printf("Please enter ten strings:\n");
	for (int i = 0; i < 10; i++) {
		str[i] = malloc(32);//為每一個指標分配空間
		scanf_s("%s", str[i], 32);
	}
	sort(str);
	printf("\n");
	for (int i = 0; i < 10; i++){
		printf("%s\n", str[i]);
        free(str[i]);
	}
	system("pause");
	return 0;
}

13. 寫一個用矩形法求定積分的通用函式,分別求$\int_0^1 sinxdx, \quad \int_0^1 cosxdx, \quad \int_0^1 e^xdx,$ ,說明: sin,cos,exp 函式已在系統的數學函式庫中,程式開頭要用#include <math. h>。

解題思路:

矩形法,學過高等數學就知道化曲為直的思想。將定積分化為多個函式連續的和。基本思想是將區間[a,b]化成n等分,當n越大的時候結果越準確。圖形化成一小塊一小塊的矩形。底邊長都為(b-a)/n.高為每個等分點的函式值。然後將每個矩形的面積相加即為所求。

因為被分成n等分,就可以認為每一等分是一個矩形,那麼每一矩形的面積為: 每一個矩形面積為:

Sn=f(x)(b-a)/n ;總面積為:S=S1+S2+…+Sn;具體計算過程根據公式套即可

這裡主要在於函式指標的應用,將函式作為引數傳遞給另一個函式,在另一個函式中進行呼叫的方式向外提供統一介面,而介面內的處理方式隨著傳入的函式而不同。

答案:

#include<stdio.h>
#include<math.h>

double integral(double(*handler)(double), double a, double b, int n)
{
	double i,s = 0;
	double h = (b - a) / n;
	for (i = a; i <= b; i += h){
		s += handler(i) * h;
	}
	return s;
}
int main()
{
	double a, b;
	int n = 200000; // 區間劃分個數
	int func_idx; // 計算函式選擇id
	printf("Please enter the lower and upper limit of integration:");
	scanf_s("%lf %lf", &a, &b);
	printf("Please enter specific calculation function(1-sin/2-cos/3-exp): ");
	scanf_s("%d", &func_idx);
	switch (func_idx) {
		case 1:printf("The integral of sin(x) is:%lf\n", integral(sin, a, b, n)); break;
		case 2:printf("The integral of cos(x) is:%lf\n", integral(cos, a, b, n)); break;
		case 3:printf("The integral of exp(x) is:%lf\n", integral(exp, a, b, n)); break;
		default:
			printf("function id error\n");
			return -1;
	}
	system("pause");
	return 0;
}

14. 將n個數按輸入時順序的逆序排列,用函式實現。

解題思路: 定義兩個指標,一個指向陣列頭部,一個指向陣列尾部,頭部每次+1,尾部每次-1;則在頭部小於尾部的情況下進行資料交換即可。

答案:

#include<stdio.h>
#include<math.h>

void reorder(int *arry, int n)
{
	int *start = arry;
	int *end = arry + n - 1;
	for (; start < end; start++, end--) {
		int tmp = *start;
		*start = *end;
		*end = tmp;
	}
	return;
}

int main()
{
	int arry[10];
	printf("Please enter ten numbers:");
	for (int i = 0; i < 10; i++) {
		scanf_s("%d", &arry[i]);
	}
	reorder(arry, 10);
	printf("\n");
	for (int i = 0; i < 10; i++) {
		printf("%d ", arry[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

15. 有一個班4個學生,5門課程。

①求第1門課程的平均分;

②找出有兩門以上課程不及格的學生,輸出他們的學號和全部課程成績及平均成績;

③找出平均成績在90分以上或全部課程成績在85分以上的學生。

分別編3個函式實現以上3個要求。

解題思路: 4個學生,5門課程就是一個4x5的二維陣列,

  1. 求第一門課的平均分,就是將第0列資料相加除以學生人數
  2. 遍歷每個學生的成績,判斷不及格次數,若大於2則輸出資訊即可
  3. 統計每個學生總成績,以及對每門課程成績進行判斷即可

答案:

#include<stdio.h>
#include<math.h>

float avg(int arry[][5], int n)
{
	float sum = 0;
	for (int i = 0; i < n; i++) {
		sum += arry[i][0];
	}
	printf("Average of course 1:%f\n", (sum / n));
	return (sum / n);
}
void fail(int arry[][5], int n)
{
	printf("Information on students who fail in more than two courses: ");
	for (int i = 0; i < n; i++) {
		int sum = 0, fail_count = 0;
		for (int j = 0; j < 5; j++) {
			if (arry[i][j] < 60) {
				fail_count++;
			}
		}
		if (fail_count <= 2) {
			continue;
		}
		printf("seq:%d ", i + 1);
		printf("score: ");
		for (int j = 0; j < 5; j++) {
			sum += arry[i][j];
			printf("%d ", arry[i][j]);
		}
		printf("avg:%d ", sum / 5);
		printf("\n");
	}
	return;
}
void excellent(int arry[][5], int n)
{
	int i, j;
	for (i = 0; i < n; i++) {
		int sum = 0, count = 0;
		for (j = 0; j < 5; j++) {
			sum += arry[i][j]; //計算總分用於計算平均分
			if (arry[i][j] > 85) {
				count++; //若每門課都大於85則count總會與j同步++
			}
		}
		if ((sum / 5) > 90 || count == j) {
			printf("Excellent students: %d\n", i + 1);
		}
	}
	return;
}

int main()
{
	int arry[4][5];
	printf("Please enter a 4x5 matrix:\n");
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 5; j++) {
			scanf_s("%d", &arry[i][j]);
		}
	}
	avg(arry, 4);
	fail(arry, 4);
	excellent(arry, 4);
	printf("\n");
	system("pause");
	return 0;
}

16. 輸入一個字串,內有數字和非數字字元,例如:A123x456 17960? ,302tab5876,將其中連續的數字作為一個整數,依次存放到一陣列a中。例如,123放在a[0],456放在a1[1].....統計共有多少個整數,並輸出這些數。

解題思路: 遇到數字字元,則開始統計連續數字字元的個數,統計完畢後,則從右往左每次乘以10(除了個位數)作為數字的單位,最終相加得到數字;然後越過這個數字,從後邊繼續查詢。

答案:

#include<stdio.h>
#include<string.h>

void count_digit(char *str)
{
	int digit[32], count = 0;
	char *ptr = str;
	int i = 0, str_len = strlen(str);
	while (i < str_len) {
		if (*(ptr+i) >= '0' && *(ptr+i) <= '9') {
			int len = 1;//用於統計連續數字的個數
			while (*(ptr + i + len) >= '0' && *(ptr + i+ len) <= '9' && (i+len) < str_len) {//找出從當前位置連續數字的個數
				len++;
			}
			int sum = *(ptr + i + len - 1) - '0';//先獲取個位數的資料
			int unit = 1;//每一位的單位,從十位開始每次乘以10作為單位
			for (int j = len - 2; j >= 0; j--) {//從右往左逐個處理
				unit *= 10;
				sum += (*(ptr + i + j) - '0') * unit;
			}
			digit[count++] = sum;
			i += len; // i需要加上len的長度,越過這個數字,防止一個連續數字中的字元重複處理
			continue;
		}
		i++;
	}
	for (int i = 0; i < count; i++) {
		printf("%d ", digit[i]);
	}
	return;
}
int main()
{
	char buf[1024] = { 0 };
	printf("Please enter a string with numbers:\n");
	gets_s(buf, 1024);
	count_digit(buf);
	printf("\n");
	system("pause");
	return 0;
}

17. 寫一函式,實現兩個字串的比較。即自己寫一個strcmp函式,函式原型為int strcmp(char * p1 ,char * p2); 設p1指向字串s1, p2指向字串s2。要求當s1=s2時,返回值為0;若s1≠s2,返回它們二者第1個不同字元的ASCII碼差值(如"BOY"與"BAD" ,第2個字母不同,0與A之差為79- 65=14)。如果s1>s2,則輸出正值;如果s1<s2,則輸出負值。

解題思路: 使用兩個指標指向兩個字串首部,逐個往後進行比較,不相等的時候則將資料進行相減,作為返回值。

答案:

#include<stdio.h>
#include<string.h>

int mystrcmp(char *str1, char *str2)
{
	char *ptr1 = str1;
	char *ptr2 = str2;
	int res;
	while (*ptr1 != '\0' && *ptr2 != '\0') {
		if (*ptr1 != *ptr2) {
			res = *ptr1 - *ptr2;
			break;
		}
		ptr1++;
		ptr2++;
	}
	if (*ptr1 == '\0' || *ptr2 == '\0') {//注意一個字串到達結尾或者兩個都到達結尾的情況
		res = *ptr1 - *ptr2;
	}
	return res;
}
int main()
{
	char buf1[1024] = { 0 };
	char buf2[1024] = { 0 };
	while (1) {
		printf("Please enter two strings:\n");
		gets_s(buf1, 1024);
		gets_s(buf2, 1024);
		printf("mystrcmp:%d", mystrcmp(buf1, buf2));
		printf("\n");
	}
	system("pause");
	return 0;
}

18. 編一程式,輸入月份號,輸出該月的英文月名。例如,輸人3,則輸出"March" ,要求用指標陣列處理。

解題思路: 首先定義字串指標數字,陣列中每一個元素都存放一個字串指標,每個指標指向不同字串的位置。則輸入月份數字後,根據下標獲取對應月份字串的地址即可

答案:

#include<stdio.h>
int main()
{
	int month;
	char* Month[12] = { "January","February","March","April","May","June",
	"July","August","September","October","November","December" };
	while (1) {
		printf("Please enter the month: ");
		scanf_s("%d", &month);
		if (month < 1 && month>12) {
			printf("Input error, Month should be greater than 0 and less than 12\n");
		}
		printf("%s\n", Month[month - 1]);
	}
	return 0;
}

19.(1) 編寫一個函式new,對n個字元開闢連續的儲存空間,此函式應返回一個指標(地址),指向字串開始的空間。new(n)表示分配n個位元組的記憶體空間。(2)寫一函式free,將前面用new函式佔用的空間釋放。free(p)表示將p(地址)指向的單元以後的記憶體段釋放。

解題思路: 封裝malloc函式申請空間,封裝free函式釋放空間;

答案:

#include <stdio.h>
#include <stdlib.h>

void *mynew(int n)
{
	return malloc(n);
}
void myfree(char *p)
{
	return free(p);
}
int main()
{
	int num;
	char *str = NULL;
	printf("Please enter number: ");
	scanf_s("%d", &num);
	printf("before new p--%p:%s\n", str, str);//申請空間之前,檢視指標的地址和指向空間資料
	str = (char*)mynew(num);
	printf("after new p--%p:%s\n", str, str);//申請空間之後,檢視指標的地址和指向空間資料
	printf("Please enter a string:");
	scanf_s("%s", str, num);
	printf("before free p--%p:%s\n", str, str);//釋放空間之前,檢視指標的地址和指向空間資料
	myfree(str);
	printf("after free p--%p:%s\n", str, str);//釋放空間之後,檢視指標的地址和指向空間資料
	system("pause");
	return 0;
}

20. 用指向指標的指標的方法對5個字串排序並輸出。

解題思路:指向指標的指標其實就是二級指標,使用二級指標的儲存一級指標的地址,讓這個一級指標指向具體的資料空間; 定義一個字串指標陣列包含5個元素,每個元素可以儲存一個字串的首地址,而這個地址指向的是具體的字串資料空間,通過指標訪問實現對指向空間內的字串進行比較排序交換即可。

答案:

#include<stdio.h>
#include<string.h>
void sort(char *s[10])
{
	int i, j;
	for (i = 0; i < 10; i++){
		for (j = i; j < 10; j++){
			if (strcmp(s[i], s[j])> 0){//s[i]儲存的就是一個字串的首地址
				char *tmp = s[i]; //指標的好處在於直接通過賦值可以改變指向
				s[i] = s[j];  //只要交換了字串的地址就實現了字串的交換
				s[j] = tmp;//因此通過指標指向的交換就能夠實現陣列中字串的排序
			}
		}
	}
}
int main()
{
	char *str[5];//定義字串指標陣列,可以分別儲存指向5個字串所在空間首地址
	printf("Please enter five strings:\n");
	for (int i = 0; i < 5; i++) {
		str[i] = malloc(32);//為每一個指標分配空間
		scanf_s("%s", str[i], 32);
	}
	sort(str);
	printf("\n");
	for (int i = 0; i < 5; i++){
		printf("%s\n", str[i]);
        free(str[i]);
	}
    
	system("pause");
	return 0;
}

21. 用指向指標的指標的方法對n個整數排序並輸出。要求將排序單獨寫成一個函式。n個整數在主函式中輸入,最後在主函式中輸出。

解題思路: 指向指標的指標其實就是二級指標,使用二級指標的儲存一級指標的地址,讓這個一級指標指向具體的資料空間。排序就是按照每個元素指標指向空間中的資料進行比對排序即可。

答案:

#include<stdio.h>
#include<string.h>
void sort(int *s[], int len)
{
	int i, j;
	for (i = 0; i < len; i++) {
		for (j = i; j < len; j++) {
            //s[i]就是s指標陣列中第i個元素儲存的一級指標,再次解引用就是最終的資料空間
			if (*(s[i]) > *(s[j])) {
				int tmp = *(s[i]); //指標的好處在於直接通過賦值可以改變指向
				*(s[i]) = *(s[j]);  //只要交換了字串的地址就實現了字串的交換
				*(s[j]) = tmp;//因此通過指標指向的交換就能夠實現陣列中字串的排序
			}
		}
	}
}
int main()
{
	int *integers;
	int count = 0;
	printf("Please enter the number of count: ");
	scanf_s("%d", &count);
	integers = (int*)malloc(count * sizeof(int));//為指標申請count個int空間用於存放輸入的資料
	int **p = (int **)malloc(count * sizeof(int*));//為指標申請count個int*空間用於存放int空間的首地址
	printf("Please enter %d integers: \n", count);
	for (int i = 0; i < count; i++) {
		p[i] = integers + i; //將陣列中每個int元素空間的首地址賦值給指標陣列中的各個元素
		scanf_s("%d", p[i]);//p[i]就儲存時第i個數據的地址,因此這裡不用取地址
	}
	sort(p, count);
	for (int i = 0; i < count; i++) {
		printf("%d ", integers[i]);
	}
	printf("\n");
	free(integers);
	free(p);
	system("pause");
	return 0;
}

c語言程式設計第五版課後答案譚浩強更多答案

c語言程式設計第五版課後答案譚浩強 第七章課後答案
c語言程式設計第五版課後答案譚浩強 第九章課後答案