概述
本文主要提供《C语言程序设计》(浙大版) 第七、八章的课后习题解析,以方便同学们完成题目后作为参考对照。后续将更新第九、十章节的课后习题解析,如想了解更多,请持续关注该专栏。
专栏直达链接:《C语言程序设计》(浙大版)_孟俊宇-MJY的博客-CSDN博客http://t.csdnimg.cn/ZtcgY
一.第七章(数组)
选择题
[7-1]
假定 int 类型变量占用两个字节,则以下定义的数组 a 在内存中所占字节数是( )。
int a[10]={10,2,4};
A. 20
B.10
C.6
D.3
答:A
解析:题目中,根据 int a[10] ,表示定义了数组的长度是 10 ,每个变量占用两个字节,一共就是 20 个字节。
[7-2]
若有定义:`int a[2][3]` ;以下选项中对数组元素正确引用的是( )。
A. a[2][0]
B. a[2][3]
C. a[0][3]
D. a[1>2][1]
答:D
解析:
题目中定义了二维数组 a[2][3] ,那么该数组表示一个 2 行 3 列的矩阵,行的下标(第一个下标)的取值范围就是 0,1,列的下标(第二个下标)的取值范围就是 0,1,2。这里是有选项 D,a[1>2][1],实际上是 a[0][1],下标的数值没有越界。
[7-3]
以下程序段的输出结果是( )。
int aa[4][4]={{1,2,3,4},{5,6,7,8},{3,9,10,2},{4,2,9,6}};
int i, s=0;
for(i=0; i<4; i++)
s+=aa[i][3];
printf("%d\n", s);
A.11
B.19
C.13
D.20
答:D
解析:
题目中定义的是二维数组,4X4 的矩阵。
1 2 3 4
5 6 7 8
3 9 10 2
4 2 9 6
循环中 i 的值表示行,从 0 取到 3,而列的下标固定是 3,所以表示累加最后一列的值。4+8+2+6 = 20。
[7-4]
设有数组定义:char array[]="China" ; 则数组 array 所占的空间为( )字节。
A.4个
B.5个
C.6个
D.7个
答:C
解析:再题目的定义方式中,系统会自动在数组最后加入一个'\0',表示字符数组的结束,因此数组的长度就是 6 个字节。
[7-5]
下述对字符数组的描述中错误的是( )。
A.字符数组可以存放字符串
B.字符数组中的字符串可以整体输入、输出
C.可以在赋值语句中通过赋值运算符"="对字符数组整体赋值
D.不可以用关系运算符对字符数组中的字符串进行比较
答:C
解析:
选项 A 正确,在 C 语言中可以将字符串作为一个特殊的一位字符数组来处理。例如:char array[]="China" ;
选项 B 正确,因为字符数组中直接使用数组名称时数组会退化为指针而且字符串结尾会有“\0”,指针遇到“\0”会结束输入或者输出。用到的代码是: char ch[100]; gets(ch); //整体输入puts(ch);整体输出。(同时这里提个醒字符数组可以进行整体的输入输出,但是整型输出是不可以进行的整体输入输出)
选项 C 不正确。在赋值语句中通过赋值运算符"="对字符数组整体赋值,则就需要用到字符数组名,而对字符数组名进行操作时其会退化为常量指针,而进行赋值时左值必须是可以修改的变量。所以错误。
选项 D 正确。数组名会退化为指针,所以比较的其实就是指针所指向的内存地址的大小,这个跟比较字符串的大小没有关系。
[7-6]
对于以下定义,正确的叙述为( )。
char x[]="abcdefg", char y[]={'a','b','c','a','e','f','g'};
A.数组 x 和数组 y 等价
B.数组 x 的长度大于数组 y 的长度
C.数组 x 和数组 y 的长度相同
D.数组 x 的长度小于数组 y 的长度
答:B
解析:
char x[]="abcdefg",数组 x 的长度是 8,7个字符,以及系统自动加的 '\0'。
char y[]={'a','b','c','a','e','f','g'},数组 y 的长度是 7。
char x[]=”abcdefg”;
//等价于
char x[]={‘a’,'b’,'c’,'d’,'e’,'f’,'g’,'\0'};
填空题
[7-1]
写出以下程序段的输出结果:输入4,则输出( ),输入5,则输出( ),输入12,则输出( ),输入-5,则输出( )。
int i, n = 5, x, a[10] = {1, 3, 5, 7, 9};
scanf("%d", &x);
for (i = n - 1; i >= 0; i--)
if (x < a[i])
a[i + 1] = a[i];
else
break;
a[i + 1] = x;
n++;
printf("%d", i + 1);
答:2 3 5 0
解析:
循环中 i 的取值为 4,3,2,1,0。当取到 -1 时结束 for循环。循环里就是在比较 x 和 a[i] 的大小。
第一个空,当 x 的值为 4 时, 下标 i 的值为 1,对应数组中的 3,if 语句不成立,break 了循环,此时 i 的值为1 。最终打印 i+1的值就是 2。
第二个空,当 x 的值为 5 时,下标 i 的值为 2,对应数组中的的 5,if 语句不成立,break 了循环,此时 i 的值为 2。最终打印 i+1 的值就是 3。
第三个空,当 x 的值为 12 时,下标 i 的值为 4,对应数组中的 9,if 语句不成立,break 循环,此时 i 的值为 4。最终打印 i+1 的值就是 5。
第四个空,当 x 的值为 -5 时,整个数组中的所有值都比 x 大,循环结束时 i 的值为 -1 。最终打印 i+1 的值就是 0。
[7-2]
求数组中相邻元素之和。将数组 x 中相邻两个元素的和依次存放到 a 数组中。请填空。
int i, a[9], x[10];
for (i = 0; 1 < 10; i++)
scanf("%d", &x[i]);
for (_______; i < 10; i++)
a[i - 1] = _______ + x[i];
答:
i = 1
x[i - 1]
解析:因为要表示数组中相邻的元素,可以使用 x[i-1] 和 x[i],所以在第二个 for 循环中,i 的初始值为 1。
[7-3]
简化的插入法排序。将一个给定的整数 x 插到已按升序排列的整型数组 a 中,使 a 数组仍然按升序排列。假定变量都已正确定义并赋值,请填空。
for (i = 0; i < n; i++)
{
if (________)
{
break;
}
}
for (________)
{
a[j + 1] = a[j];
}
________;
n++;
答:
x < a[i]
j = n - 1; j >= i; j--
a[i] = x
解析:
这里的思路是:第一个 for 循环,比较 x 和 数组中的元素,直到 x 大于数组中的某一个元素。然后记录该值的下标。
然后第二个循环将 i 后的每一个元素向后移动一个位置。
最后将 x 插入到 下表 i 的位置上。
[7-4]
输入 8 ,以下程序段的输出结果为( ),输入 5 ,输出结果为( )。
int i, max_sum, n, this_sum, a[] = {-1, 3, -2, 4, -6, 1, 6, -1};
scanf("%d", &n);
max_sum = this_sum = 0;
for (i = 0; i < n; i++)
{
this_sum += a[i];
if (this_sum > max_sum)
max_sum = this_sum;
else if (this_sum < 0)
this_sum = 0;
}
printf("%d\n", max_sum);
答:7 5
解析:
第一空,当 n = 8 时,for 循环遍历了数组中的所有的元素,下标从 0 到 7 。
i = 0 时,循环条件成立,进入循环,this_sum 累加完 a[0] = -1 ,值为 -1,执行 else if 的内容,this_sum 的值被修改为 0。
i = 1 时,循环条件成立,进入循环,this_sum 累加完 a[1] = 3,值为 3,执行 if 的内容,max_sum 的值为 3。
i = 2 时,循环条件成立,进入循环,this_sum 累加完 a[2] = -2,值为 1,不执行 if 也不执行 else if,然后下一次循环。
i = 3 时,循环条件成立,进入循环,this_sum 累加完 a[3] = 4,值为 5,执行 if 的内容,max_sum 的值为 5。
i = 4 时,循环条件成立,进入循环,this_sum 累加完 a[4] = -6,值为 -1,执行 else if 的内容,this_sum 的值被修改为 0。
i = 5 时,循环条件成立,进入循环,this_sum 累加完 a[5] =1,值为 1,不执行if 也不执行 else if,然后下一次循环。
i = 6 时,循环条件成立,进入循环,this_sum 累加完 a[6]= 6,值为 7,执行 if 的内容,max_sum 的值修改为 7。
i = 7 时,循环条件成立,进入循环,this_sum 累加完 a[7] = -1,值为 6。不执行if 也不执行 else if。
i = 8 时,结束循环。
第二空,当 n = 5 时,for 循环遍历了下标从 0 到 4。数值的遍历从 -1 到 -6 。分析过程如上。
[7-5]
输入 1 2 3 4 5 6 ,则程序段 A 的输出结果是( ),程序段 B 的输出结果是( )。
程序段 A
int i, j, table[3][2];
for (i = 0; i < 3; i++)
for (j = 0; j < 2; j++)
scanf("%d", &table[i][j]);
for (i = 0; i < 3; i++)
for (j = 0; j < 2; j++)
printf("%d#", table[i][j]);
程序段 B
int i, j, table[3][2];
for (j = 0; j < 2; j++)
for (i = 0; i < 3; i++)
scanf("%d", &table[i][j]);
for (i = 0; i < 3; i++)
for (j = 0; j < 2; j++)
printf("%d#", table[i][j]);
答:
1#2#3#4#5#6#
1#4#2#5#3#6#
[7-6]
判断二维数组是否对称。检查二维数组 a 是否对称,即对所有 i ,j 都满足`a[i][j]` 和`a[j][i]`的值相等。假定变量都已正确定义并赋值,请填空。
found = 1;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (___________)
{
___________;
break;
}
}
if (___________)
break;
}
if (found != 0)
printf("该二维数组对称\n");
else
printf("该二维数组不对称\n");
答:
a[i][j] != a[j][i]
found = 0
found == 0
解析:
由打印输出条件可以看的出来,found 的值为 1 时,是对称数组,found 为 0 时,是非对称数组。
所以第一个空,填入 a[i][j] != a[j][i],他俩的值不想等,那么就把 found 修改为 0。所以第二个空为 found = 0,执行了 break,结束这个 j 这个循环。第三个空要判断 found 的值是否为 0 ,如果是 0 就结束整个 i 的循环,因为一旦 found 被修改为 0,那么这个数组就不是对称的了,后面的其他数值也不需要判断了。
[7-7]
字符串复制。将字符串 str1 的内容复制到字符串 str2 。 假定变量都已正确定义并赋值,请填空。
i = 0;
while (___________)
{
___________;
i++;
}
___________;
答:
str1[i] != '\0'
str2[i] = str1[i]
str2[i] = '\0'
解析:这里循环复制就可以了。只不过使用 char[] 数组操作字符串,最后一个字符存储 '\0'。
[7-8]
删除字符串中的空格。将字符串 str 中的所有空格都删除。假定变量都已正确定义并赋值,请填空。
i = j = 0;
while (__________)
{
if (__________)
{
str[j] = str[i];
__________
}
i++;
}
__________
答:
str[i] != '\0'
str[i] != ' '
j++;
str[j] = '\0';
解析:
循环遍历字符串,通过两个下标 i 和 j 来操作。i 用于遍历字符串中的每个字符,j 用于存储非空格的字符。如果这个字符不是空格,就复制到 j 对应的位置上。最后要记得末尾加 '\0'。
程序设计题
[7-1]
选择法排序。输入一个正整数 n (1<n≤10),再输入 n 个整数,将它们从大到小排序后输出。试编写相应程序。
答案代码:
#include <stdio.h>
int max(int a[], int i, int n) ;
int main()
{
//数据存入
int i, n;
printf("input n number:");
scanf("%d", &n);
int a[n];
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
//选择排序
for (i = 0; i < n - 1; i++)
{
int maxid = max(a, i , n);
if(maxid != i){
int t = a[maxid];
a[maxid] = a[i];
a[i] = t;
}
}
for (i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
int max(int a[], int i, int n)
{
int j, maxid = i;
for (j = i + 1; i < n; j++)
{
if (a[j] > a[maxid])
{
maxid = j;
}
}
return maxid;
}
运行结果:
[7-2]
求一批整数中出现最多的数字。输入一个正整数 n(1<n≤1 000), 再输入 n 个整数,分析每个整数的每一位数字,求出现次数最多的数字。例如输入 3 个整数 1234、2345、3456, 其中出现次数最多的数字是 3 和 4 ,均出现了 3 次。试编写相应程序。
答案代码:
#include <stdio.h>
int main()
{
int n, i, max = 0, temp, time[10] = {0};
printf("input n:");
scanf("%d", &n);
printf("input %d integers:", n);
for (i = 0; i < n; i++)
{
scanf("%d", &temp);
while (temp != 0)
{
time[temp % 10]++;
temp /= 10;
}
}
for (i = 0; i < 10; i++)
{
if (max < time[i])
max = time[i];
}
printf("出现最多次数 %d 次的数字是:", max);
for (i = 0; i < 10; i++)
if (time[i] == max)
printf("%d ", i);
printf("\n");
return 0;
}
运行结果:
再输入一组:
[7-3]
判断上三角矩阵。输入一个正整数 n(1≤n≤6)和 n 阶方阵 a 中的元素,如果 a 是上三角矩阵,输出 “YES", 否则,输出 “NO"。 上三角矩阵指主对角线以下的元素都为 0 的矩阵,主对角线为从矩阵的左上角至右下角的连线。试编写相应程序。
答案代码:
#include <stdio.h>
int main()
{
int flag = 1,i,j,n;
printf("input n:");
scanf("%d",&n);
int a[n][n];
printf("input array:\n");
for(i = 0 ;i < n; i++){
for(j = 0;j < n; j++){
scanf("%d",&a[i][j]);
}
}
for(i = 0;i < n;i++){
for(j = 0; j < i; j++){
if(a[i][j] != 0){
flag = 0;
break;
}
}
if(flag == 0){
break;
}
}
if(flag){
printf("YES\n");
}else{
printf("NO\n");
}
return 0;
}
运行结果:
[7-4]
求矩阵各行元素之和。输入 2 个正整数 m 和 n (1≤m≤6,1≤n≤6) ,然后输入矩阵 a ( m 行 n 列 ) 中的元素,分别求出各行元素之和,并输出。试编写相应程序。
答案代码:
#include <stdio.h>
int main()
{
int i,j,m,n,sum;
printf("input m,n:");
scanf("%d%d",&m,&n);
int a[m][n];
printf("input array:\n");
for(i = 0 ;i < m; i++){
for(j = 0;j < n;j++){
scanf("%d",&a[i][j]);
}
}
for(i = 0;i < m;i++){
sum = 0;
for(j = 0;j < n; j++){
sum += a[i][j];
}
printf("sum of row %d is %d\n",i,sum);
}
return 0;
}
运行结果:
[7-5]
找鞍点。输入 1 个正整数 n ( 1≤n≤6) 和 n 阶方阵 a 中的元素,假设方阵 a 最多有 1 个鞍点,如果找到 a 的鞍点,就输出其下标,否则,输出“NO"。 鞍点的元素值在该行上最大,在该列上最小。试编写相应程序。
答案代码:
#include <stdio.h>
int main()
{
int flag, i, j, k, row, col, n, a[6][6];
printf("input n: ");
scanf("%d", &n);
printf("input array:\n");
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
for (i = 0; i < n; i++)
{
flag = 1;
col = 0;
for (j = 0; j < n; j++)
if (a[i][col] < a[i][j])
col = j;
for (k = 0; k < n; k++)
if (a[i][col] > a[k][col])
{
flag = 0;
break;
}
if (flag)
{
row = i;
break;
}
}
if (flag)
printf("a[%d][%d]=%d\n", row, col, a[row][col]);
else
printf("NO\n");
return 0;
}
运行结果:
再输入一组:
[7-6]
统计大写辅音字母。输入一个以回车结束的字符串(少于 80 个字符),统计并输出其中大写辅音字母的个数。大写辅音字母是指除 'A','E' ,'I','O', 'U' 以外的大写字母。试编写相应程序。
答案代码:
#include <stdio.h>
int main()
{
int count, i;
char ch, str[80];
printf("input a string:");
i = 0;
while ((ch = getchar()) != '\n')
{
str[i++] = ch;
}
str[i] = '\0';
count = 0;
for (i = 0; str[i] != '\0'; i++)
if (str[i] <= 'Z' && str[i] > 'A' && str[i] != 'E' && str[i] != 'I' && str[i] != 'O' && str[i] != 'U')
count++;
printf("count = %d\n", count);
return 0;
}
运行结果:
[7-7]
字符串替换。输入一个以回车结束的字符串(少于 80 个字符),将其中的大写字母用下面列出的对应大写字母替换,其余字符不变,输出替换后的字符串。试编写相应程序。
原字母对应字母 A→Z B→Y C→X D→W ... X→C Y→B Z→A
答案代码:
#include <stdio.h>
int main()
{
int i;
char ch, str[80];
printf("input a string:");
i = 0;
while ((ch = getchar()) != '\n')
{
str[i++] = ch;
}
str[i] = '\0';
for (i = 0; str[i] != '\0'; i++)
if (str[i] <= 'Z' && str[i] >= 'A')
str[i] = 'A' + 'Z' - str[i];
printf("After replaced:");
for (i = 0; str[i] != '\0'; i++)
putchar(str[i]);
putchar('\n');
return 0;
}
运行结果:
[7-8]
字符串转换成十进制整数。输入一个以字符 “#” 结束的字符串,滤去所有的非十六进制字符(不分太小写),组成一个新的表示十六进制数字的字存串,然后将其转换为十进制数后输出。如果过滤后字符串的首字符为 “-“ 代表该数是负数。试编写相应程序。
答案代码:
#include <stdio.h>
int main()
{
char str_old[81], str_new[81];
int i = 0, j, flag = 0, temp; // flag用来表示是否有负号存在,0表示负数,1表示正数
long sum = 0;
printf("input s string:");
while ((str_old[i] = getchar()) != '#')
i++; //输入一个以'#'结束的非空字符串
str_old[i] = '\0';
for (i = 0; str_old[i] != '\0'; i++)
if (str_old[i] == '-')
{
temp = i;
break;
} //找到第一个'-'出现的位置,用temp保存
for (i = 0; i < temp; i++)
{
if ((str_old[i] >= '0' && str_old[i] <= '9') || (str_old[i] >= 'a' && str_old[i] <= 'f') || (str_old[i] >= 'A' && str_old[i] <= 'F'))
{
flag = 1;
break;
}
} //遍历字符串至temp,如果第一个'-'之前存在十六进制数字,那么'-'无效,该数为正
for (i = 0, j = 0; str_old[i] != '\0'; i++)
{
if ((str_old[i] >= '0' && str_old[i] <= '9') || (str_old[i] >= 'a' && str_old[i] <= 'f') || (str_old[i] >= 'A' && str_old[i] <= 'F'))
{
str_new[j] = str_old[i];
j++;
}
} //滤去所有与十六进制数无关的字符
str_new[j] = '\0';
for (j = 0; str_new[j] != '\0'; j++)
{
if (str_new[j] >= '0' && str_new[j] <= '9')
sum = 16 * sum + str_new[j] - '0';
else if (str_new[j] >= 'a' && str_new[j] <= 'f')
sum = 16 * sum + str_new[j] - 'a' + 10;
else if (str_new[j] >= 'A' && str_new[j] <= 'F')
sum = 16 * sum + str_new[j] - 'A' + 10;
} //十六进制转化为十进制数
if (flag == 0)
sum = -sum;
printf("%ld\n", sum);
return 0;
}
运行结果:
二.第八章(指针)
选择题
[8-1]
下列语句定义 px 为指向 int 类型变量的指针,正确的是( )。
A. int x, *px=x;
B. int x, *px=&x;
C. int *px=&x, x;
D. int x, px=x;
答:B
解析:先定义变量,再定义指针,定义指针使用 *。为指针赋值为某个变量的地址时使用 & 符。
[8-2]
以下选项中,对基本类型相同的指针变量不能进行运算的运算符是( )。
A. =
B. ==
C. +
D. -
答:C
解析:
选项 A :“=(赋值)”是对于类型相同的两个指针变量之间常规运算。
选项 B: “==(比较相等)”比较两个指针变量是否相同。
选项 C:“+” 运算是不可以的,因为指针变量是一种特殊的变量,指针变量的值存放的是所指向变量的地址,两个地址相加并不能保证结果为一个有效的地址值,因而在 C 语言中指针变量相加是非法的。
选项 D:“-(减法)”运算两个相同指针变量相减可以获得在之间相隔的同类型元素个数(在某个类型的数组中的应用)。
[8-3]
下列程序的输出结果是( )。
void f(int *p)
{
*p = 5;
}
int main(void)
{
int x = 10, *px = &x;
f(px);
printf("%d#", (*px)++);
printf("%d\n", x);
return 0;
}
A.5#6
B.6#6
C.10#11
D.11#11
答:A
解析:这里考察当是指针作为函数的参数。这里将 px 作为实参,传递给函数的形参 p,就表示 p 也指向变量 x 的地址。在函数中操作指针 p,修改 x 的值为 5。当函数结束后,打印 (*px)++,就是指针 px 对应的变量 x++,5。然后 x 的值自增 1,为 6 。
[8-4]
以下程序的输出结果是( )。
void sub(int x, int y, int *z)
{
*z = y - x;
}
int main(void)
{
int a, b, c;
sub(10, 5, &a);
sub(7, a, &b);
sub(a, b, &c);
printf("%d,%d,%d\n", a, b, c);
return 0;
}
A.5,2, 3
B.5, -2, -7
C.-5,-12, -17
D.-5,-12, - 7
答:D
解析:
自定义函数中主要是修改指针 z 指向的变量的值。
在 main() 中,先定义了 3 个变量 a ,b,c。由于没有初始值,那么系统会自动分配随机值。
然后第一次调用sub() 函数,形参 x 赋值为 10,y 赋值为 5,*z 赋值为 a 的地址,就表示指针 z 指向变量 a 的地址。函数中通过指针 z 修改变量 a 的值为 y-x,就是 -5。
然后第二次调用sub() 函数,形参 x 赋值为 7,y 赋值为 a,就是刚刚的 -5,*z 赋值为 b 的地址,就表示指针 z 指向变量 b 的地址。函数中通过指针 z 修改变量 b 的值为 y-x,就是 -5-7=-12。
然后第三次调用sub() 函数,形参 x 赋值为 a,是 -5 ,y 赋值为 b,就是刚刚的 -12,*z 赋值为 c 的地址,就表示指针 z 指向变量 c 的地址。函数中通过指针 z 修改变量 c 的值为 y-x,就是 -12-(-5)=-7。
[8-5]
若有以下定义,且 0<=i<10 ,则对数组元素的错误引用是( )。·
int i,a[]={0,1,2,3,4,5,6,7,8,9},*p=a;
A. *(a+i)
B. a[p-a+i]
C. p+i
D. *(&a[i])
答:C
解析:p 是指针类型,要想操作 p 指向的变量,需要使用 *
[8-6]
下列程序段的输出结果是( )。
int a[10]={0,1,2,3,4,5,6,7,8,9},*p=a+3;
printf("%d", *++p);
A.3
B.4
C.a[4]的地址
D.非法
答:B
解析:数组 a 的长度为 10,a 指向了数组的基地址,也就是第 1 个元素的地址。指针变量 p,初始值为 a+3,就表示指向了 数组 a 中的第 4 个元素的地址,打印的是 ++p 之后表示指向了第 5 个元素,也就是数值 4。
[8-7]
对于下面的程序段,叙述正确的是( )。
char s[]="china", *p=s;
A. *p与 s[0] 相等
B.数组 s 中的内容和指针变量 p 中的内容相等
C. s 和 p 完全相同
D.数组 s 的长度和 p 所指向的字符串长度相等
答:A
解析:
选项 B,数组 s 中的内容是字符串,p 中的内容是一个地址
选项 C,从指针角度看,s 是常量指针,而 p 不是
选项 D,s 数组的长度是 p 所指向的字符串长度 +1
[8-8]
下面程序段的运行结果是( )。
char s[] = "language", *p = s;
while (*p++ != 'u')
{
printf("%c", *p - 'a' + 'A');
}
A. LANGUAGE
B. ANGU
C. LANGU
D. LANG
答:B
解析:p 指向字符串首地址,while 判断 p 指向的字符是否为 'u',如果是 'u' 则循环结束,然后将字符转换为大写字符。这里的一个关键问题是,while 中 * p++ != 'u',是先判断 * p != 'u',然后 p++,因此判断字符 !='u'后,p 接着就指向了下一个字符 'a',因此 printf 输出的是 'A' ,当 p 指向字符 'g' 时,也不等于 'u',然后 p 指向下一个字符 'u' ,因此会输出 'U'。最终输出的字符是"ANGU"
填空题
[8-1]
输出一维数组最大元素和最小元素的下标。査找一维数组的最大元素和最小元素的下标,分別存放在函数 main() 的 maxsub 和 minsub 变量中。请填空。
void find(int *, int, int *, int *);
int main(void)
{
int maxsub, minsub, a[] = {5, 3, 7, 9, 2, 0, 4, 1, 6, 8};
find(____________);
printf("maxsub=%d, minsub=%d\n", maxsub, minsub);
return 0;
}
void find(int *a, int n, int *maxsub, int *minsub)
{
int i;
*maxsub = *minsub = 0;
for (i = 1; i < n; i++)
{
if (a[i] > a[*maxsub])
____________;
if (a[i] < a[*minsub])
____________;
}
}
答:
a, 10, &maxsub, &minsub
*maxsub = i
*minsub = i
解析:
find() 函数是为了找到最大值和最小值的下标。这里需要 4 个参数,第一个参数是数组,第二个参数是数组的长度,第三个是要存储最大值下标 maxsub,第四个要存储最小值下标 minsub。
所以第二个空,当数组中的元素值大于 最大值下标对应的数组元素值 a[i] > a[*maxsub],那么将 i 的值赋值给最大下标:*maxsub = i 。
第二个空,当数组中的元素值小于 最小值下标对应的数组元素值 a[i] < a[*minsub],那么将 i 的值赋值给最小下标:*minsub = i 。
至于第一个空,就是调用函数。传入对应的实参即可。
[8-2]
数组插值。函数 insert() 的功能是在一维数组 a 中将 x 插入到下标为 i (i>=0)的元素前,如果 i>=元素个数,则 x 插入到末尾,元素个数存放在指针 n 所指向的变量中,插入后元素个数加 1 。请填空。
void insert(int a[], int *n, int x, int i)
{
int j;
if (________)
{
for (j = *n - 1; ________; j--)
________ = a[j];
}
else
{
i = *n;
}
a[i] = ________;
(*n)++;
}
答:
i < *n
j >= i
a[j + 1]
x
解析:
第一空,题目说如果 i>=元素个数,则 x 插入到末尾,所以 if 的条件就是 i < *n,
第二空,循环将 i 后面的元素向后移动一位。所以第二空是 j >= i。
第三空,向后移动一位。就是 a[j + 1] = a[j]
第四空,将 x 存入到 i 的位置上。a[i] = x。
[8-3]
判断回文。先消除输入字符串 s 的前后空格,再判断其是否为“回文”(即字符串正读和倒读都是一样的), 若是则输出 Yes ,否则输出 No。请填空。
char ch, s[80], *p, *q;
int i, j, n;
gets(s);
p = _________;
while (*p == ' ')
{
_________;
}
n = strlen(s);
q = _________;
while (*q == ' ')
{
q--;
}
while (_________ && *p == *q)
{
p++;
_________;
}
if (p < q)
printf("No\n");
else
printf("Yes\n");
答:
s
p++
s + n - 1
p < q
q--
解析:
首先将指针 p 指向字符串 s ,第一个 while 循环结束后,指针 p 会指到字符串非空的第一个字符,也就是说这个循环用于清除字符串的前面的空格。第二个 while 循环结束后,会去除字符串尾部的空格,指针 q 指向最后一个非空的字符。最后一个 while 循环,这里操作两个指针,判断它俩指向的字符是否相同,如果相同,p 从前向后移动,q 从后向前移动,如果最后 p 和 q 能重合,就说明是回文字符串,否则就不是。
[8-4]
最大字符移位。在字符串 str 中找出最大的字符,将在该字符前的所有字符往后顺序移动一位,再把最大字符放在字符串的第一个位置上。如 " knowedge" 变成 "wknoledge" 。请填空。
char max, str[80], *p = str, *q = str;
gets(p);
max = *(p++);
while (*p != '\0')
{
if (max < *p)
{
max = *p;
__________;
}
p++;
}
p = q;
while (__________)
{
__________;
p--;
}
*p = max;
puts(p);
答:
q = p
p != str
*p = *(p - 1)
解析:
第一个空,q 指向当前的最大字符,所以一旦判断 max <*p ,那么就取 p 赋值给 q。一直循环到整个字符串结束, q 就指向了整个字符串中的最大字符。
然后将 p 也设置到 q 指向的位置,然后将 p 前面的字符,每一个都向后移动一位。直到字符串开头,所以循环条件就是 p != str。
最后再将 max 的字符,赋值到字符串开头即可。
[8-5]
字符传送。将字符串 s1 的所有字符传送到字符串 s2 中,要求每传送 3 个字符就再存放一个星号。如字符串 s1 为 "abedefg" ,则字符串 s2 为 `"abe*def*g"`。请填空。
char s1[80], s2[80], *p = s1;
int cnt = 0, k = 0;
gets(p);
while (*p != '\0')
{
s2[k] = *p;
k++;
p++;
cnt++;
if (_________)
{
s2[k] = '*';
_________;
_________;
}
}
s2[k] = '\0';
puts(s2);
答:
cnt == 3
cnt = 0
k++
解析:
每传送 3 个字符,就要放一个星号,所以 cnt 为 3 的时候,放置星号,然后 cnt 要重新置为 0 ,k 要继续 ++ 。
程序设计题
[8-1]
拆分实数的整数与小数部分:要求自定义一个函数 void splitfloat (float x,int *intpart, float *fracpart), 其中 x 是被拆分的实数,* intpart`和 * fracpart 分别是将实数 x 拆分出来的整数部分与小数部分。编写主函数,并在其中调用函数 splitfloat() 。试编写相应程序。
答案代码:
#include <stdio.h>
void splitfloat(float x, int *intpart, float *fracpart);
int main(void)
{
// 习题(8.3.1)
/*
拆分实数的整数与小数部分:要求自定义一个函数 void splitfloat (float x,int *intpart, float *fracpart),
其中 x 是被拆分的实数,* intpart 和 * fracpart 分别是将实数 x 拆分出来的整数部分与小数部分。
编写主函数,并在其中调用函数 splitfloat() 。
*/
float x, fracpart;
int intpart;
printf("input number:");
scanf("%f", &x);
splitfloat(x, &intpart, &fracpart);
printf("intpart=%d\n", intpart);
printf("fracpart=%f\n", fracpart);
return 0;
}
void splitfloat(float x, int *intpart, float *fracpart)
{
*intpart = (int)x;
*fracpart = x - *intpart;
}
运行结果:
[8-2]
在数组中查找指定元素:输入一个正整数 n ( 1<n≤10),然后输入 n 个整数存入数组 a 中,再输入一个整数 x ,在数组 a 中查找 x ,若找到则输出相应的下标,否则显示 Not found。要求定义和调用函 search(int lis[], int n, int x), 在数组 list 中查找元素 x ,若找到则返回相应下标,否则返回 -1,参数 n 代表数组 list 中元素的数量。试编写相应程序。
答案代码:
#include <stdio.h>
int main(void)
{
// 习题(8.3.2)
/*
在数组中查找指定元素:输入一个正整数 n ( 1<n≤10),然后输入 n 个整数存入数组 a 中,再输入一个整数 x ,
在数组 a 中查找 x ,若找到则输出相应的下标,否则显示 Not found。
要求定义和调用函 search(int lis[], int n, int x), 在数组 list 中查找元素 x ,
若找到则返回相应下标,否则返回 -1,参数 n 代表数组 list 中元素的数量。
*/
int i, n, res, x;
int a[10];
int search(int list[], int n, int x);
printf("input n:");
scanf("%d", &n);
printf("input %d number:\n", n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
printf("input x:");
scanf("%d", &x);
res = search(a, n, x);
if (res != -1)
printf("index = %d\n", res);
else
printf("Not found\n");
return 0;
}
int search(int list[], int n, int x)
{
int i;
for (i = 0; i < n; i++)
if (list[i] == x)
return i;
return -1;
}
运行结果:
[8-3]
循环后移:有 n 个整数,使前面各数顺序向后移 m 个位置,移出的数再从开头移入。编写一个函数实现以上功能,在主函数中输入 n 个整数并输出调整后的 n 个数。试编写相应程序。
答案代码:
#include <stdio.h>
void mov(int *x, int n, int m);
int main(void)
{
// 习题(8.3.3)
/*
循环后移:有 n 个整数,使前面各数顺序向后移 m 个位置,移出的数再从开头移入。
编写一个函数实现以上功能,在主函数中输入 n 个整数并输出调整后的 n 个数。
*/
int i, m, n;
int a[80];
printf("input n,m:");
scanf("%d%d", &n, &m);
printf("input %d number:\n", n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
mov(a, n, m);
printf("After move: ");
for (i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
/*函数mov(x,m)实现循环移动的功能,函数形参x的类型是整型指针,形参n和m的类型是int, 函数的类型是void。 */
void mov(int *x, int n, int m)
{
int i, j, k;
for (i = 1; i <= m; i++)
{
k = x[n - 1];
for (j = n - 1; j > 0; j--)
x[j] = x[j - 1];
x[0] = k;
}
}
运行结果:
[8-4]
报数:有 n 个人围成一圈,按顺序从 1 到 n 编好号。从第一个人开始报数,报到 m(m<n)的人退出圈子,下个人从 1 开始报数,报到 m 的人退出圈子。 如此下去,直到留下最后一个人。输入整数 n 和 m ,并按退出顺序输出退出圈子的人的编号。试编写相应程序。
答案代码:
#include <stdio.h>
int main(void)
{
// 习题(8.3.4)
/*
报数:有 n 个人图成一圈,按顺序从 1 到 n 编好号。从第一个人开始报数,报到 m(m<n)的人退出圈子,
下个人从 1 开始报数,报到 m 的人退出圈子。 如此下去,直到留下最后一个人。
输入整数 n 和 m ,并按退出顺序输出退出圈子的人的编号。
*/
int count, i, m, n, no;
int num[50];
int *p;
printf("input n and m: ");
scanf("%d%d", &n, &m);
for (i = 0; i < n; i++)
num[i] = i + 1;
p = num;
count = no = 0;
while (no < n - 1)
{
if (*p != 0)
count++;
if (count == m)
{
no++;
printf("No%d: %d\n", no, *p);
*p = 0;
count = 0;
}
p++;
if (p == num + n)
p = num;
}
p = num;
while (*p == 0)
p++;
printf("Last No is: %d\n", *p);
return 0;
}
运行结果:
[8-5]
使用函数实现字符串复制:输入一个字符串 t 和一个正整数 m, 将字符串 t 中从第 m 个字符开始的全部字符复制到字符串 s 中,再输出字符串 s 。要求自定义并调用函数 void strmcpy(char *s, char *t, int m)。试编写相应程序。
答案代码:
#include <stdio.h>
#include <string.h>
int main(void)
{
// 习题(8.3.5)
/*
使用函数实现字符串复制:输入一个字符串 t 和一个正整数 m, 将字符串 t 中从第 m 个字符开始的全部字符复制到字符串 s 中,再输出字符串 s 。
要求自定义并调用函数 void strmcpy(char *s, char *t, int m)。
*/
char s[80], t[80];
int m;
void strmcpy(char *s, char *t, int m);
printf("input string t:\n");
gets(t);
printf("input number m:");
scanf("%d", &m);
getchar();
if (strlen(t) < m)
printf("error input");
else
{
strmcpy(s, t, m);
puts(s);
}
return 0;
}
void strmcpy(char *s, char *t, int m)
{
t = t + m - 1;
while (*t != '\0')
{
*s = *t;
s++;
t++;
}
*s = '\0';
}
运行结果:
[8-6]
删除字符:输入一个字符串,再输入一个字符 ch , 将字符串中所有的 ch 字符删除后输出该字符串。要求定义和调用函数 delchar(s, c),该函数将字符串 s 中出现的所有 c 字符删除。试编写相应程序。
答案代码:
#include <stdio.h>
#include <string.h>
int main(void)
{
char c;
char str[80];
void delchar(char *str, char c);
printf("input a string:\n");
gets(str);
printf("input a char:");
scanf("%c", &c);
getchar();
delchar(str, c);
printf("result: ");
puts(str);
return 0;
}
void delchar(char *str, char c)
{
int i, j;
i = j = 0;
while (str[i] != '\0')
{
if (str[i] != c)
{
str[j] = str[i];
j++;
}
i++;
}
str[j] = '\0';
}
运行结果:
[8-7]
字符串排序:输入5个字符串,按由小到大的顺序输出。试编写相应程序。
答案代码:
#include <stdio.h>
#include <string.h>
int main(void)
{
int i, j, index;
char sx[5][80], stemp[80];
printf("input 5 string:\n");
for (i = 0; i < 5; i++)
scanf("%s", sx[i]);
for (i = 0; i < 4; i++)
{
index = i;
for (j = i + 1; j < 5; j++)
if (strcmp(sx[j], sx[index]) < 0)
index = j;
strcpy(stemp, sx[i]);
strcpy(sx[i], sx[index]);
strcpy(sx[index], stemp);
}
printf("after sorted:\n");
for (i = 0; i < 5; i++)
puts(sx[i]);
return 0;
}
运行结果:
[8-8]
判断回文:判断输入的一串字符是否为“回文”。所谓“回文”是指顺读和倒读都一样的字符串。如 "XYZYX" 和 "xyzzyx" 都是回文。试编写相应程序。
答案代码:
#include <stdio.h>
int main(void)
{
char s[80];
int mirror(char *p);
printf("input a string:");
gets(s);
if (mirror(s) != 0)
printf("YES\n");
else
printf("NO\n");
return 0;
}
int mirror(char *p)
{
char *q;
q = p;
while (*q != '\0')
q++;
q--;
while (p < q)
{
if (*p != *q)
return 0;
p++;
q--;
}
return 1;
}
运行结果:
[8-9]
分类统计字符个数:输入一行文字,统计其中的大写字母、小写字母、空格、数字以及其他字符各有多少。试编写相应程序。
答案代码:
#include <stdio.h>
int main(void)
{
char s[80];
char *p;
int blank, digit, lower, other, upper;
gets(s);
upper = lower = blank = digit = other = 0;
for (p = s; *p != '\0'; p++)
if (*p >= 'A' && *p <= 'Z')
upper++;
else if (*p >= 'a' && *p <= 'z')
lower++;
else if (*p >= '0' && *p <= '9')
digit++;
else if (*p == ' ')
blank++;
else
other++;
printf("upper: %d lower: %d blank: %d digit: %d other: %d\n", upper, lower, blank, digit, other);
return 0;
}
运行结果:
[8-10]
(选做)输出学生成绩(动态分配):输入学生人数后输入每个学生的成绩,最后输出学生的平均成绩、最高成绩和最低成绩。要求使用动态内存分配来实现。试编写相应程序。
答案代码:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// 习题(8.3.10)
/*
(选做)输出学生成绩(动态分配):输入学生人数后输入每个学生的成绩,最后输出学生的平均成绩、最高成绩和最低成绩。
要求使用动态内存分配来实现。
*/
int n, i;
float *p, sum, max, min, avg;
printf("input students' number n: ");
scanf("%d", &n);
/*为数组p动态分配n个浮点数float 类型大小的空间*/
if ((p = (float *)calloc(n, sizeof(float))) == NULL)
{
printf("Not able to allocate memory.\n");
exit(1);
}
sum = 0.0;
max = -1; /*初始化*/
min = 1000;
printf("input %d students' scores: ", n); /*提示输入n个整数*/
for (i = 0; i < n; i++)
{
scanf("%f", p + i);
sum = sum + *(p + i);
if (min > *(p + i))
min = *(p + i);
if (max < *(p + i))
max = *(p + i);
}
avg = sum / n;
printf("The avg is %f, max is %f, min is %f\n", avg, max, min);
free(p); /*释放动态分配的空间*/
return 0;
}
运行结果:
总结
以上为本篇文章的所有内容,后续将更新各个章节课后习题解析,如想了解更多,请持续关注该专栏。如有疑问或提供意见,请指出,谢谢!!!
文章内容参考: 程序咖
如想观看讲解视频或解析请参考:C语言程序设计第4版(浙大版)何钦铭颜晖著 (chengxuka.cn)程序咖XR实验室是程序咖平台旗下的前沿科技沉浸式面试准备和学习实验室。瞄准「Web3.0」、「元宇宙」、「区块链」、「NFT」、「数字孪生」、「VR/AR/XR」、「DAO」等前沿科技沉浸式课程,带给您最好的学习体验,提升您的职场竞争力。https://www.chengxuka.cn/#/mooc/outline?_id=39&title=C%25E8%25AF%25AD%25E8%25A8%2580%25E7%25A8%258B%25E5%25BA%258F%25E8%25AE%25BE%25E8%25AE%25A1%25E7%25AC%25AC4%25E7%2589%2588%28%25E6%25B5%2599%25E5%25A4%25A7%25E7%2589%2588%29%25E4%25BD%2595%25E9%2592%25A6%25E9%2593%25AD%25E9%25A2%259C%25E6%2599%2596%25E8%2591%2597