【C语言16天强化训练】从基础入门到进阶:Day 12
🔥个人主页:艾莉丝努力练剑
❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、洛谷刷题、C/C++基础知识知识强化补充、C/C++干货分享&学习过程记录
🍉学习方向:C/C++方向学习者
⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平
前言:距离我们学完C语言已经过去一段时间了,在学习了初阶的数据结构之后,博主还要更新的内容就是【C语言16天强化训练】,之前博主更新过一个【C语言刷题12天IO强训】的专栏,那个只是从入门到进阶的IO模式真题的训练。【C语言16天强化训练】既有IO型,也有接口型。和前面一样,今天依然是训练五道选择题和两道编程算法题,希望大家能够有所收获!
目录
1.1 题目1
1.2 题目2
1.3 题目3
1.4 题目4
1.5 题目5
二、两道算法题
2.1 数字颠倒
2.1.1 题目理解
2.1.2 思路
2.1.3 实现(C/C++)
2.2 单词倒排
2.2.1 题目理解
2.2.2 思路
2.2.3 实现(C/C++)
结尾
一、五道选择题
1.1 题目1
题干:请阅读以下程序,其运行结果是( )
int main()
{char c='A';if('0'<=c<='9') printf("YES");else printf("NO");return 0;
}
A. YES B. NO C. YESNO D. 语句错误
解析:正确答案就是A选项。
'0'<=c<='9'并非判断x大于等于字符0,小于等于字符9,而是先执行'0'<=c,使用这个表达式的结果再和'9'比较,'0'的ASCII码值是48,'A'的ASCII码值是'65',故'0'<c是真值1,1无疑是小于字符'9'的,最终是真,即选项A“YES”。
1.2 题目2
题干:假设编译器规定 int 和 short 类型长度分别为32位和16位,若有下列C语言语句,则 y 的机器数为( )
unsigned short x = 65530;
unsigned int y = x;
A. 0000 7FFA B. 0000 FFFA C. FFFF 7FFA D. FFFF FFFA
解析:正确答案就是B选项。
unsigned short类型的x变量2个字节保存了65530,十六进制形式为0xFFFA,x给y赋值时会整型提升,而无符号数在提升时高位补0,其实就相当于把x的值放在了y的低2个字节的空间中,故选B。
1.3 题目3
题干:下列程序的输出结果是什么( )
#include<stdio.h>
int main()
{int n = 1001;int ans = 0;for(int i = 1; i <= n; ++i){ans ^= i % 3;}printf("%d",ans);return 0;
}
A. -2 B. 0 C. 1 D. 2
解析:正确答案就是B选项。
可以这样解释:
i % 3 的值按1、2、0循环,可推算出ans按1、3、3、2、0、0循环,循环进行1001次,而1001%6=5,也就是ans按规律得到的第5个数为最终结果,故ans=0。
也可以这样解释:
循环计算1001次 i % 3 的异或。i % 3 的值每3次循环(0,1,2)重复,异或结果:0^1^2=3(二进制11,即3),但每3次重复。1001/3=333组余2(最后余i=1000和1001:1000%3=1,1001%3=2)。
每组3次异或结果为3(但ans初始0),每组的异或值:0^1^2=3,但连续异或333组:由于3的二进制为11,异或多次时,取决于次数。
实际上,每两组异或会抵消:3^3=0,所以333组(奇数组)异或后为3,再异或最后两个(1和2):3^1^2=0(因为3^1=2, 2^2=0)。
因此最终ans=0。
1.4 题目4
题干:C语言中,下列运算符优先级最高的是 ( )
A. ! B. % C. >> D. ==
解析:正确答案就是A选项。
单目运算符的优先级通常都比较高,具体情况可查阅运算符优先级表格。
运算符优先级:
!(逻辑非)优先级最高(单目运算符),
%(取模)和 >>(右移)为算术运算符,优先级次之,
==(相等)优先级较低。
因此优先级最高的是 ! 。
1.5 题目5
题干:要使 a 的低四位翻转,需要进行操作是( )
A. a | 0xF B. a & 0xF C. a ^ 0xF D. ~a
解析:正确答案就是C选项。
十六进制数0xF是4位1,参与运算时整型提升,高位都是0。低四位和1异或,0^1是1,1^1是0;高位和0异或,0^0是0,1^0是1。故而可以通过异或F使得a的低四位翻转,并保持高位不变。
也可以这样解释:
要使低四位翻转(即0变1,1变0),应使用异或操作:a ^ 0xF (0xF二进制为00001111,异或后低四位取反,高位不变)。
其他:
a | 0xF 低四位置1,a & 0xF 只保留低四位,~a 所有位取反。
选择题答案如下:
1.1 A
1.2 B
1.3 B
1.4 A
1.5 C
校对一下,大家都做对了吗?
二、两道算法题
2.1 数字颠倒
牛客网链接:HJ11 数字颠倒
题目描述:
2.1.1 题目理解
为了解决这个问题,我们需要将给定的非负整数颠倒后以字符串形式输出,包括任何前导零。关键在于如何处理数字的每一位,并确保颠倒后的字符串正确表示原数字的逆序。
2.1.2 思路
1、问题分析:输入是一个非负整数,需要将其数字顺序颠倒后输出。
例如,输入1516000应输出0006151。
2、关键点:直接使用数学运算逐位提取数字,从最低位开始输出,这样可以自然形成颠倒后的字符串,包括前导零。
3、算法选择:通过循环取模运算获取最后一位数字,并将其转换为字符输出,然后通过整数除法移除已处理的数字。重复此过程直到所有数字处理完毕。
4、复杂度分析:该算法的时间复杂度为O(d),其中d是数字的位数,因为每个数字处理一次。空间复杂度为O(1),仅使用固定空间。
2.1.3 实现(C/C++)
这道题是IO型的,下面是C语言的模版(如果是IO型就可以不用管它们了)——
代码演示:
//C语言实现
#include <stdio.h>int main()
{int n;scanf("%d", &n);if (n == 0){printf("0");}else{while (n){printf("%c", '0' + n % 10);n /= 10;}}return 0;
}
时间复杂度:O(n);
空间复杂度:O(1)。
1、输入处理:读取输入的整数n。
2、特殊情况处理:如果n为0,直接输出"0"。
3、数字颠倒:对于非零的n,通过循环每次取n的最后一位数字(使用取模运算),转换为对应的字符并输出。随后通过整数除法移除已处理的数字。
4、输出结果:循环直到所有数字处理完毕,输出的字符串即为颠倒后的数字,包括任何前导零。
这种方法高效且直接,确保了正确性和简洁性。
当然还有比这个更加简洁的写法:do while——
代码演示:
//C语言实现——方法2
#include <stdio.h>
int main()
{int a;scanf("%d", &a);do {printf("%d", a % 10);a /= 10;} while (a);return 0;
}
时间复杂度:O(n);
空间复杂度:O(1)。
当然还有一种写法:
代码演示:
//C语言实现——方法3
#include <stdio.h>
int main()
{int num;while (~scanf("%d", &num)) {if (num == 0) {//0的情况特殊处理,因为0不会进入while循环计算余数,因此不会被打印printf("%d", num % 10);continue;} while(num > 0) {printf("%d", num % 10);//打印一个数字的个位数 129 % 10 得到9num /= 10;//通过除以10的方式去掉个位数 例如:129/10 得到12}printf("\n");} return 0;
}
时间复杂度:O(n);
空间复杂度:O(1)。
我们学习了C++之后也可以尝试用C++来实现一下,看看自己前段时间C++学得怎么样——
代码演示:
//C++实现
#include <iostream>
using namespace std;int main()
{int n;cin >> n;if (n == 0){cout << '0';}else{while (n){cout << char('0' + n % 10);n /= 10;}}return 0;
}
时间复杂度:O(n),空间复杂度:O(1)。
我们目前要写出来C++的写法是非常考验前面C++的学习情况好不好的,大家可以尝试去写一写,优先掌握C语言的写法,博主还没有介绍C++的算法题,之后会涉及的,敬请期待!
2.2 单词倒排
牛客网链接:HJ31 单词倒排
题目描述:
2.2.1 题目理解
我们需要将输入字符串中的单词(仅由大小写字母组成)提取出来,然后逆序输出,单词之间用单个空格分隔。非字母字符作为分隔符。
2.2.2 思路
1、读取输入:使用
getline
(C++)或fgets
(C)读取整行输入。2、提取单词:遍历字符串中的每个字符,如果是字母则添加到当前单词,否则结束当前单词(如果非空)并添加到单词列表。
3、处理最后一个单词:在遍历结束后,检查是否还有未添加的单词。
4、逆序输出:从单词列表的末尾开始向前输出,单词之间用空格分隔。
这种方法确保了单词的正确提取和逆序输出,同时处理了各种非字母分隔符的情况。
2.2.3 实现(C/C++)
这道题是IO型的,下面是C语言的模版(如果是IO型就可以不用管它们了)——
代码演示:
//C语言实现
#include <stdio.h>
#include <ctype.h>
#include <string.h>int main()
{char s[10001]; // 总字符长度不超过10^4fgets(s, sizeof(s), stdin);char words[5000][21]; // 假设最多5000个单词,每个单词最长20int count = 0;int idx = 0;int len = strlen(s);for (int i = 0; i < len; i++){if (isalpha(s[i])){// 将字母添加到当前单词words[count][idx++] = s[i];}else{if (idx > 0){words[count][idx] = '\0'; // 结束当前单词count++;idx = 0;}}}if (idx > 0){ // 处理最后一个单词words[count][idx] = '\0';count++;}// 逆序输出单词for (int i = count - 1; i >= 0; i--){printf("%s", words[i]);if (i > 0) printf(" ");}printf("\n");return 0;
}
时间复杂度:O(n*m),空间复杂度:O(1)。
这个的代码量还是很大的,可以再简洁一点——
代码演示:
//C语言实现——方法2
#include <stdio.h>
#include <string.h>
int main()
{char str[10001] = { 0 };//题目要求:字符串最长10000int row = 0;while (gets(str) > 0) {char* ptr = str;char* word[10000] = { NULL };while (*ptr != '\0') {//如果是个字母字符,则是单词的起始字符if (('z' >= *ptr && *ptr >= 'a') || ('Z' >= *ptr && *ptr >= 'A')) {word[row++] = ptr;//保存每个单词的起始地址//把本次的单词字母字符走完,直到遇到非字母字符while (*ptr != '\0' &&(('z' >= *ptr && *ptr >= 'a') || ('Z' >= *ptr && *ptr >= 'A'))) {ptr++;}continue;//不能继续向下,因为下面的ptr++会跳过当前的非字母字符}*ptr = '\0';//把非字母的数据全部替换为结尾标志ptr++;}for (int i = row - 1; i >= 0; i--) {printf("%s ",word[i]);//针对所有单词的起始地址逆序打印即可}printf("\n");}
}
时间复杂度:O(n*m),空间复杂度:O(1)。
我们学习了C++之后也可以尝试用C++来实现一下,看看自己前段时间C++学得怎么样——
代码演示:
//C++实现
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
using namespace std;int main()
{string s;getline(cin, s); // 读取整行输入vector<string> words;string word;for (char c : s){if (isalpha(c)){ // 如果是字母,添加到当前单词word += c;}else{if (!word.empty()){ // 遇到非字母字符,且当前单词非空,则添加到列表words.push_back(word);word.clear();}}}if (!word.empty()){ // 处理最后一个单词words.push_back(word);}// 逆序输出单词for (int i = words.size() - 1; i >= 0; --i){cout << words[i];if (i > 0) cout << " ";}cout << endl;return 0;
}
时间复杂度:O(n*m),空间复杂度:O(1)。
我们目前要写出来C++的写法是非常考验前面C++的学习情况好不好的,大家可以尝试去写一写,优先掌握C语言的写法,博主还没有介绍C++的算法题,之后会涉及的,敬请期待!
结尾
本文内容到这里就全部结束了,希望大家练习一下这几道题目,这些基础题最好完全掌握!
往期回顾:
【C语言16天强化训练】从基础入门到进阶:Day 11
【C语言16天强化训练】从基础入门到进阶:Day 10
【C语言16天强化训练】从基础入门到进阶:Day 9
【C语言16天强化训练】从基础入门到进阶:Day 8
【C语言16天强化训练】从基础入门到进阶:Day 7
【C语言16天强化训练】从基础入门到进阶:Day 6
【C语言16天强化训练】从基础入门到进阶:Day 5
【C语言16天强化训练】从基础入门到进阶:Day 4
【C语言16天强化训练】从基础入门到进阶:Day 3
【C语言16天强化训练】从基础入门到进阶:Day 2
【C语言16天强化训练】从基础入门到进阶:Day 1
结语:感谢大家的阅读,记得给博主“一键四连”,感谢友友们的支持和鼓励!