C语言阶段性测试错题纠正与拓展

引言: 在2024年4月26日,我进行了C语言知识 的**"期末考试"** 。通过这次考试,我发现了我的知识漏洞。所以,我写下这篇博客来记录我的错题 ,并进行纠正 ,然后对于以前遗忘知识的回顾

更多有关C语言的知识详解可前往个人主页:计信猫

目录

一,选择题

1,第一题

2,第二题

3,第三题

4,第四题

5,第五题

二,编程题

1,第一题

2,第二题

三,遗忘知识的回顾

1,整型提升和算术提升

Ⅰ,整型提升例题

[​编辑 四,勉励自己](#编辑 四,勉励自己)


一,选择题

1,第一题

原因分析: 在刚看到这道题时,我其实就已经想到了解题的关键,那就是以前所讲到的unsigned char类型的变量的取值范围,如下图:

可是,就在我进行对i值的不断减三时,我好似发现了一个可以秒杀这道题的地方,那就是unsigned char无符号整型 ,那这个值i就永远不可能为负数对吧,那退出for循环 的条件肯定永远都不会被满足啊,那么不直接就死循环了吗?那答案就是B啊。

所以这道题我就败在了看题的准确度上,仔细读题,才发现for循环的判断条件是i>0,那么也就意味着,i=0时也可以退出循环

题目正解:正如前面所提到的unsigned char类型 的取值范围只可以为0~255 ,所以i 初始化为7,那么对其不断地减去三,i的值则会如下变化:

那么每减去一次三,就**++j**,那么具体的减三次数如下图所示:

那么2+1+84+1+85=173 次,所以答案应该选C

2,第二题

原因分析: 说实话,这道题错了真该挨巴掌。我当时其实也是分析出来了,x 首先为1,经过printf语句 后,打印x 值为1,之后x 加一为2,通过while循环 判断条件后x又减一为1,如此往复循环,那么应该是陷入了死循环 。但是我当时脑子一抽,认为A选项 的1表示的就是死循环 的打印1,只是太长了,就没有全部写出来。现在一回想真的是后悔莫及啊!

**题目正解:**直接上图,不废话了:

所以如图所示,1,2过程一直循环 ,始终跳不出while循环,故死循环打印1,答案选D。

3,第三题

原因分析: 这道题我错的原因是知识点掌握不牢固,感觉每一句话都有模有样很有道理,最后迫不得已扣了字眼 ,认为D选项 不对,一个普普通通的**#define的宏定义** 这么简单的写法,怎么可能比函数 (如此强大的工具)效率更高?而事实证明我还是错了,计算机语言做题是十分严谨的,不能去抠字眼,每一道题的答案都要选的有根有据。

题目正解:这道题虽然涉及到了C++ 的语法知识,但是通过排除法 还是可以做出来的。从我的笔记来看,我所能归纳出的#define宏的优缺点如下:

优点:

1,宏的规模和速度更胜于函数一筹

2,宏的类型与参数的类型无关

缺点:

1,宏在替换时会延长代码

2,宏无法通过调试判断是否出错

3,宏无类型,不严谨

4,宏会带来运算符优先级的问题

所以根据如上归纳,选项ACD 都是对的,那么排除法就是选B了。

4,第四题

原因分析:这道题的错误原因是知识点掌握错误,而导致了这道题的错误,我的错误笔记如下:

做这道题时,我还保留着错误的认知,认为int*为4个字节,char*为1个字节 ,那么不就大小不同吗?所以我就选择了错误答案B 。(现在错误的笔记已被改正)

**题目正解:**我们直接在x86和x64的环境下进行代码实操就行了:

cpp 复制代码
#include <stdio.h>
int main()
{
	printf("%zd\n", sizeof(int*));
	printf("%zd\n", sizeof(char*));
	printf("%zd\n", sizeof(float*));
	printf("%zd\n", sizeof(double*));
	printf("%zd\n", sizeof(short*));
	printf("%zd\n", sizeof(long*));
	return 0;
}

x86环境:

x64环境:

可以看出,指针变量的大小只与平台有关,32位机为4,64位机则为8 。而这道题真正错误的是A选项 ,当我们使用free函数 释放掉某个指针所指向的内容时,该指针并不会自动置为NULL ,必须我们手动置空

5,第五题

**原因分析:**这道题错误的原因也是我的知识点掌握不牢固,别无其他原因。

**题目正解:**我将如下归纳预处理,编译,链接,执行的作用:

一,预处理:展开宏定义,展开头文件,甚至进行更多预处理指令操作(如 #error #pragma #line等预处理指令)。

二,编译:将预处理后的⽂件进⾏⼀系列的:词法分析、语法分析、语义分析及优化,发现语法错误,⽣成相应的汇编代码⽂件。

三,链接:地址和空间分配,符号决议和重定位等这些步骤,链接解决的是⼀个项⽬中多⽂件、多模块之间互相调⽤的问题(于此中发现函数未被定义)。

四,执行:不会引发调试器或测试框架,只是简单地启动应用程序并按照程序代码的逻辑执行代码。

二,编程题

1,第一题

题目正解:首先,我们可以使用以前学到的%10来获取数字的最后一位,/10来去掉数字的最后一位 ,然后,再将所得到的数字以字符的形式储存到字符数组 中,并且每隔三个字符,就额外储存一个",",最后,我们再将字符串打印出来就可以了。那么代码如下:

cpp 复制代码
#include <stdio.h>
int main()
{
	int input = 0;
	scanf("%d", &input);
	char arr[100] = { 0 };
	int save = 0;
	int i = 0;
	int count = 0;
	while (input)
	{
		if (count != 0 && count % 3 == 0)
		{
			arr[i++] = ',';
		}
		save = input % 10;//获取数字的最后一位
		input /= 10;//删除数字的最后一位
		arr[i++] = save + '0';//将得到的数字以字符形式储存
		count++;
	}
	i -= 1;//在while循环最后一次时,i++使i多了个1,所以要将i减1
	printf("%s", arr);
	return 0;
}

2,第二题

题目正解:对于这道题目,我们的思路就是首先创造两个字符数组 ,我们**将第一个字符数组的每一个字符于第二个字符数组中遍历,如果第二个字符数组中有该字符,则不打印;反之,就打印该字符。**所以代码如下:

cpp 复制代码
#include<stdio.h>
int is_exist(char ch, char arr[])
{
	int i = 0;
	while (arr[i])
	{
		if (arr[i] == ch)
		{
			//在第二个字符串中
			return 0;
		}
		i++;
	}
	//不在第二个字符串中
	return 1;
}
int main()
{
	char arr1[101] = { 0 };
	char arr2[101] = { 0 };
	//获得字符串放入两个字符数组
	gets(arr1);
	gets(arr2);
	int i = 0;
	while (arr1[i])
	{
		if (is_exist(arr1[i], arr2))
		{
			printf("%c", arr1[i]);
		}
		i++;
	}
	return 0;
}

三,遗忘知识的回顾

1,整型提升和算术提升

在考试中,曾有这么一道题:

而这道题中,就涉及到了整型提升和算术提升 的知识点。整型提升: 当变量类型的级别低于int 时,算数运算时就会将变量的类型提升为int。算术提升: 当变量类型的级别高于int 时,算数运算时就会将变量的类型提升为更高的类型。

如此,答案为D选项

Ⅰ,整型提升例题

那我们现在来看一道与整型提升有关的例题:

cpp 复制代码
#include<stdio.h>
int main()
{
	char a = 5;
	char b = 28;
	char sum = a + b;
	printf("%d\n", sum);
	printf("%c\n", sum);
	return 0;
}

那么这段代码的输出结果是什么呢?

题目解答: 这道题之中,我们将数字228 分别赋给字符变量ab ,后面再执行a+b 并将结果赋值给sum 。那么很明显,在相加的时候,就会发生前面是所提到的整型提升

所以sum=a+b33 ,再将33 对应的阿斯克码值 换算出为**'!'**,故打印出的结果如下:

小问题的解答: 在做这道题时,其实我就会想到一个问题,我们使用字符类型来定义变量a,b和sum,为什么我们却使用整型变量来初始化它们呢?这不就乱套了吗?

其实,这样初始化并没有错误。因为在计算机中,任何数据都是以二进制代码进行储存 的,而每一个字符都有自己对应的阿斯克码值阿斯克码值 不就是整型数字吗?那么我们就可以理解为其实字符变量类型储存的其实也是数字 ,所以我们拿整型对某个字符变量初始化并无不妥。

请注意!如下两种初始化是有区别的!

cpp 复制代码
#include<stdio.h>
int main()
{
	char a = 0;//将数字0初始化a,0的阿斯克码值所对应的字符为NULL(无法被打印)
	char b = '0';//将字符0初始化b
	printf("%c\n", a);
	printf("%c\n", b);
	return 0;
}

代码一走,结果如下:

四,勉励自己

虽然这次考试成绩不理想,但是经过这次的写博客进行总结,感觉学到了很多东西,越来越上道了

虽然这篇博客的技术含量不高,但是对我来说意义重大 。这篇博客不仅让我搞懂了以前没有搞懂的知识 ,并且还让我有了以前上高中时,对着自己没考好的数学卷子改错纠错记错题的感觉 ,这种记错题的好习惯真的让我受益匪浅。加油吧,每天学习一点点,百万年薪正等着我呢!!!

相关推荐
Dontla10 分钟前
Rust泛型系统类型推导原理(Rust类型推导、泛型类型推导、泛型推导)为什么在某些情况必须手动添加泛型特征约束?(泛型trait约束)
开发语言·算法·rust
Neophyte06081 小时前
C++算法练习-day40——617.合并二叉树
开发语言·c++·算法
慕容复之巅1 小时前
基于MATLAB的条形码的识别图像处理报告
开发语言·图像处理·matlab
zqzgng1 小时前
Python 数据可视化pilot
开发语言·python·信息可视化
写bug的小屁孩1 小时前
websocket初始化
服务器·开发语言·网络·c++·websocket·网络协议·qt creator
Dr_eamboat1 小时前
【Java】枚举类映射
java·开发语言·python
代码小鑫2 小时前
A031-基于SpringBoot的健身房管理系统设计与实现
java·开发语言·数据库·spring boot·后端
五味香2 小时前
Linux学习,ip 命令
linux·服务器·c语言·开发语言·git·学习·tcp/ip
欧阳枫落2 小时前
python 2小时学会八股文-数据结构
开发语言·数据结构·python
何曾参静谧2 小时前
「QT」文件类 之 QTextStream 文本流类
开发语言·qt