浙大版《C语言程序设计》第四版(何钦铭颜晖) 第6章 回顾数据类型和表达式 课后习题答案

103 阅读8分钟

浙大版《C语言程序设计》第四版(何钦铭颜晖) 第6章 回顾数据类型和表达式 课后习题答案

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

WX20220412-135428@2x

一、选择题

1.已知字符 'A' 的 ASCII 码是 65,分别对应八进制数 101 和十六进制数 41,以下( )不能正确表示字符'A'。

A. 'A'

B. '\101'

C. '\x41'

D. '\0x41'

答:D

解析:

十六进制表示字符用 \x 开头。

2.设 a 为整型变量,不能正确表达数学关系: 10<a<15 的 C 语言表达式是( )。

A.10<a<15

B. !(a<= 10lla>= 15)

C. a>10 && a<15

D. !(a<= 10)&&!(a>= 15)

答:A

解析:

在 C 语言中,不能像选项 A 中 10<a<15,这样写。

3.执行以下程序段后,变量 c 的值是( )。

int a=10, b=20, c;
c=(a%2==0)? a:b

A.0

B.5

C.10

D.20

答:C

解析:

a 的初始值是 10,b 的初始值是 20。

a %2 == 0,值为 1。所以取 :前的内容赋值给 c ,即 a 的值。所以为 10。

4.设 x、y 都是整型变量,表达式( )的值不为 9。

A. x=y=8, x+y, x+1

B. x=y=8, x+y, y+1

C. y=8, y+1, x=y, x+1

D. x=8 ,x+1,y=8,x+y

答:D

解析:

选项 A,x=y=8,那么 x 为 8, y 为 8,x+y 为 17,x+1 为 9。

选项 B,x=y=8,那么 x 为 8, y 为 8,x+y 为 17, y+1 为 9。

选项 C,y=8,y+1 为 9 ,x=y,x 为 8, x+1 为 9。

选项 D,x=8,x+1 为 9,y=8,x+y,为 16 。

5.若 a 是整型变量,表达式 ~ (a^~a) 等价于( )。

A. ~a B. 1 C. 0 D. 2

答:C

解析:

首先 a ^ ~a ,为 1。~1 为 0 。

6.若表达式 sizeof( int) 的值为 2 ,则 int 类型数据可以表示的最大整数为( )。

A. 216-1 B. 215-1 C. 232-1 D.231-1

答:B

解析:sizeof用于返回变量或数据类型的字节长度。题目中sizeof(int) 的值为 2 ,说明占 2 个字节,那就是 16 位。所以可以表示最大的整数是 215-1。

二、填空题

1.-127的原码为( )、反码为( )、补码为( )。

答:

1000000001111111

1111111110000000

1111111110000001

解析:

按照原码,反码,补码的规则,正数的原码,反码,补码都相同,即符号位是 0,其余各位表示数值。负数的原码:符号位是 1,其余各位表示数值的绝对值。反码:符号位是 1,其余各位对原码取反。补码:反码加 1 。

2.设 int a=5, b=6; 则表达式 (++a==b--) ?++a:--b 的值是( )。

答:7

解析:

(++a==b--) ?++a:--b,整体是一个条件表达式。

先要看 ?左侧的内容是否为非 0 。所以先计算 (++a==b--),这里 a 的初始值是 5,++a的结果是 6,a 的值经过自加 1 后也为 6。再看 b-- 的值,b 的初始值为 6,b-- 按 6 来算,自减 1 后,b 的值为 5。所以 (++a==b--),即为 6 == 6,为 1 ,那么整个条件表达式取 : 前的值 ,即 ++a 的值,a 的值之前经历过 自增 1 ,已经变为 6 了,那么 ++a 就是 7 。整个表达式执行完,最后 a 的值是 7 ,b 的值是 5。

3.设变量定义如下,则表达式 'x'+1>c 的值是( ),'y'!=c+2 的值是( ),-a-5* b<=d+1 的值是( ), b== (a=2) 的值是( )。

  char c='w'; int a=1, b=2, d=-5;

答:1 0 1 1

解析:

'x'+1>c:'x' 的值为 120,'x'+1 的结果就是 121,'w' 的值为 119。所以 'x'+1>c 成立,结果即为 1 。

'y'!=c+2:'y' 的值为 121,c 为 'w' 值为 119,c+2 的值就是121 ,所以 'y'!=c+2 ,值都是 121 ,不成立,结果即为 0 。

-a-5* b<=d+1:这里先算 <= 左侧的内容,-a-5*b,-1-10 = -11,<= 右侧的内容 d+1,是 -4,-11<=-4,成立,结果即为 1。

b== (a=2):先算 == 右侧的内容,a=2,即为2,b==2,成立,结果即为1。

4.逻辑表达式 x && 1 等价于关系表达式( )。

答:x!=0

解析:x !=0 ,就表示 x 非 0,x && 1,&& 表示并且的意思,1 为非 0,只要 x 非 0 即可。

5.输入 13456# <Enter> ,则输出结果是( )。

  char ch;
  while((ch=getchar())!='#'){
  	putchar(ch); 
  	ch=getchar();
  }

答:135

解析:

while 循环的条件是读入一个字符到 ch 中,如果不是 # ,条件就成立。

所以程序执行后,进入 while 循环后,在判断条件时先读入第一个字符 1 ,循环条件成立,进入循环体,打印 ch 这个字符,此时是 1 ,所以先打印 1 。然后执行到下一行,会再读入一个字符 2 。然后再来判断循环条件,那么此时再读入一个字符 3 ,不是 #,循环条件成立,那么进入循环体,打印 ch ,此时是 3 ,打印输出 3,然后再读入一个字符 4 。然后再来判断循环条件,那么此时再读入一个字符 5,不是 # ,循环条件成立,那么进入循环体,打印 5,然后再读入一个字符 6。然后再来判断循环条件,那么此时再读入一个字符 #,循环条件不成立了,退出 while 循环。最终打印的结果就是 135 。

三、程序设计题

题目1:分类统计字符个数:输入一行字符,统计出其中的英文字母、空格、数字和其他字符的个数。试编写相应程序。

答案代码:

#include <stdio.h>
int main(void)
{
	// 习题(6.3.1)
	/*
	分类统计字符个数:输入一行字符,统计出其中的英文字母、空格、数字和其他字符的个数。
	*/
	char ch;
	int letter = 0, digit = 0, blank = 0, other = 0;
	printf("input string:");
	while (ch != '\n')
	{
		scanf("%c", &ch); //可以加入getchar(); 用于读入并舍弃换行符,但此处是循环取值,不可以加 ,可参考课本P056 例3-7
		if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
		{
			letter++;
		}
		else if (ch >= '0' && ch <= '9')
		{
			digit++;
		}
		else if (ch == ' ')
		{
			blank++;
		}
		else
		{
			other++; //包括输入字符结束的那个回车
		}
	}
	printf("letter= %d,digit= %d,blank= %d,other= %d\n", letter, digit, blank, other);

	return 0;
}

运行结果:

WX20220411-105907@2x

题目2:使用函数累加由 n 个 a 构成的整数之和:输入两个正整数 a 和 n ,求a+a+aa+aaa+aa...a ( n 个 a ) 之和。要求定义并调用函数 fn(a, n), 它的功能是返回 aa...a (n个a)。例如,fn(3, 2) 的返回值是 33 。试编写相应程序。

答案代码:

#include <stdio.h>
int fn(int a, int n)
{
	int i, sum = 0;
	for (i = 1; i <= n; i++)
	{
		sum += a;
		a = a * 10;
	}
	return sum;
}

int main(void)
{
	// 习题(6.3.2)
	/*
	使用函数累加由 n 个 a 构成的整数之和:输入两个正整数 a 和 n ,求a+a+aa+aaa+aa...a ( n 个 a ) 之和。
	要求定义并调用函数 fn(a, n), 它的功能是返回 aa...a (n个a)。
	例如,fn(3, 2) 的返回值是 33 。
	*/
	int n, a, sum = 0;
	printf("input a,n:");
	scanf("%d%d", &a, &n);
	while (n != 0)
	{
		sum += fn(a, n);
		n--;
	}
	printf("sum= %d\n", sum);

	return 0;
}

运行结果:

WX20220411-113149@2x

题目3:使用函数输出指定范围内的完数:输入两个正整数 m 和 n (1≤m,n≤1 000),输出 m~n 之间的所有完数,完数就是因子和与它本身相等的数。要求定义并调用函数 factorsum( number),它的功能是返回 number 的因子和。例如,factorsum(12) 的返回值是 16(1+2+3+4+6)。试编写相应程序。

答案代码:

#include <stdio.h>

// 获取 number 的因子的和
int factorsum(int number)
{
	int i, sum = 0;
	for (i = 1; i <= number / 2; i++)
	{
		if (number % i == 0)
		{ // number是i的倍数
			sum += i;
		}
	}
	return sum;
}
int main(void)
{
	// 习题(6.3.3)
	/*
	使用函数输出指定范围内的完数:输入两个正整数 m 和 n (1≤m,n≤1 000),输出 m~n 之间的所有完。
	完数就是 因子和 与它本身相等的数。要求定义并调用函数 factorsum( number),它的功能是返回 number 的因子和。
	例如,factorsum(12) 的返回值是  16(1+2+3+4+6)。
	*/
	int m, n, j, result = 0;
	printf("input m,n(m>=1,n<=10000):");
	scanf("%d%d", &m, &n);
	printf("%d~%d之间的完数为:", m, n);
	for (j = m; j <= n; j++)
	{
		result = factorsum(j);
		if (result == j)
		{
			printf("%6d", j);
		}
	}

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

运行结果:

WX20220411-115340@2x

题目4:使用函数输出指定范围内的斐波那契数:输入两个正整数 m 和 n (1≤m, n≤10 000) , 输出 m~n 之间所有的斐波那契数。斐波那契序列(第 1 项起): 1 1 2 3 5 8 13 21... 要求定义并调用函数 fib(n),它的功能是返回第 n 项斐波那契数。例如,fib(7) 的返回值是 13。试编写相应程序。

答案代码:

#include <stdio.h>
/*int fib(int n)//返回斐波那契数列第n项
{//递归
	if(n==1||n==2){//第一项和第二项结果都为1,返回1
		return 1;
	}
	else return fib(n-1)+fib(n-2);//从第三项开始,等于前两项之和
}*/
int fib(int n) //非递归,更易理解
{
	int x1 = 1, x2 = 1, x = 0, i;
	if (n < 3)
	{
		return 1;
	}
	for (i = 3; i <= n; i++) 
	{
		x = x1 + x2;
		x1 = x2;
		x2 = x;
	}
	return x;
	
}

int main(void)
{
	// 习题(6.3.4)
	/*
	使用函数输出指定范围内的斐波那契数:输入两个正整数 m 和 n (1≤m, n≤10 000) , 输出 m~n 之间所有的斐波那契数。
	斐波那契序列(第 1 项起): 1 1 2 3 5 8 13 21... 要求定义并调用函数 fib(n),它的功能是返回第 n 项斐波那契数。
	例如,fib(7) 的返回值是 13。
	*/
	int m, n,i, count = 0;;
	printf("input m,n(m>=1,n<=10000):");
	scanf("%d%d", &m, &n);
	for (i = 1; fib(i) <= n; i++) { //数列到<=n时终止循环,不然会死循环
		if (fib(i) >= m){ //固定在m~n之间
			count++; //记录数列的项数
			printf("%6d", fib(i));
		}
	}
	if (count == 0){
		printf("No Fibonacci number\n");
	}
  	printf("\n");
	return 0;
}

运行结果:

WX20220411-122608@2x

题目5:使用函数验证哥德巴赫猜想:任何一个不小于 6 的偶数均可表示为两个奇素数之和。例如 6=3+3,8=3+5,... ,18=5+13。将 6~100 之间的偶数都表示成两个素数之和。 打印时一行打印5组。试编写相应程序。

答案代码:

#include <stdio.h>
#include <math.h>
int prime(int m);
int main(void)
{

	// 习题(6.3.5)
	/*
	使用函数验证哥德巴赫猜想:任何一个不小于  6 的偶数均可表示为两个奇素数之和。
	例如 6=3+3,8=3+5,... ,18=5+13。将 6~100 之间的偶数都表示成两个素数之和。
	打印时一行打印5组。
	*/
	//这里我们的m、n的值已经给定了,当然也可以自己输入
	int i, m = 6, n = 100, count;
	//循环区间,都是偶数所以 m+=2
	for (m = 6; m <= n; m += 2)
	{
		//初始化i=3,最小奇素数是3
		for (i = 3; i <= m; i += 2)
		{
			//奇数不一定为素数,所以需要判断
			if (prime(i) && prime(m - i))
			{
				printf("%d=%d+%d\t\t", m, i, m - i);
				count++;
				if (count % 5 == 0)
				{
					printf("\n"); //每行打印 5 个
				}
			}
		}
	}

	return 0;
}

int prime(int m)
{
	//只有1和它本身能被其整除,1不是素数,2是素数
	int i;
	if (m == 1)
	{
		return 0;
	}
	else
	{
		for (i = 2; i <= sqrt(m); i++)
		{
			if (m % i == 0)
			{
				return 0;
			}
		}
		return m;
	}
}

运行结果:

WX20220411-141114@2x

WX20220411-141059@2x

WX20220411-141030@2x

题目6:使用函数输出一个整数的逆序数:输入一个整数,将它逆序输出。要求定义并调用函数 reverse(number),它的功能是返回 number 的逆序数。例如,rever(12345) 的返回值是 54321。试编写相应程序。

答案代码:

#include <stdio.h>
int reverse(int number);
int main(void)
{

	// 习题(6.3.6)
	/*
	使用函数输出一个整数的逆序数:输入一个整数,将它逆序输出。
	要求定义并调用函数 reverse(number),它的功能是返回 number 的逆序数。
	例如,rever(12345) 的返回值是 54321。
	*/
	int in = 12345, res;
	printf("input a number:");
	scanf("%d", &in);
	res = reverse(in);
	printf("%d\n", res);
	return 0;
}
int reverse(int number)
{
	int flag, res;
	if (number >= 0)
		flag = 1;
	else
	{
		flag = -1;
		number = -number;
	}
	res = 0;
	do
	{
		res = res * 10 + number % 10;
		number /= 10;
	} while (number != 0);
	return flag * res;
}

运行结果:

WX20220411-141629@2x

题目7:简单计算器:模拟简单运算器的工作,输入一个算式(没有空格),遇等号”=” 说明输入结束,输出结果。假设计算器只能进行加、减、乘、除运算,运算数和结果都是整数,4 种运算符的优先级相同,按从左到右的顺序计算。例如,输入 “1+2*10-10/2=” 后,输出 10。试编写相应程序。

答案代码:

#include <stdio.h>
int main(void)
{

	// 习题(6.3.7)
	/*
	简单计算器:模拟简单运算器的工作,输入一个算式(没有空格),遇等号”=” 说明输入结束,输出结果。
	假设计算器只能进行加、减、乘、除运算,运算数和结果都是整数,4 种运算符的优先级相同,按从左到右的顺序计算。
	例如,输入 “1+2*10-10/2=” 后,输出 10。
	*/

	int a, b, sum = 0;
	char ch;
	printf("输入一个算式:");
	scanf("%d", &a); //取输入算式的第一个数
	while ((ch = getchar()) != '=')
	{
		scanf("%d", &b); //取算式的第二个数 ,取算式的第三个数
		switch (ch)
		{ //判断运算符
		case '+':
			sum = a + b;
			break; //每次一个运算符就结束,再赋值,就能满足从左到右(从整个输入的那个大算式看),加减乘除看似违背先乘除再加减的法则
		case '-':
			sum = a - b;
			break;
		case '*':
			sum = a * b;
			break;
		case '/':
			if (b != 0)
			{
				sum = a / b;
			}
			break;
		default:
			printf("error");
			return 0; //如果不是运算符直接结束程序
		}
		a = sum; //前两个数算完后,需要把sum赋给a再次进入循环
	}
	printf("%d\n", a);
	return 0;
}

运行结果:

WX20220411-142553@2x

题目8:统计一行字符,将每个单词的首字母改为大写后输出。所谓“单词”是指连续不含空格的字符串,各单词之间用空格分隔,空格数可以是多个,试编写相应程序。

答案代码:

#include <stdio.h>
int main(void)
{

	// 习题(6.3.8)
	/*
	统计一行字符,将每个单词的首字母改为大写后输出。
	所谓“单词”是指连续不含空格的字符串,各单词之间用空格分隔,空格数可以是多个
	*/

	int word = 0; //满足非空格字符转换条件
	char ch;
	while ((ch = getchar()) != '\n')
	{
		if (ch == ' ')
		{
			word = 0; //符合多空格也可以满足条件,同时在此条件下,进行字符转换
		}
		else if (word == 0)
		{ //字符非空格,此时word(定义的时候的)=0,判断并转化为大写字母
			if (ch >= 'a' && ch <= 'z')
			{
				ch = ch - 32;
				word = 1; // 在没遇到空格时,小写输出 ,同时保证只输出一个大写字母
			}
		}
		putchar(ch); //输出大写字母后,Word=1,第一个if不进,第一个else也不进,直接到这原样输出字符(即小写)
	}
	printf("\n");
	return 0;
}

运行结果:

WX20220411-143523@2x