有偿出电子书及解答!!!!!!!!!!私我
有偿出电子书及解答!!!!!!!!!!私我
有偿出电子书及解答!!!!!!!!!!私我
有偿出电子书及解答!!!!!!!!!!私我
有偿出电子书及解答!!!!!!!!!!私我
新编C语言习题与解析
做习题时发现有些错误答案,写篇博客进行改正记录。不对地方欢迎指正~
使用g++进行编译。
文章目录
第二章·数据类型及其运算
2-2-4
乘除和求余的优先级一样高。 所以正确的解释如下:
2.5+1*7%2/4=2.5+7%2/4=2.5+1/4=2.5+0=2.5。
之后再统一精度。
2-1-17
C. 其中b的表达形式错误,若加上0x1e2b则正确。所以C错误。
D. e后为整数。指数命名规则:e前有数,后有整数。所以D错误。
以下部分为第二章的答案详细解答
将20题和25对比记忆:
答案为:BC
A. 连续赋值,从右至左分割,第一个赋值表达式的左侧是9+e+f为表达式,错误。赋值表达式左侧应该为变量。
B. 逗号表达式,赋值正确。
C. 逗号表达式,赋值正确。
D. 出现的问题和A选项类似,左侧不应该是表达式而是变量。
这里的B选项和上题对应,而且要注意的是25题要选的是表达式不是语句哦。
2-1-80
该题不同编译器给的结果不同,vc++就是上述结果。
gcc的结果为:a=8,x=210,b=1,y=6
第三章·选择语句和循环语句
3-1-12
根据后面选项,可知题目为-1.
3-1-14
A. case后的常量表达式不是整型,且switch后也不是整型;
B. switch(a);后有分号错误;
C. case后的常量表达式不是整型;
D. switch(a+b);后有分号。若无分号,正确答案为D。
3-1-22
少了个S,应该都看得出来。
3-1-23
红色框处应该为分号。
3-2-40
输出部分偶数之和应该直接输出c,而不是c-11。
#include <stdio.h>
int main()
{
int a,b,c;
a=c=0;
for (int i = 0; i < 10; i+=2)
{
a+=i;
b=i+1;
c+=b;
}
printf("even = %d\n",a);
printf("odd = %d\n",c);
} // namespace std;
3-2-56
- j%2==1当判断条件为1的时候输出
- 每个集合之间有逗号(数字之间的逗号可以用个if做一下)
#include<stdio.h>
int main(){
int n,m,i,j,k;
printf("n=");
scanf("%d",&n);
//计算具有子集的个数
m=1;
for(i=1;i<=n;i++){
m=m*2;
}
m--;
for(i=0;i<=m;i++){
printf("{");
j=i;
k=0;
while(j!=0){
if(j%2==1) printf("%d",k);
k++;
j/=2;
}
printf("},");
if((i+1)%5==0) printf("\n");
}
printf("\n");
}
第四章·数组
4-1-3
在定义数组时,定义赋初值的个数等于数组长度,则数组长度可以省略,所以只给部分数组元素赋初值时,对数组的长度声明不能省略。故答案为A、B。
简记:一维数组可以省略,二维数组行能省略,列不能。
4-1-9
这里有一个歧义题目:
书上说:定义静态数组时才会初始化全为0。该定义不是静态数组,故将初值只赋值给前两个元素。
网上说:数组为初始化,中存放的是乱码,但是只要初始化一个数,其余数据自动填充0,所以数组元素都为0。
两者歧义,先按照书上定义的来,另外苏小红书中也提到静态数组定义的时候会将数组元素赋为0。
4-1-16
由于题目中要求输出行列号元素之和为3的数组元素,故正确答案为:x<=3,y<=2,z==3.
4-1-26
我们看第十个判断题:如果想使一个数组中全部元素的值为0,可以写成int a[10]={0*10};。请问这句话的说法是正确的吗?
个人认为: 题目等价于 int a[10]={0},表示只给第一个元素赋初值,后面9个元素值默认为0.
拓展: int a[10]={1*10},是否正确,初始化的结果是什么?
输出结果:10,0,0,0,0,0,0,0,0,0
4-2-20
第五章·指针
5-1-4
该题无正确选项。B具体解释可看5-1-14
第五章的指针是重点,所以按照5-1-10为例简单介绍一下行指针和列指针的使用和区别(我自己也梳理梳理)。ps:该题答案是正确的
首先明确的是当指向一维数组和二维数组时,所需要的指针变量是不同的。
这是因为在指向二维数组的时候总是要经过这样的转换:
- 指向一维数组的指针变量:在C语言规定中,数组名代表数组首地址,而且是一个地址常量,所以指针可以直接指向地址(即数组)
p=a
等价于p=a[0]
. - 指向多维数组的指针变量:
- a+1是跳过一行。因为二维数组名是行指针,加1是跳过一行不是一个元素。
- 只有列指针才是指向“真正”的元素。即指向某一个元素的存储单元。
- 一维数组名表示的是行指针,二维数组名表示的是列指针。
5-2-10
现在是二维数组,二维数组名是行指针,而在二维情况下int *p
是一维的,不能直接将a数组赋值给p,换句话说因为p是指针;a是指向指针的指针,两个无法赋值。
行指针和列指针辨析:
那么行指针和列指针怎么理解呢?我个人理解的是:行指针跳一行,列指针因为已经从行指向了列所以跳一个元素。
对于行指针:其实就是二维数组名的等价代换例如,a[2][2]等价于p[2][2]
对于列指针:
p+1
指向a[0][0]
p+6
指向a[1][1]
以此类推
5-1-11
该题正确答案应该为D:
a='\'
.转义符号后应该包含其他符号,如下表。
b='\xab'
.该类型符合下表中\xhh
类型的二位16进制。
c='\0xab'
.C语言中没有这种形式的转义字符。
d="\017"
.首先\0
看作一个空字符,17作为十进制数字。
这道题还需要注意的是给d分配的是字符串而不是字符,这是因为字符串的首地址可以直接使用指针指向,而字符不行。另外转义字符还需要和八进制、十六进制的表示做区别!
上图参考《李春葆新编C语言习题与解析》12页
5-2-4
5-2-4:
A. p指针指向“are you”字符串。程序段正确
B. a为地址常量,不能进行++a操作。程序段错误
C. a[11]数组内存为11,而st指向的字符串为11+1(最后还有’\0\),数组内存不够。程序段错误
D. a数组未声明多大的数组。程序段错误
5-2-11:
A. p指针指向“are you”字符串。程序段正确
B. a为地址常量,不能进行++a操作。程序段错误
C. a[11]数组内存为11,而st指向的字符串为11+1(最后还有’\0\),数组内存不够。程序段错误
D. p指针指向"w are you"字符串。程序段正确
5-2-36
#include<stdio.h>
#include<string.h>
int main(){
char *ptr1,*ptr2;
ptr1=ptr2="abcde";
while(*ptr2!='\0')
putchar(*ptr2++);
while(--ptr2>=ptr1)
putchar(*ptr2);
putchar('\n');
}
本题答案有误,编译器输出结果为:abcdeedcba
5-3-14
本题答案有误,编译器输出结果为:
greeting[0]=Hello
greeting[1]=Good morning
greeting[2]=How are you
Hello
Good morning
How are you
第六章·函数
6-1-6
B选项正确。
储备知识:
当数组名即地址作为实参时,这三种形式等价。
A) 参数2,数组长度不限。正确
B) 参数2,数组长度41, &a[9] 从9-50是41。正确
C) 参数2,指针用地址调用。正确
D) 参数2,为整型,不能传入地址。不正确
6-3-26
这道题的答案的提问方式错了,应该问的是正确的定义方式。
当用二维数组作为形参时,第一维的大小可以省略,但第二维的大小是不能省略的,必须和实参数组第二维的大小一致。所以正确答案是C。
参考问题答案
6-3-31
这道题应该不是字符串从大到小排序,而是输出字符串长度最大的。对应答案为B则正确。
6-3-34
第三个形式表示错误应为:void fun(double (*b)[22])
6-3-37
输出格式不对,正确格式为:1,3,2
第七章·结构体与共用体
7-4-2
答案应为D。
A. a.next后应该赋值为c的地址;另外这种形式就是不对的,变量a的next应该指向地址,而不是结构体c。
B. 首先p和q链接之后,q.next变为q了,第二句中的q.next和p.next是让他们的指针域互指,不能形成正确的单链表。
C. 该选项当p和q连结之后,反的错误和B类似,p和q指针域互指了。
D. 首先变量a的指针域p指向变量c,然后让变量c的指针域指向变量b。答案正确。
另外,没有变量名时,应该先连后头的,再把前面连上,否则断链了
参考答案链接
对比这两种共用体题型记忆,题目并无错误
7-5-6
#include<stdio.h>
int main(){
union
{
short int i[2];
long k;
char c[4];
}r,*s=&r;
s->i[0]=0x39;
s->i[1]=0x38;
printf("%c\n",s->c[0]);
}
- 首先明确union所有成员共用一个内存单元,大小由空间最大的来决定,同时值共用且会覆盖。上述代码内存空间为4个字节(short int占两个字节,有两个数组元素共四个字节;long也是占用四个字节;char占四个字节,有四个数组元素共四个字节)。
- 然后通过
s->i[0]=0x39; s->i[1]=0x38;
给i进行赋值,也就是i的前两个字节存的是0x39
后两个字节存的0x38
。由于他们使用同一个内存空间c数组也是同样存储。
存储方式如图所示:
有个超级易错的点:一个字节8位,放8个二进制
。并且x86系统支持的小端存放,即低地址放低字节。
- 然后再看输出,
printf("%c\n",s->c[0]);
c以字符的方式输出到屏幕上,也就是以十六进制字符的方式输出到屏幕上。值得注意的是0x39所代表的字符是’9’(在ASCII表中的十六进制)。所以输出的是‘9‘。 - 这样的理解方式我认为比答案解析要清楚。另外值得注意的是题目中给了‘0’字符十进制ASCII码为48,那么我们就可以算得‘0’字符对应十六进制ASCII码为30,从而得到最后可以输出’9’。
7-5-8
#include<stdio.h>
int main(){
union
{
char s[2];
short int i;
}a;
a.i=0x1234;
printf("%x,%x\n",a.s[0],a.s[1]);
}
分析步骤和上面类似:
- 共用体a占用2个字节
- i变量占用两个字节,第一个个字节存储0x34,第二个字节存储0x12。
- 输出格式为十六进制,故分别输出34和12。
总结
:
- 小端存储:低地址低字节,一个字节内顺序存储
- 一个字节放8位!这里很容易错!
- 注意输出格式,是字符还是十六进制。如果是字符记住‘0’字符对应十六进制ASCII码为30。
- 对比记忆,‘0’字符对应十六进制ASCII为30.
这个题再多说一点:如果输出的是整数的话要按照先高地址然后再低地址这样存储。以下面这个题目为例:
#include <stdio.h>
int main()
{
union
{
char i[2];
int k;
}r;
r.i[0]=2;
r.i[1]=0;
printf("%d\n",r.k);
}
运行结果为:2
7-5-9
该题D选项有问题。
第九章·文件
9-1-1
本题答案为D。
A.文本文件的每一个字节放一个ASCII码,代表一个字符。文本文件也称为ASCII码文件,具有可读性。故A选项正确。
B. 由于数据在计算机中是以二进制形式存放的,因此二进制文件中的数据可以直接读出,而不需要像文本文件那样把ASCII码转换成二进制,因此速度较快。故B选项正确。
C. 在文本文件中,数据以ASCII码形式存放的,用户很难判定一个数据到底占几个字节,所以不适合使用随机读写方式。故C选项正确。
D. 数据以二进制形式存放,占有的字节数是固定的,所以可以进行随机读写,当然也可以顺序读写。所以,D选项为所选。
参考答案链接
9-2-11
本题答案为C。
fprintf 存入fp所指向的ASCII文件中,非二进制文件
fread 从二进制文件fp中读取count个数据块
fputc 将字符写到fp指向的文件中去,不一定二进制