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語言程序設計第五版課后答案譚浩強 第七章課后答案
c語言程序設計第五版課后答案譚浩強 第九章課后答案


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM