浙大版《C语言程序设计》第四版(何钦铭颜晖) 第7章 数组 课后习题答案


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

WX20220412-135428@2x

一、选择题
1.假定 int 类型变量占用两个字节,则以下定义的数组 a 在内存中所占字节数是( )。

int a[10]={10,2,4};

A. 20
B.10
C.6
D.3

答:A

解析:题目中,根据 int a[10] ,表示定义了数组的长度是 10 ,每个变量占用两个字节,一共就是 20 个字节。

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],下标的数值没有越界。

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。

4.设有数组定义:char array[]="China" ; 则数组 array 所占的空间为( )字节。

A.4个
B.5个
C.6个
D.7个

答:C

解析:在题目的定义方式中,系统会自动在数组最后加入一个'\0',表示字符数组的结束,因此数组的长度就是 6 个字节。

5.下述对字符数组的描述中错误的是( )。

A.字符数组可以存放字符串

B.字符数组中的字符串可以整体输入、输出

C.可以在赋值语句中通过赋值运算符"="对字符数组整体赋值

D.不可以用关系运算符对字符数组中的字符串进行比较

答:C

解析:

选项 A 正确,在 C 语言中可以将字符串作为一个特殊的一位字符数组来处理。例如:char array[]="China" ;

选项 B 正确,因为字符数组中直接使用数组名称时数组会退化为指针而且字符串结尾会有“\0”,指针遇到“\0”会结束输入或者输出。用到的代码是: char ch[100]; gets(ch); //整体输入puts(ch);整体输出。(同时这里提个醒字符数组可以进行整体的输入输出,但是整型输出是不可以进行的整体输入输出)

选项 C 不正确。在赋值语句中通过赋值运算符"="对字符数组整体赋值,则就需要用到字符数组名,而对字符数组名进行操作时其会退化为常量指针,而进行赋值时左值必须是可以修改的变量。所以错误。

选项 D 正确。数组名会退化为指针,所以比较的其实就是指针所指向的内存地址的大小,这个跟比较字符串的大小没有关系。

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

二、填空题
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。

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。

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 的位置上。

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 。分析过程如上。

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#

分析:

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.字符串复制。将字符串 str1 的内容复制到字符串 str2 。 假定变量都已正确定义并赋值,请填空。

	i = 0;
	while (___________)
	{
		___________;
		i++;
	}
	___________;

答:

str1[i] != '\0'

str2[i] = str1[i]

str2[i] = '\0'

解析:这里循环复制就可以了。只不过使用 char[] 数组操作字符串,最后一个字符存储 '\0'。

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'。

三、程序设计题
题目1:选择法排序。输入一个正整数 n (1

答案代码:

#include 
int max(int a[], int len);
int main()
{
	// 习题(7.3.1)
	/*
	选择法排序。输入一个正整数 n (1 0; i--)
	{
		int maxid = max(a, i + 1);
		int t = a[maxid];
		a[maxid] = a[i];
		a[i] = t;
	}

	for (i = len - 1; i >= 0; i--)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
	return 0;
}
int max(int a[], int len) //找出数组中最大数
{
	int i, maxid = 0;
	for (i = 1; i < len; i++)
	{
		if (a[i] > a[maxid])
		{
			maxid = i;
		}
	}
	return maxid;
}

运行结果:

WX20220411-153455@2x

题目2:求一批整数中出现最多的数字。输入一个正整数 n(1

答案代码:

#include 
int main()
{
	// 习题(7.3.2)
	/*
	求一批整数中出现最多的数字。输入一个正整数 n(1

运行结果:

WX20220411-163619@2x

再输入一组:

WX20220411-163538@2x

题目3:判断上三角矩阵。输入一个正整数 n(1≤n≤6)和 n 阶方阵 a 中的元素,如果 a 是上三角矩阵,输出 “YES", 否则,输出 “NO"。 上三角矩阵指主对角线以下的元素都为 0 的矩阵,主对角线为从矩阵的左上角至右下角的连线。试编写相应程序。

答案代码:

#include 
int main()
{
	// 习题(7.3.3)
	/*
	判断上三角矩阵。输入一个正整数 n(1≤n≤6)和 n 阶方阵 a 中的元素,如果 a 是上三角矩阵,输出 “YES", 否则,输出 “NO"。
	上三角矩阵指主对角线以下的元素都为 0 的矩阵,主对角线为从矩阵的左上角至右下角的连线。
	*/
	int a[6][6], flag, i, j, n;
	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]);
	flag = 1;
	for (i = 0; i < n; i++)
		for (j = 0; j < i; j++)
			if (a[i][j] != 0)
				flag = 0;
	if (flag)
		printf("YES\n");
	else
		printf("NO\n");
	return 0;
}

运行结果:

WX20220411-160217@2x

WX20220411-160305@2x

题目4:求矩阵各行元素之和。输入 2 个正整数 m 和 n (1≤m≤6,1≤n≤6) ,然后输入矩阵 a ( m 行 n 列 ) 中的元素,分别求出各行元素之和,并输出。试编写相应程序。

答案代码:

#include 
int main()
{
	// 习题(7.3.4)
	/*
	求矩阵各行元素之和。输入 2 个正整数 m 和 n (1≤m≤6,1≤n≤6) ,然后输入矩阵 a ( m 行 n 列 ) 中的元素,
	分别求出各行元素之和,并输出。
	*/

	int a[6][6], i, j, m, n, sum;
	printf("input m,n : ");
	scanf("%d%d", &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 = sum + a[i][j];
		printf("sum of row %d is %d\n", i, sum);
	}
	return 0;
}

运行结果:

WX20220411-160804@2x

题目5:找鞍点。输入 1 个正整数 n ( 1≤n≤6) 和 n 阶方阵 a 中的元素,假设方阵 a 最多有 1 个鞍点,如果找到 a 的鞍点,就输出其下标,否则,输出“NO"。 鞍点的元素值在该行上最大,在该列上最小。试编写相应程序。

答案代码:

#include 
int main()
{
	// 习题(7.3.5)
	/*
	找鞍点。输入 1 个正整数 n ( 1≤n≤6) 和 n 阶方阵 a 中的元素,假设方阵 a 最多有 1 个鞍点,
	如果找到 a 的鞍点,就输出其下标,否则,输出“NO"。 鞍点的元素值在该行上最大,在该列上最小。
	*/

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

运行结果:

WX20220411-161421@2x

再输入一组:

WX20220411-161545@2x

题目6:统计大写辅音字母。输入一个以回车结束的字符串(少于 80 个字符),统计并输出其中大写辅音字母的个数。大写辅音字母是指除 'A','E' ,'I','O', 'U' 以外的大写字母。试编写相应程序。

答案代码:

#include 
int main()
{
	// 习题(7.3.6)
	/*
	统计大写辅音字母。输入一个以回车结束的字符串(少于 80 个字符),统计并输出其中大写辅音字母的个数。
	大写辅音字母是指除 'A','E' ,'T','O', 'U' 以外的大写字母。
	*/

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

运行结果:

WX20220411-162505@2x

题目7:字符串替换。输入一个以回车结束的字符串(少于 80 个字符),将其中的大写字母用下面列出的对应大写字母替换,其余字符不变,输出替换后的字符串。试编写相应程序。
原字母对应字母
A→Z
B→Y
C→X
D→W
...
X→C
Y→B
Z→A

答案代码:

#include 
int main()
{
	// 习题(7.3.7)
	/*
	字符串替换。输入一个以回车结束的字符串(少于 80 个字符),将其中的大写字母用下面列出的对应大写字母替换,其余字符不变,输出替换后的字符串。试编写相应程序。
	原字母对应字母
	A→Z
	B→Y
	C→X
	D→W
	...
	X→C
	Y→B
	Z→A

	*/

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

运行结果:

WX20220411-163031@2x

题目8:字符串转换成十进制整数。输入一个以字符 “#” 结束的字符串,滤去所有的非十六进制字符(不分太小写),组成一个新的表示十六进制数字的字存串,然后将其转换为十进制数后输出。如果过滤后字符串的首字符为 “-“ 代表该数是负数。试编写相应程序。

答案代码:

#include 
int main()
{
	// 习题(7.3.2)
	/*
	求一批整数中出现最多的数字。输入一个正整数 n(1= '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;
}

运行结果:

WX20220411-164100@2x