c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)

你也可以上程序咖(https://meta.chengxuka.com),打开大学幕题板块,不但有答案,讲解,还可以在线答题。

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(1)

本章习题均要求用指针方法处理。

题目1:输入3个整数,按由小到大的顺序输出。

解:

答案代码:

#include <stdio.h> int main() { void swap(int *p1, int *p2); int n1, n2, n3; int *p1, *p2, *p3; printf("input three integer n1,n2,n3:"); scanf("%d,%d,%d", &n1, &n2, &n3); p1 = &n1; p2 = &n2; p3 = &n3; if (n1 > n2) swap(p1, p2); if (n1 > n3) swap(p1, p3); if (n2 > n3) swap(p2, p3); printf("Now,the order is:%d,%d,%d\n", n1, n2, n3); return 0; } void swap(int *p1, int *p2) { int p; p = *p1; *p1 = *p2; *p2 = p; }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(2)

题目2:输入3个字符串,按由小到大的顺序输出。

解:

#include <stdio.h> #include <string.h> int main() { void swap(char *, char *); char str1[20], str2[31], str3[20]; printf("input three line:\n"); gets(str1); gets(str2); gets(str3); if (strcmp(str1, str2) > 0) swap(str1, str2); if (strcmp(str1, str3) > 0) swap(str1, str3); if (strcmp(str2, str3) > 0) swap(str2, str3); printf("Now,the order is:\n"); printf("%s\n%s\n%s\n", str1, str2, str3); return 0; } void swap(char *p1, char *p2) { char p[20]; strcpy(p, p1); strcpy(p1, p2); strcpy(p2, p); }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(3)

输入3行文字,程序把它们按字母由小到大的顺序输出。

题目3:输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。写3 个函数:

①输入 10个数;

②进行处理;

③输出 10 个数。

解:

#include <stdio.h> int main() { void input(int *); void max_min_value(int *); void output(int *); int number[10]; input(number); //调用输入10 个数的函数 max_min_value(number); //调用交换函数 output(number); //调用输出函数 return 0; } //输入10 个数的函数 void input(int *number) { int i; printf("input 10 numbers:"); for (i = 0; i < 10; i ) scanf("%d", &number[i]); } // 交换函数 void max_min_value(int *number) { int *max, *min, *p, temp; max = min = number; //开始时使 max和 min都指向第1个数 for (p = number 1; p < number 10; p ) if (*p > *max) max = p; //若 p指向的数大于max指向的数,就使 max指向p指向的大数 else if (*p < *min) min = p; //若 p指向的数小于min指向的数,就使 min指向p指向的小数 temp = number[0]; //将最小数与第1个数 number[0]交换 number[0] = *min; *min = temp; if (max == number) max = min; //如果 max和 number相等,表示第1个数是最大数,则使 max指向当前的最大数 temp = number[9]; //将最大数与最后一个数交换 number[9] = *max; *max = temp; } //输出函数 void output(int *number) { int *p; printf("Now, they are: "); for (p = number; p < number 10; p ) printf("%d ", *p); printf("\n"); }

分析:关键在 max_min_value 函数,请认真分析此函数。形参 number 是指针,局部变量 max,min和 p都定义为指针变量,max 用来指向当前最大的数,min 用来指向当前最小的数。

number 是第 1 个数 number[0] 的地址,开始时执行 max=min=number 的作用就是使 max 和 min 都指向第 1 个数 number[0] 。以后使 p 先后指向10个数中的第 2~10 个数。如果发现第 2 个数比第 1 个数 number[0] 大,就使 max 指向这个大的数,而 min 仍指向第 1 个数。如果第 2 个数比第. 1个数 number[0] 小,就使 min 指向这个小的数,而 max 仍指向第 1个数。然后使 p 移动到指向第 3 个数,处理方法同前。直到 p 指向第 10 个数,并比较完毕为止。此时 max. 指向 10个数中的最大者,min 指向 10 个数中的最小者。假如原来 10 个数是:

32 24 56 78 1 98 36 44 29 6

在经过比较和对换后,max和 min的指向为

32 24 56 78 1 98 36 44 29 6 ↑ ↑ min max

此时,将最小数 1 与第 1 个数(即 number[0] )32 交换,将最大数 98 与最后一个数 6 交换。因此应执行以下两行:

temp = number[0]; number[0] = *min;*min = temp;//将最小数与第1个数 number[0]交换 temp = number[9]; number[9] = *max;*max = temp;//将最大数与最后一个数交换

最后将已改变的数组输出。

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(4)

但是,有一个特殊的情况应当考虑:如果原来 10 个数中第 1 个数 number[0] 最大,如:

98 24 56 78 1 32 36 44 29 6

在经过比较和对换后,max 和 min 的指向为

98 24 56 78 1 32 36 44 29 6 ↑ ↑ max min

在执行完上面第1行"temp=number[0] ;number[0]=*min;*min=temp;"后,最小数 1 与第 1个数 number[0] 对换,这个最大数就被调到后面去了(与最小的数对调)。

1 24 56 78 98 32 36 44 29 6 ↑ ↑ max min

请注意:数组元素的值改变了,但是 max 和 min 的指向未变,max 仍指向 number[0]。此时如果接着执行下一行:temp= number[9];number[9]=* max;* max= temp; 就会出问题,因为此时 max 并不指向最大数,而指向的是第1个数,结果是将第 1个数(最小的数已调到此处)与最后一个数 number[9] 对调。结果变成:

6 24 56 78 98 32 36 44 29 1

显然就不对了。

为此,在以上两行中间加上一行:

if(max== number)max = min;

由于经过执行"temp= number[0]; number[0]=* min;* min=temp;"后,10 个数的排列为

1 24 56 78 98 32 36 44 29 6 ↑ ↑ max min

max指向第 1 个数,if 语句判别出 max 和 number 相等(即 max 和 number 都指向 number[0] ),而实际上 max 此时指向的已非最大数了,就执行"max=min",使 max 也指向 min 当前的指向。而 min 原来是指向最小数的,刚才与 number[0] 交换,而 number[0] 原来是最大数,所以现在 min 指向的是最大数。执行 max=min 后 max也指向这个最大数。

1 24 56 78 98 32 36 44 29 6 ↑ max,min

然后执行下面的语句:

temp = number[9]; number[9]=*max;* max= temp;

这就没问题了,实现了把最大数与最后一个数交换。

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(5)

读者可以将上面的"if(max==number)max=min;" 删去,再运行程序,输入以上数据,分析一下结果。

也可以采用另一种方法:先找出 10 个数中的最小数,把它和第 1 个数交换,然后再重新找 10 个数中的最大数,把它和最后一个数交换。这样就可以避免出现以上的问题。重写void max_min_value 函数如下:

//交换函数 void max_min_value(int *number) { int *max, *min, *p, temp; max = min = number; //开始时使max和min都指向第1个数 for (p = number 1; p < number 10; p ) if (*p < *min) //若p指向的数小于min指向的数,就使min指向p指向的小数 min = p; temp = number[0]; //将最小数与第1个数 number[0] 交换 number[0] = *min; *min = temp; for (p = number 1; p < number 10; p ) if (*p > *max) //若p指向的数大于max指向的数,就使max指向p指向的大数 max = p; temp = number[9]; //将最大数与最后一个数交换 number[9] = *max; *max = temp; }

这种思路容易理解。

这道题有些技巧,请读者仔细分析,学会分析程序运行时出现的各种情况,并善于根据情况予以妥善处理。

题目4:有n个整数,使前面各数顺序向后移 m 个位置,最后 m 个数变成最前面 m 个数,见图 8.43。写一函数实现以上功能,谜在主函数中输入 n个整数和输出调整后的n个数。

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(6)

解:

答案代码:

#include <stdio.h> int main() { void move(int[20], int, int); int number[20], n, m, i; printf("how many numbers?"); //问共有多少个数 scanf("%d", &n); printf("input %d numbers:\n", n); for (i = 0; i < n; i ) scanf("%d", &number[i]); //输入n 个数 printf("how many place you want move?"); //问后移多少个位置 scanf("%d", &m); move(number, n, m); //调用move 函数 printf("Now,they are:\n"); for (i = 0; i < n; i ) printf("%d ", number[i]); printf("\n"); return 0; } //循环后移一次的函数 void move(int array[20], int n, int m) { int *p, array_end; array_end = *(array n - 1); for (p = array n - 1; p > array; p--) *p = *(p - 1); *array = array_end; m--; if (m > 0) //递归调用,当循环次数m减至为0时,停止调用 move(array, n, m); }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(7)

题目5:有 n 个人围成一圈,顺序排号。从第 1 个人开始报数。(从1到3报数),凡报到3 的 人退出圈子,问最后留下的是原来第几号的那位。

解:N-S图如图8.2所示。

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(8)

答案代码:

#include <stdio.h> int main() { int i, k, m, n, num[50], *p; printf("\ninput number of person: n="); scanf("%d", &n); p = num; for (i = 0; i < n; i ) *(p i) = i 1; //以1至 n 为序给每个人编号 i = 0; // i为每次循环时计数变量 k = 0; // k 为按1,2,3报数时的计数变量 m = 0; // m为退出人数 while (m < n - 1) //当退出人数比 n-1少时(即未退出人数大于1时)执行循环体 { if (*(p i) != 0) k ; if (k == 3) { *(p i) = 0; //对退出的人的编号置为0 k = 0; m ; } i ; if (i == n) //报数到尾后,i 恢复为0了 i = 0; } while (*p == 0) p ; printf("The last one is NO.%d\n", *p); return 0; }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(9)

题目6:写一函数,求一个字符串的长度。在 main 函数中输入字符串,并输出其长度。

解:

答案代码:

#include <stdio.h> int main() { int length(char *p); int len; char str[20]; printf("input string: "); scanf("%s", str); len = length(str); printf("The length of string is %d.\n", len); return 0; } //求字符串长度函数 int length(char *p) { int n; n = 0; while (*p != '\0') { n ; p ; } return (n); }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(10)

题目7:有一字符串,包含 n 个字符。写一函数,将此字符串中从第 m 个字符开始的全部字符复制成为另一个字符串。

解:

答案代码:

#include <stdio.h> #include <string.h> int main() { void copystr(char *, char *, int); int m; char str1[20], str2[20]; printf("input string:"); gets(str1); printf("which character that begin to copy?"); scanf("%d", &m); if (strlen(str1) < m) printf("input error!"); else { copystr(str1, str2, m); printf("result:%s\n", str2); } return 0; } void copystr(char *p1, char *p2, int m) //字符串部分复制函数 { int n; n = 0; while (n < m - 1) { n ; p1 ; } while (*p1 != '\0') { *p2 = *p1; p1 ; p2 ; } *p2 = '\0'; }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(11)

题目8:输入一行文字,找出其中大写字母、小写字母、空格、数字以及其他字符各有多少。

解:

答案代码:

#include <stdio.h> int main() { int upper = 0, lower = 0, digit = 0, space = 0, other = 0, i = 0; char *p, s[20]; printf("input string: "); while ((s[i] = getchar()) != '\n') i ; p = &s[0]; while (*p != '\n') { if (('A' <= *p) && (*p <= 'Z')) upper; else if (('a' <= *p) && (*p <= 'z')) lower; else if (*p == ' ') space; else if ((*p <= '9') && (*p >= '0')) digit; else other; p ; } printf("upper case:%d lower case:%d", upper, lower); printf(" space:%d digit:%d other:%d\n", space, digit, other); return 0; }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(12)

题目9:写一函数,将一个 3×3 的整型矩阵转置。

解:

答案代码:

#include <stdio.h> int main() { void move(int *pointer); int a[3][3], *p, i; printf("input matrix:\n"); for (i = 0; i < 3; i ) scanf("%d %d %d", &a[i][0], &a[i][1], &a[i][2]); p = &a[0][0]; move(p); printf("Now,matrix:\n"); for (i = 0; i < 3; i ) printf("%d %d %d\n", a[i][0], a[i][1], a[i][2]); return 0; } void move(int *pointer) { int i, j, t; for (i = 0; i < 3; i ) for (j = i; j < 3; j ) { t = *(pointer 3 * i j); *(pointer 3 * i j) = *(pointer 3 * j i); *(pointer 3 * j i) = t; } }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(13)

说明: a 是二维数组,p 和形参 pointer 是指向整型数据的指针变量,p 指向数组 0 行 0 列元素 a[0][0] 。在调用 move 函数时,将实参p的值&a[0][0] 传递给形参 pointer,在 move 函数中将 a[i][j]与 a[j][i] 的值互换。由于 a 数组的大小是 3×3,而数组元素是按行排列的,因此 a[i][j] 在 a 数组中是第(3×i j)个元素,例如,a[2][1]是数组中第(3×2+1)个元素,即第 7 个元素(序号从 0 算起)。a[i][j]的地址是(pointer十3*i j,同理,a[i][j] 的地址是(pointer十3*j i)。将*(pointer+3*i j)和*(pointer 3*j i)互换,就是将a[i][j]和 a[j][i]互换。

题目10:将一个 5×5 的矩阵中最大的元素放在中心,4 个角分别放 4 个最小的元素(顺序为从左到右,从上到下依次从小到大存放),写一函数实现之。用 main 函数调用。

解:

答案代码(1):

#include <stdio.h> int main() { void change(int *p); int a[5][5], *p, i, j; printf("input matrix:\n"); //提示输入二维数组各元素 for (i = 0; i < 5; i ) for (j = 0; j < 5; j ) scanf("%d", &a[i][j]); p = &a[0][0]; //使p指向0行0列元素 change(p); //调用change 函数,实现交换 printf("Now,matrix:\n"); for (i = 0; i < 5; i ) //输出已交换的二维数组 { for (j = 0; j < 5; j ) printf("%d ", a[i][j]); printf("\n"); } return 0; } //交换函数 void change(int *p) { int i, j, temp; int *pmax, *pmin; pmax = p; pmin = p; for (i = 0; i < 5; i ) //找最大值和最小值的地址,并赋给 pmax,pmin for (j = i; j < 5; j ) { if (*pmax < *(p 5 * i j)) pmax = p 5 * i j; if (*pmin > *(p 5 * i j)) pmin = p 5 * i j; } temp = *(p 12); //将最大值换给中心元素 *(p 12) = *pmax; *pmax = temp; temp = *p; //将最小值换给左上角元素 *p = *pmin; *pmin = temp; pmin = p 1; for (i = 0; i < 5; i ) //找第二最小值的地址并赋给 pmin for (j = 0; j < 5; j ) if (((p 5 * i j) != p) && (*pmin > *(p 5 * i j))) pmin = p 5 * i j; temp = *pmin; //将第二最小值换给右上角元素 *pmin = *(p 4); *(p 4) = temp; pmin = p 1; for (i = 0; i < 5; i ) //找第三最小值的地址并赋给 pmin for (j = 0; j < 5; j ) if (((p 5 * i j) != (p 4)) && ((p 5 * i j) != p) && (*pmin > *(p 5 * i j))) pmin = p 5 * i j; temp = *pmin; //将第三最小值换给左下角元素 *pmin = *(p 20); *(p 20) = temp; pmin = p 1; //找第四最小值的地址并赋给 pmin for (i = 0; i < 5; i ) for (j = 0; j < 5; j ) if (((p 5 * i j) != p) && ((p 5 * i j) != (p 4)) && ((p 5 * i j) != (p 20)) && (*pmin > *(p 5 * i j))) pmin = p 5 * i j; temp = *pmin; //将第四最小值换给右下角元素 *pmin = *(p 24); *(p 24) = temp; }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(14)

说明:程序中用 change 函数来实现题目所要求的元素值的交换,分为以下几个步骤:

①找出全部元素中的最大值和最小值,将最大值与中心元素互换,将最小值与左上角元素互换。中心元素的地址为p 12(该元素是数组中的第 12 个元素——序号从 0 算起)。

②找出全部元素中的次小值。由于最小值已找到并放在 a[0][0]中,因此,在这一轮的比较中应不包括a[0][0],在其余 24 个元素中值最小的就是全部元素中的次小值。在双重 for 循环中应排除 a[0][0]参加比较。在 if 语句中,只有满足条件 ((p 5*i j)!=p) 才进行比较。不难理解, (p 5*i j) 就是 &a[i][j] ,p 的值是 &a[0][0] 。((p 5*i j)!=p) 意味着在 i 和 j 的当前值条件下 &a[i][j] 不等于 &a[0][0] 才满足条件,这样就排除了 a[0][0] 。因此执行双重 for 循环后得到次小值,并将它与右上角元素互换,右上角元素的地址为 p 4。

③找出全部元素中第 3 个最小值。此时 a[0][0] 和 a[0][4](即左上角和右上角元素)不应参加比较。可以看到∶在 if 语句中规定,只有满足条件 ((p 5*i j)!=p)&&((p 5*i j)!=(p 4)) 才进行比较。((p 5*i j)!=p) 的作用是排除 a[0][0],((p 5*i j)!=(p+4)) 的作用是排除 a[0][4] 。(p 5*i j) 是 &a[i][j] ,(p 4) 是 &a[0][4] ,即右上角元素的地址。满足 ((p 5*i j)!=(p 4)) 条件意味着排除了 a[0][4] 。执行双重 for 循环后得到除了 a[0][0] 和 a[0][4] 外的最小值,也就是全部元素中第 3 个最小值,将它与左下角元素互换,左下角元素的地址为 p 20。

④找出全部元素中第 4 个最小值。此时 a[0][0] ,a[0][4] 和 a[4][0](即左上角、右上角和左下角元素)不应参加比较,在 if 语句中规定,只有满足条件 ((p 5*i j)!=p)&&((p 5*i j)!=(p+4))&&((p 5*i j)!=(p+20)) 才进行比较。((p 5*i j)!=p) 和((p 5*i j)!=(p 4)) 的作用前已说明,((p 5*i j)!=(p 20)) 的作用是排除 a[4][0] ,理由与前面介绍的类似。执行双重 for 循环后得到除了 a[0][0] ,a[0][4] 和 a[4][0] 以外的最小值,也就是全部元素中第 4 个最小值,将它与右下角元素互换,左下角元素的地址为 p 24。

上面所说的元素地址是指以元素为单位的地址,p+24 表示从指针 p 当前位置向前移动 24 个元素的位置。如果用字节地址表示,上面右下角元素的字节地址应为 p 4*24,其中4 是整型数据所占的字节数。

(2)可以改写上面的 if 语句,change 函数可以改写如下∶

//交换函数 void change(int *p) { int i, j, temp; int *pmax, *pmin; pmax = p; pmin = p; for (i = 0; i < 5; i ) //找最大值和最小值的地址,并赋给 pmax,pmin for (j = i; j < 5; j ) { if (*pmax < *(p 5 * i j)) pmax = p 5 * i j; if (*pmin > *(p 5 * i j)) pmin = p 5 * i j; } temp = *(p 12); //将最大值与中心元素互换 *(p 12) = *pmax; *pmax = temp; temp = *p; //将最小值与左上角元素互换 *p = *pmin; *pmin = temp; pmin = p 1; //将 a[0][1]的地址赋给 pmin,从该位置开始找最小的元素 for (i = 0; i < 5; i ) //找第二最小值的地址并赋给 pmin for (j = 0; j < 5; j ) { if (i == 0 && j == 0) continue; if (*pmin > *(p 5 * i j)) pmin = p 5 * i j; } temp = *pmin; //将第二最小值与右上角元素互换 *pmin = *(p 4); *(p 4) = temp; pmin = p 1; for (i = 0; i < 5; i ) //找第三最小值的地址并赋给 pmin for (j = 0; j < 5; j ) { if ((i == 0 && j == 0) || (i == 0 && j == 4)) continue; if (*pmin > *(p 5 * i j)) pmin = p 5 * i j; } temp = *pmin; //将第三最小值与左下角元素互换 *pmin = *(p 20); *(p 20) = temp; pmin = p 1; //找第四最小值的地址并赋给 pmin for (i = 0; i < 5; i ) for (j = 0; j < 5; j ) { if ((i == 0 && j == 0) || (i == 0 && j == 4) || (i == 4 && j == 0)) continue; if (*pmin > *(p 5 * i j)) pmin = p 5 * i j; } temp = *pmin; //将第四最小值与右下角元素互换 *pmin = *(p 24); *(p 24) = temp; }

这种写法可能更容易为一般读者所理解。

题目11:在主函数中输入 10 个等长的字符串。用另一函数对它们排序。然后在主函数输出这 10 个已排好序的字符串。

解∶

(1)用字符型二维数组

答案代码:

#include <stdio.h> #include <string.h> int main() { void sort(char s[][6]); int i; char str[10][6]; // p 是指向由 6个元素组成的一维数组的指针 printf("input 10 strings:\n"); for (i = 0; i < 10; i ) scanf("%s", str[i]); sort(str); printf("Now,the sequence is:\n"); for (i = 0; i < 10; i ) printf("%s\n", str[i]); return 0; } void sort(char s[10][6]) //形参s是指向由6个元素组成的一维数组的指针 { int i, j; char *p, temp[10]; p = temp; for (i = 0; i < 9; i ) for (j = 0; j < 9 - i; j ) if (strcmp(s[j], s[j 1]) > 0) { //以下3行是将s[i]指向的一维数组的内容与s[j 1]指向的一维数组的内容互换 strcpy(p, s[j]); strcpy(s[j], s[ j 1]); strcpy(s[j 1], p); } }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(15)

(2) 用指向一维数组的指针作函数参数

#include <stdio.h> #include <string.h> int main() { void sort(char(*p)[6]); int i; char str[10][6]; char(*p)[6]; printf("input 10 strings:\n"); for (i = 0; i < 10; i ) scanf("%s", str[i]); p = str; sort(p); printf("Now, the sequence is:\n"); for (i = 0; i < 10; i ) printf("%s\n", str[i]); return 0; } void sort(char (*s)[6]) { int i, j; char temp[6], *t = temp; for (i = 0; i < 9; i ) for (j = 0; j < 9 - i; j ) if (strcmp(s[j], s[j 1]) > 0) { strcpy(t, s[j]); strcpy(s[j], s[ j 1]); strcpy(s[j 1], t); } }

运行结果同(1)。

题目12:用指针数组处理上一题目,字符串不等长。

解:

答案代码:

#include <stdio.h> #include <string.h> int main() { void sort(char *[]); int i; char *p[10], str[10][20]; for (i = 0; i < 10; i ) p[i] = str[i]; //将第i个字符串的首地址赋予指针数组 p的第i个元素 printf("input 10 strings:\n"); for (i = 0; i < 10; i ) scanf("%s", p[i]); sort(p); printf("Now,the sequence is:\n"); for (i = 0; i < 10; i ) printf("%s\n", p[i]); return 0; } void sort(char *s[]) { int i, j; char *temp; for (i = 0; i < 9; i ) for (j = 0; j < 9 - i; j ) if (strcmp(*(s j), *(s j 1)) > 0) { temp = *(s j); *(s j) = *(s j 1); *(s j 1) = temp; } }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(16)

题目13:写一个用矩形法求定积分的通用函数,分别求

$$\int _0^1 sinxdx, \int _0^1 cosxdx,\int_0^1e^xdx$$

说明:sin,cos,exp 函数已在系 统的数学函数库中,程序 开头要用 # include <math.h>。

解:

可以看出,每次需要求定积分的函数是不一样的。可以编写一个求定积分的通用函数 integral,它有3个形参,即下限 a、上限 b及指向函数的指针变量 fun。函数原型可写为

float integral(float a, float b,float(* fun)());

先后调用integral函数3次,每次调用时把 a,b,sin,cos,exp 之一作为实参,把上限、下限及有关函数的入口地址传送给形参 fun。在执行 integral 函数过程中求出定积分的值。根据以上思路编写出程序:

#include <stdio.h> #include <math.h> int main() { float integral(float (*)(float), float, float, int); //对 integarl函数的声明 float fsin(float); //对 fsin 函数的声明 float fcos(float); //对 fcos 函数的声明 float fexp(float); //对fexp 函数的声明 float a1, b1, a2, b2, a3, b3, c, (*p)(float); int n = 20; printf("input a1,b1:"); scanf("%f,%f", &a1, &b1); //输入求 sin(x)定积分的下限和上限 printf("input a2,b2:"); scanf("%f,%f", &a2, &b2); //输入求 cos(x)定积分的下限和上限 printf("input a3,b3:"); scanf("%f,%f", &a3, &b3); //输入求e的x次方的定积分的下限和上限 p = fsin; //使p指向 fsin 函数 c = integral(p, a1, b1, n); //求出 sin(x)的定积分 printf("The integral of sin(x)is:%f\n", c); p = fcos; //使 p指向fcos 函数 c = integral(p, a2, b2, n); //求出 cos(x)的定积分 printf("The integral of cos(x)is:%f\n", c); p = fexp; //使p指向 fexp 函数 c = integral(p, a3, b3, n); //求出e的x次方的定积分 printf("The integral of exp(x)is:%f\n", c); return 0; } //下面是用矩形法求定积分的通用函数 float integral(float (*p)(float), float a, float b, int n) { int i; float x, h, s; h = (b - a) / n; x = a; s = 0; for (i = 1; i <= n; i ) { x = x h; s = s (*p)(x)*h; } return (s); } float fsin(float x) //计算 sin(x)的函数 { return sin(x); } float fcos(float x) //计算 cos(x)的函数 { return cos(x); } float fexp(float x) //计算e的 x次方的函数 { return exp(x); }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(17)

说明:sin,cos 和 exp 是系统提供的数学函数,在程序中定义3 个函数,即 fsin,fcos 和 fexp。分别用来计算 sin(x) ,cos(x) 和exp(x) 的值。在 main 函数中要对这 3 个函数作声明。在 main 函数定义中 p为指向函数的指针变量,定义形式是"float(*p)(float)",表示 p 指向的函数有一个实型形参,p 指向返回值为实型的函数。在 main 函数中有"p=fsin;",表示将 fsin 函数的入口地址传赋给 p,在调用 integral 函数时,用 p 作为实参,把 fsin 函数的入口地址传递给形参 p(相当于 fsin(x) 。fsin(x) 的值就是 sin(x)的值。因此通过调用 integral 函数求出 sin(x) 的定积分。求其余两个函数的定积分的情况与此类似。

题目14:将 n 个数按输入时顺序的逆序排列,用函数实现。

解:

答案代码:

#include <stdio.h> int main() { void sort(char *p, int m); int i, n; char *p, num[20]; printf("input n:"); scanf("%d", &n); printf("please input these numbers: \n"); for (i = 0; i < n; i ) scanf("%d", &num[i]); p = &num[0]; sort(p, n); printf("Now,the sequence is:\n"); for (i = 0; i < n; i ) printf("%d ", num[i]); printf("\n"); return 0; } //将n 个数逆序排列函数 void sort(char *p, int m) { int i; char temp, *p1, *p2; for (i = 0; i < m / 2; i ) { p1 = p i; p2 = p (m - 1 - i); temp = *p1; *p1 = *p2; *p2 = temp; } }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(18)

题目15:有一个班 4 个学生,5 门课程。

①求第 1 门课程的平均分;

②找出有两门以上课程不及格的学生,输出他们的学号和全部课程成绩及平均成绩;

③找出平均成绩在 90 分以上或全部课程成绩在 85分以上的学生。

分别编3个函数实现以上 3个要求。

解:

答案代码:

#include <stdio.h> int main() { void avsco(float *, float *); //函数声明 void avcour1(char(*)[10], float *); //函数声明 void fali2(char course[5][10], int num[], float *pscore, float aver[4]); //函数声明 void good(char course[5][10], int num[4], float *pscore, float aver[4]); //函数声明 int i, j, *pnum, num[4]; float score[4][5], aver[4], *pscore, *paver; char course[5][10], (*pcourse)[10]; printf("input course:\n"); pcourse = course; for (i = 0; i < 5; i ) scanf("%s", course[i]); printf("input NO. and scores:\n"); printf("NO."); for (i = 0; i < 5; i ) printf(",%s", course[i]); printf("\n"); pscore = &score[0][0]; pnum = &num[0]; for (i = 0; i < 4; i ) { scanf("%d", pnum i); for (j = 0; j < 5; j ) scanf("%f", pscore 5 * i j); } paver = &aver[0]; printf("\n\n"); avsco(pscore, paver); //求出每个学生的平均成绩 avcour1(pcourse, pscore); //求出第 1 门课的平均成绩 printf("\n\n"); fali2(pcourse, pnum, pscore, paver); //找出两门课不及格的学生 printf("\n\n"); good(pcourse, pnum, pscore, paver); //找出成绩好的学生 return 0; } //求每个学生的平均成绩的函数 void avsco(float *pscore, float *paver) { int i, j; float sum, average; for (i = 0; i < 4; i ) { sum = 0.0; for (j = 0; j < 5; j ) sum = sum (*(pscore 5 * i j)); //累计每个学生的各科成绩 average = sum / 5; //计算平均成绩 *(paver i) = average; } } //求第1课程的平均成绩的函数 void avcour1(char (*pcourse)[10], float *pscore) { int i; float sum, average1; sum = 0.0; for (i = 0; i < 4; i ) sum = sum (*(pscore 5 * i)); //累计每个学生的得分 average1 = sum / 4; //计算平均成绩 printf("course 1:%s average score:%7.2f\n", *pcourse, average1); } //找两门以上课程不及格的学生的函数 void fali2(char course[5][10], int num[], float *pscore, float aver[4]) { int i, j, k, label; printf(" ======Student who is fail in two courses ======\n"); printf("NO. "); for (i = 0; i < 5; i ) printf("s", course[i]); printf(" average\n"); for (i = 0; i < 4; i ) { label = 0; for (j = 0; j < 5; j ) if (*(pscore 5 * i j) < 60.0) label ; if (label >= 2) { printf("%d", num[i]); for (k = 0; k < 5; k ) printf(".2f", *(pscore 5 * i k)); printf(".2f\n ", aver[i]); } } } //找成绩优秀学生(各门85分以上或平均 90分以上)的函数 void good(char course[5][10], int num[4], float *pscore, float aver[4]) { int i, j, k, n; printf(" ======Students whose score is good ======\n"); printf("NO. "); for (i = 0; i < 5; i ) printf("s", course[i]); printf(" average\n"); for (i = 0; i < 4; i ) { n = 0; for (j = 0; j < 5; j ) if (*(pscore 5 * i j) > 85.0) n ; if ((n == 5) || (aver[i] >= 90)) { printf("%d", num[i]); for (k = 0; k < 5; k ) printf(".2f", *(pscore 5 * i k)); printf(".2f\n", aver[i]); } } }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(19)

程序中 num 是存放 4 个学生学号的一维数组,course 是存放 5 门课名称的二维字符数组,score 是存放 4 个学生 5 门课成绩的二维数组,aver 是存放每个学生平均成绩的数组。pnum 是指向 num数组的指针变量,pcou 是指向 course 数组的指针变量,psco 是指向 score 数组的指针变量,pave是指向 aver 数组的指针变量,见图8.3。

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(20)

函数的形参用数组,调用函数时的实参用指针变量。形参也可以不用数组而用指针变量,请读者自己分析。

题目16:输入一个字符串,内有数字和非数字字符,例如∶

A123x456 17960?302tab5876

将其中连续的数字作为一个整数,依次存放到一数组 a 中。例如,123放在 a[0],456放在a[1]……统计共有多少个整数,并输出这些数。

解∶

答案代码:

#include <stdio.h> int main() { char str[50], *pstr; int i, j, k, m, e10, digit, ndigit, a[10], *pa; printf("input a string:\n"); gets(str); pstr = &str[0]; //字符指针 pstr置于数组 str 首地址 pa = &a[0]; //指针 pa 置于a数组首地址 ndigit = 0; // ndigit 代表有多少个整数 i = 0; //代表字符串中的第几个字符 j = 0; while (*(pstr i) != '\0') { if ((*(pstr i) >= '0') && (*(pstr i) <= '9')) j ; else { if (j > 0) { digit = *(pstr i - 1) - 48; //将个数位赋予digit k = 1; while (k < j) //将含有两位以上数的其他位的数值累加于digit { e10 = 1; for (m = 1; m <= k; m ) e10 = e10 * 10; // e10 代表该位数所应乘的因子 digit = digit (*(pstr i - 1 - k) - 48) * e10; //将该位数的数值\累加于 digit k ; //位数k自增 } *pa = digit; //将数值赋予数组 a ndigit ; pa ; //指针 pa 指向 a数组下一元素 j = 0; } } i ; } if (j > 0) //以数字结尾字符串的最后一个数据 { digit = *(pstr i - 1) - 48; //将个数位赋予 digit k = 1; while (k < j) { e10 = 1; //将含有两位以上数的其他位的数值累加于 digit for (m = 1; m <= k; m ) e10 = e10 * 10; // e10代表位数所应乘的因子 digit = digit (*(pstr i - 1 - k) - 48) * e10; //将该位数的数值累加于 digit k ; //位数k自增 } *pa = digit; //将数值赋予数组 a ndigit ; j = 0; } printf("There are %d numbers in this line, they are:\n", ndigit); j = 0; pa = &a[0]; for (j = 0; j < ndigit; j ) //输出打印数据 printf("%d ", *(pa j)); printf("\n"); return 0; }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(21)

题目17:写一函数,实现两个字符串的比较。即自己写一个 strcmp 函数,函数原型为

int strcmp(char * p1,char * p2);

设 p1指向字符串sl,p2指向字符串s2。要求当s1=s2时,返回值为0;若 s1≠s2,返回它们二者第 1 个不同字符的 ASCII 码差值(如"BOY"与"BAD",第 2个字母不同,O与 A 之差为79-65=14)。如果 s1>s2,则输出正值;如果 s1<s2,则输出负值。

解:

答案代码:

#include <stdio.h> int main() { int m; char str1[20], str2[20], *p1, *p2; printf("input two strings:\n"); scanf("%s", str1); scanf("%s", str2); p1 = &str1[0]; p2 = &str2[0]; m = strcmp(p1, p2); printf("result:%d,\n", m); return 0; } //两个字符串比较函数 strcmp(char *p1, char *p2) { int i; i = 0; while (*(p1 i) == *(p2 i)) if (*(p1 i ) == '\0') //相等时返回结果0 return (0); return (*(p1 i) - *(p2 i)); /*不等时返回结果为第一个不等字符ASCII码的差值 */ }

运行结果∶

①:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(22)

②:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(23)

题目18:编一程序,输入月份号,输出该月的英文月名。例如,输入 3,则输出"March",要求用指针数组处理。

解:

答案代码:

#include <stdio.h> int main() { char *month_name[13] = {"illegal month ", " January", " February", " March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; int n; printf("input month:\n"); scanf("%d", &n); if ((n <= 12) && (n >= 1)) printf("It is %s.\n", *(month_name n)); else printf("It is wrong.\n"); return 0; }

运行结果∶

①:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(24)

②:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(25)

③:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(26)

题目19:(1)编写一个函数 new,对 n 个字符开辟连续的存储空间,此函数应返回一个指针(地址),指向字符串开始的空间。new(n)表示分配 n 个字节的内存空间。(2)写一函数 free;将 前面用 new 函数占用的空间释放。free(p)表示将 p(地址))指向的单元以后的内存段释放。

解∶

(1)编写函数new 程序如下∶

#include <stdio.h> #define NEWSIZE 1000 //指定开辟存储区的最大容量 char newbuf[NEWSIZE]; //定义字符数组 newbuf char *newp = newbuf; //定义指针变量 newp,指向可存储区的始端 //定义开辟存储区的函数 new,开辟存储区后返回指针 char *new (int n) { if (newp n <= newbuf NEWSIZE) //开辟区未超过 newbuf 数组的大小 { newp = n; // newp指向存储区的末尾 return (newp - n); //返回一个指针,它指向存储区的开始位置 } else return (NULL); //当存储区不够分配时,返回一个空指针 }

new 函数的作用是:分配 n 个连续字符的存储空间。为此,应先开辟一个足够大的连续存储区,今设置字符数组 newbuf[1000],new 函数将在此范围内进行操作。指针变量 newp 开始指向存储区首字节。在每当请求用 new 函数开辟 n 个字符的存储区时,要先检查一下 newbuf 数组是否还有足够的可用空间。若有,则使指针变量 newp 指向开辟区的末尾(newp=newp十n),见图8.4中的 newp 。此时 newp 指向下面的空白(未分配)的区域的开头,即 newp 的值是下一次可用空间的开始地址。如果再一次调用 new 函数,就从 newp 最后所指向的字节开始分配下一个开辟区。如果若存储区不够分配,则返回 NULL,表示开辟失败。

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(27)

new返回一个指向字符型数据的指针,指向新开辟的区域的首字节。

在主函数中可以用以下语句:

pt = new(n);

把新开辟的区域首字节的地址赋给 pt,使指针变量 pt 也指向新开辟的区域的开头。

(2)编写函数 free

free 的作用是使newp 的值恢复为p。

free 函数如下∶

#include <stdio.h> #define NEWSIZE 1000 char newbuf[NEWSIZE]; char *newp = newbuf; //释放存区函数 void free(char *p) { if (p >= newbuf && p < newbuf NEWSIZE) newp = p; }

在主函数中用以下语句指令释放 pt 指向的存储区。

free(pt);

调用 free时,实参 pt 的值传给形参 p,因此 p的值也是新开辟的区域首字节的地址。用 if 语句检查 p 是否在已开辟区的范围内(否则不合法,不能释放未分配的区域)。如果确认 p 在上述范围内,就把 p(即 pt)的值赋给 newp,使 newp 重新指向原来开辟区的开头,这样,下次再开辟新区域时就又从 newp 指向的字节开始分配,这就相当于释放了此段空间,使这段空间可再分配作其他用途。

有人可能对 if语句所检查的条件 "p>=newbuf && p<newbuf + NEWSIZE" 不理解,为什么不直接检查 "p==newbuf" 呢?他们认为 p 应当指向 newbuf 的开头。这里有个细节要考虑∶当第 1 次调用 new 函数开辟存储区时,new 函数的返回值(也是 pt 的值)的确是 newbuf。但是如果接着再开辟第 2 个存储区,new 函数的返回值(也是 pt 的值)就不是newbuf了,而是指针变量 newp的当前值,即 newbuf n了。因此,调用free 函数时,形参p得到的值也是第 2个存储区的起始地址。要释放的是第 2个存储区,而不是第1个存储区。但p的值必然在"newbuf 到 newbuf NEWSIZE"的范围内。

上面只是编写了两个函数,并不是完整的程序,它没有main 函数。本题是示意性的,可以大体了解开辟存储区的思路。

题目20:用指向指针的指针的方法对 5个字符串排序并输出。

解:

程序如下

#include <stdio.h> #include <string.h> #define LINEMAX 20 //定义字符串的最大长度 int main() { void sort(char **p); int i; char **p, *pstr[5], str[5][LINEMAX]; for (i = 0; i < 5; i ) pstr[i] = str[i]; //将第i个字符串的首地址赋予指针数组 pstr 的第i个元素 printf("input 5 strings:\n"); for (i = 0; i < 5; i ) scanf("%s", pstr[i]); p = pstr; sort(p); printf("\nstrings sorted:\n"); for (i = 0; i < 5; i ) printf("%s\n", pstr[i]); return 0; } //用冒泡法对5个字符串排序函数 void sort(char **p) { int i, j; char *temp; for (i = 0; i < 5; i ) { for (j = i 1; j < 5; j ) //比较后交换字符串地址 { if (strcmp(*(p i), *(p j)) > 0) { temp = *(p i); *(p i) = *(p j); *(p j) = temp; } } } }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(28)

题目21:用指向指针的指针的方法对 n个整数排序并输出。要求将排序单独写成一个函数。n 个整数在主函数中输入,最后在主函数中输出。

解:

答案代码:

#include <stdio.h> int main() { void sort(int **p, int n); int i, n, data[20], **p, *pstr[20]; printf("input n:\n"); scanf("%d", &n); for (i = 0; i < n; i ) pstr[i] = &data[i]; //将第i个整数的地址赋予指针数组 pstr 的第i个元素 printf("input %d integer numbers:", n); for (i = 0; i < n; i ) scanf("%d", pstr[i]); p = pstr; sort(p, n); printf("Now,the sequence is:\n"); for (i = 0; i < n; i ) printf("%d ", *pstr[i]); printf("\n"); return 0; } void sort(int **p, int n) { int i, j, *temp; for (i = 0; i < n - 1; i ) { for (j = i 1; j < n; j ) { if (**(p i) > **(p j)) //比较后交换整数地址 { temp = *(p i); *(p i) = *(p j); *(p j) = temp; } } } }

运行结果:

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(29)

data数组用来存放n个整数,pstr 是指针数组,每一个元素指向 data 数组中的一个元素,p 是指向指针的指针,请参考图8.5。图8.5(a)表示的是排序前的情况,图8.5(b)表示的是排序后的情况。可以看到,data 数组中的数的顺序没有变化,而 pstr 指针数组中的各元素的值(也就是它们的指向)改变了。

c语言程序设计习题答案与实验指导(C语言程序设计谭浩强第五版)(30)

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页