
❄专栏传送门:《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.1 题目1)
[1.2 题目2](#1.2 题目2)
[1.3 题目3](#1.3 题目3)
[1.4 题目4](#1.4 题目4)
[1.5 题目5](#1.5 题目5)
[2.1 数字颠倒](#2.1 数字颠倒)
[2.1.1 题目理解](#2.1.1 题目理解)
[2.1.2 思路](#2.1.2 思路)
[2.1.3 实现(C/C++)](#2.1.3 实现(C/C++))
[2.2 单词倒排](#2.2 单词倒排)
[2.2.1 题目理解](#2.2.1 题目理解)
[2.2.2 思路](#2.2.2 思路)
[2.2.3 实现(C/C++)](#2.2.3 实现(C/C++))
一、五道选择题
1.1 题目1
**题干:**请阅读以下程序,其运行结果是( )
cpp
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 的机器数为( )
cpp
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
**题干:**下列程序的输出结果是什么( )
cpp
#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型就可以不用管它们了)------

代码演示:
cpp
//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------
代码演示:
cpp
//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)。
当然还有一种写法:
代码演示:
cpp
//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 得到9
num /= 10;
//通过除以10的方式去掉个位数 例如:129/10 得到12
}
printf("\n");
}
return 0;
}
时间复杂度 :O(n);
空间复杂度 :O(1)。
我们学习了C++之后也可以尝试用C++来实现一下,看看自己前段时间C++学得怎么样------

代码演示:
cpp
//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型就可以不用管它们了)------

代码演示:
cpp
//C语言实现
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main()
{
char s[10001]; // 总字符长度不超过10^4
fgets(s, sizeof(s), stdin);
char words[5000][21]; // 假设最多5000个单词,每个单词最长20
int 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)****。
这个的代码量还是很大的,可以再简洁一点------
代码演示:
cpp
//C语言实现------方法2
#include <stdio.h>
#include <string.h>
int main()
{
char str[10001] = { 0 };
//题目要求:字符串最长10000
int 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++学得怎么样------

代码演示:
cpp
//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++的算法题,之后会涉及的,敬请期待!
结尾
本文内容到这里就全部结束了,希望大家练习一下这几道题目,这些基础题最好完全掌握!
往期回顾:
结语: 感谢大家的阅读,记得给博主"一键四连",感谢友友们的支持和鼓励!