当前位置: 首页 > news >正文

【C语言16天强化训练】从基础入门到进阶:Day 3


🔥个人主页:艾莉丝努力练剑

❄专栏传送门:《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.2  旋转数组的最小数字

题目理解:

结尾


正文

一、五道选择题

1.1  题目1

题干:已知函数的原型是:int fun(char b[10], int *a); ,假设定义:char c[10];int d; ,那么正确的调用语句是( )

A. fun(c,&d);     B. fun(c,d);     C. fun(&c,&d);     D. fun(&c,d);

解析:正确的调用语句是A. fun(c,&d);。我们先分析一下函数原型int fun(char b[10], int *a);表示函数fun的第一个参数是一个字符数组(或者说字符指针),第二个参数是一个整型指针。

继续分析函数原型:

(1)第一个参数char b[10]:可以直接传递字符数组c数组名(c会退化为指针);

(2)第二个参数int *a):需要传递一个整型变量的地址,因此d应该通过&d传递其地址。

这里我们定义的是char c[10];int d;,所以关键就在于——

1.数组作为参数char c[10] 作为参数时,实际传递的是char*(d退化为指针);

2.指针参数int*a 必须传入地址(如&d),不能直接传值(如d)。

补充:

这里唯一正确的调用方式是 A. fun(c, &d);

B选项是错误的,因为它没有传递指针给 int *a

1.2  题目2

题干:请问下列表达式哪些会被编译器禁止()【多选】

int a = 248, b = 4;
int const *c = 21;
const int *d = &a;
int *const e = &b;
int const * const f = &a;

A. *c = 32;     B. *d = 43     C. e=&a     D. f=0x321f

解析:题目问的是“哪些表达式会被编译器禁止”,即哪些操作是非法(违反const规则)的。

我们注意以下几点——

(1)const 在 * 左侧(如const int* 或 int const*):指向的值不可变,指针可变

(2)const 在 * 右侧(如 int *const):指针不可变,指向的值可变

(3)const 在 * 两侧(如int const *const):指针和指向的值均不可变

所有选项(A、B、C、D)均违反const规则,全部会被编译器禁止。若题目要求“多选”,应全选

我们再深挖一下选项看看——

问:为什么D选项有两个const,分别都禁止了什么?

1、第一个const(左侧的int const或const int)

禁止的操作不能通过指针 f 修改它指向的值(即 *f 是只读的)。

举个例子:

*f = 100;  // 非法!编译器会报错,因为 *f 是常量。

作用(限制)范围:限制的是指针解引用后的值(*f),与指针本身的存储无关。

2、第二个 const(右侧的*const)

禁止的操作不能修改指针 f 本身的值(即 f 不能指向其他地址)。

举个例子:

f = &b;    // 非法!编译器会报错,因为 f 是常量指针。
f = NULL;  // 非法!

作用(限制)范围:限制的是指针变量 f 存储的地址(指针自身的值)。

总结

声明形式禁止的操作允许的操作
int const *const f1. 修改 *f(值)
2. 修改 f(指针)
1. 读取 *f
2. 读取 f(地址)

补充:两个const共同确保了指针和指向的数据都不可变。

1.3  题目3

题干:以下程序的输出结果为( )

#include <stdio.h>
int i;
void prt()
{for (i = 5; i < 8; i++)printf("%c", '*');printf("\t");
} 
int main()
{for (i = 5; i <= 8; i++)prt();return 0;
}

A. ***      B. *** *** *** ***      C. *** ***      D. * * *

解析:注意这里i是一个全局变量,i是全局变量,在ptr() 和main() 中共享。

这里 ptr() 中的 for (i = 5; i < 8; i++)会执行 3 次循环(i = 5,6,7),每次打印一个' * ',因此输出 *** 。之后打印一个制表符 \t(tab)

main()函数中,for (i = 5; i <= 8; i++)会调用 ptr()  4 次(i = 5,6,7,8)。

每次调用ptr()的时候:i 被 ptr()  的 for 循环修改为 8(循环结束后i++使 i 变为8),然后回到main() 的for循环,i++使 i 变为 9,从而终止循环。

因此,只有第一次调用 ptr() 会正常输出*** ,后续调用因为 i 的全局性导致循环条件直接不满足,因而无输出。

实际输出***(仅第一次调用有效,其余调用因 i 的值被修改而无输出),答案是A选项

注意:这里的 * 紧密相连,中间是没有空格的。

1.4  题目4

题干:下面代码段的输出是( )

int main()
{int a=3;printf("%d\n",(a+=a-=a*a));return 0;
}

A. -6      B. 12      C. 0      D. -12

解析:题目是(a+=a-=a*a),计算过程如下:

a * a → 9

a -= 9 → 3 - 9 = -6

此时 a = -6,我们把-6代入到后面的赋值操作——

a += -6 → -6 + (-6) = -12

这样一来,答案就是选项D.  -12

1.5  题目5

题干:下列不能实现死循环的是( )

A. while(1){}     B. for(;1;){}     C. do{}while(1);     D. for(;0;){}

解析:如下所示——

A. while(1){} ——

1 是恒为真条件,因此这是一个典型的死循环,故能实现死循环。

B. for(;1;){} ——

for 循环的中间条件为 1(恒为真),相当于 while(1){} ,故能实现死循环。

C. do{}while(1); ——

do{}while(1); 的条件为 1(恒真),会无限循环,故能实现死循环。

D. for(;0;){} ——

for 循环的中间条件为 0(恒为假),循环体根本不会执行,不能实现死循环。

题目问的是“不能实现死循环”的选项,因此正确答案是D选项

选择题答案如下:

1.1  A

1.2  ABCD

1.3  A

1.4  D

1.5  D

校对一下,大家都做对了吗?

二、两道算法题

2.1  记负均正

题目链接:HJ97 记负均正

题目描述:

题目理解:

我们需要统计负整数的个数并计算正整数的平均值。

这道题也是IO型的,下面是C语言的模版(IO型就不用管它们了)——

代码演示:

#define  _CRT_SECURE_NO_WARNINGS  1
//C语言
#include <stdio.h>int main() 
{int n;scanf("%d", &n);  // 读取整数个数int negative_count = 0;  // 负整数计数器int positive_count = 0;  // 正整数计数器int positive_sum = 0;    // 正整数总和for (int i = 0; i < n; i++) {int num;scanf("%d", &num);  // 读取每个整数if (num < 0) {negative_count++;  // 统计负数}else if (num > 0) {positive_count++;  // 统计正数positive_sum += num;  // 累加正数}// 0不做处理}// 输出负整数个数printf("%d ", negative_count);// 计算并输出正整数的平均值if (positive_count > 0) {double average = (double)positive_sum / positive_count;printf("%.10lf\n", average);  // 输出10位小数保证精度}else {printf("0.0\n");  // 没有正整数时输出0.0}return 0;
}

这道题也是C语言中一道比较经典的算法题目。

时间复杂度O(n)

空间复杂度O(1)

我们学习了C++之后也可以尝试用C++来实现一下,看看自己前段时间C++学得怎么样——

//C++实现
#include <iostream>
#include <iomanip> // 用于控制输出精度
using namespace std;int main() 
{int n;cin >> n;  // 读取整数个数int negative_count = 0;  // 负整数计数器int positive_count = 0;  // 正整数计数器int positive_sum = 0;    // 正整数总和for (int i = 0; i < n; i++) {int num;cin >> num;  // 读取每个整数if (num < 0) {negative_count++;  // 统计负数}else if (num > 0) {positive_count++;  // 统计正数positive_sum += num;  // 累加正数}// 0不做处理}// 输出负整数个数cout << negative_count << " ";// 计算并输出正整数的平均值if (positive_count > 0) {double average = static_cast<double>(positive_sum) / positive_count;// 设置输出精度为10位小数cout << fixed << setprecision(10) << average << endl;}else {cout << "0.0" << endl;  // 没有正整数时输出0.0}return 0;
}

时间复杂度:O(n),空间复杂度:O(1)

这个目前要写出来非常考验C++的学习情况,大家可以尝试去写一写,优先掌握C语言的写法,博主还没有介绍C++的算法题,之后会涉及的,敬请期待!

2.2  旋转数组的最小数字

题目链接:JZ11 旋转数组的最小数字

题目描述:

题目理解:

我们需要在旋转后的非降序数组中找到最小数字。由于题目要求时间复杂度为O(logn),我们使用二分查找算法来实现。

这道题是接口型的,下面是C语言的模版(IO型就不用管它们了)——

代码演示:

#define  _CRT_SECURE_NO_WARNINGS  1
//C语言
/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param nums int整型一维数组* @param numsLen int nums数组长度* @return int整型*/
int minNumberInRotateArray(int* nums, int numsLen)
{if (numsLen == 0) return 0;  // 处理空数组情况int left = 0;int right = numsLen - 1;while (left < right){int mid = left + (right - left) / 2;  // 防止溢出if (nums[mid] > nums[right]){// 最小值在右半部分left = mid + 1;}else if (nums[mid] < nums[right]){// 最小值在左半部分或就是midright = mid;}else{// 当nums[mid] == nums[right]时,无法判断,缩小右边界right--;}}return nums[left];
}

这道题是C语言中一道比较经典的题目。

当然博主还有一个更加简单的解法,这个解法大家理解起来就简单了——

我们如果学习了C++也可以尝试用C++实现一下——

//C++实现
class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param nums int整型vector* @return int整型*/int minNumberInRotateArray(vector<int>& nums) {// write code hereif (nums.empty()) return 0;  // 处理空数组情况int left = 0;int right = nums.size() - 1;while (left < right) {int mid = left + (right - left) / 2;  // 防止溢出if (nums[mid] > nums[right]) {// 最小值在右半部分left = mid + 1;} else if (nums[mid] < nums[right]) {// 最小值在左半部分或就是midright = mid;} else {// 当nums[mid] == nums[right]时,无法判断,缩小右边界right--;}}return nums[left];}
};

时间复杂度O(logn)

空间复杂度O(1)

目前要写出来C++的写法是比较考验前面C++的学习情况的,当然大家可以尝试去写一写,优先掌握C语言的写法,博主还没有介绍C++的算法题,之后会涉及的,敬请期待!


结尾

往期回顾:

【C语言16天强化训练】从基础入门到进阶:Day 2

【C语言16天强化训练】从基础入门到进阶:Day 1

结语:感谢大家的阅读,记得给博主“一键四连”,感谢友友们的支持和鼓励!

http://www.dtcms.com/a/339897.html

相关文章:

  • 光纤通信系统的光纤计量详解-连续测量更高效
  • Protobuf安装和使用
  • 把 AI 变成「图书馆管理员」——基于检索增强的离线图书语音导航小盒子
  • 更新一个GMT新增的投影类型:Spilhaus投影
  • 融智兴“RFID物流周转箱卡”荣获2025“IOTE 金奖”创新产品奖
  • 全0子数组的数目-子数组问题
  • 项目里程碑设定有哪些方法
  • 猫头虎AI分享|字节开源了一款具备长期记忆能力的多模态智能体:M3-Agent 下载、安装、配置、部署教程
  • Visual Studio 中文件属性(在解决方案资源管理器中选中文件,按 F4 或在右键菜单 -> 属性)
  • 【树莓派】【嵌入式】远程树莓派,解决ping不通问题
  • 第5.6节:awk字符串运算
  • python新工具-uv包管理工具
  • 编排之神--Kubernetes中的网络通信-Flannel插件及Calico插件演练
  • Android SystemServer 中 Service 的创建和启动方式
  • Milvus 安装和启动指南
  • 决策树学习(2)
  • almalinux9.6系统:k8s可选组件安装(1)
  • 数字ic后端设计从入门到精通14(含fusion compiler, tcl教学)半定制后端设计
  • 第三阶段数据库-2:数据库连接
  • [超表面论文快讯-200]PNAS-超表面辅助的多模态量子成像-南京大学祝世宁院士/新国立仇成伟院士团队
  • 警惕可变参数构造函数无限递归
  • Day13_【DataFrame数据组合join合并】【案例】
  • 让模型不再忽视少数类:MixUp、CutMix、Focal Loss三种技术解决数据不平衡问题
  • RabbitMQ:SpringAMQP Direct Exchange(直连型交换机)
  • RabbitMQ:SpringAMQP 入门案例
  • Flink on Native K8S安装部署
  • 3.Kotlin 集合 Set 所有方法
  • es9.0.1语义检索简单示例
  • 颠覆性进化:OpenAI正式发布GPT-5,AI大模型进入“超级智能”时代
  • InnoDB为什么使用B+树实现索引?