🎈前言:
- 本专栏每篇练习将包括
5个选择题 + 2个编程题
,将涵盖C语言的不同方面,包括基础语法、数据类型、控制结构、数组、指针和函数等。通过练习,你将逐步掌握C语言的基础知识和常见问题,提高你的编程技巧和解决问题的能力。- 我希望这个博客能够为你提供有价值的练习资源,让你在实践中不断进步。同时,我们也鼓励你在练习过程中进行思考和创新,尝试使用不同的编程方法和技巧。
- 让我们一起挑战C语言练习题,攻克每一个难点,不断提升自己的编程技能!
在评论区分享你的练习心得和问题,与我们一起交流和成长。
🌴选择题
- 已知函数的原型是:
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
【解析】:
参数
a
是指针,要接收地址,所以BD错误。参数b
可以接收的是char*
,而&c
的类型是char(*)[10]
,C错误
- 请问下列表达式哪些会被编译器禁止【多选】( )
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
🔎正确答案:
ABCD
【解析】:
- A:
*c = 32;
- 这是错误的,因为c
是一个指向常量整数的指针,意味着不能通过这个指针来修改所指向的值。编译器会禁止这个操作。- B:
*d = 43;
- 这是错误的,因为d
是一个指向整数的指针,尽管它指向一个非常量整数a
,但是由于指针本身被声明为指向常量的,所以不能通过这个指针来修改所指向的值。编译器会禁止这个操作。- C:
e = &a;
- 这是错误的,因为e
被声明为一个指向整数的常量指针,一旦指针被初始化,就不能再指向其他变量。编译器会禁止这个操作。- D:
f = 0x321f;
- 这是错误的,因为f
被声明为一个指向常量整数的常量指针,一旦指针被初始化,就不能再指向其他变量。编译器会禁止这个操作。
【拓展】:
- 如果
const
位于*
的左侧,则const
就是用来修饰指针所指向的变量,即指针指向为常量;即*c
和*d
不能变。- 如果
const
位于*
的右侧,则const
就是修饰指针本身,即指针本身是常量;即e
和f
不能变。
- 以下程序的输出结果为( )
#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: * * *
🔎正确答案:
A
【解析】:
全局变量
i
,在main()
中修改为5
,第一次在prt()
中执行循环输出三次'*'
,i
被修改为8
,回到main()
中第二次调用prt()
时,i<8
为假,循环结束没输出,执行一次print("\t")
,再次回到主函数后i++
变为9
,i<=8
为假,循环结束。
- 下面代码段的输出是( )
#include<stdio.h> int main() { int a = 3; printf("%d\n", (a += a -= a * a)); return 0; }
A: -6 B: 12 C: 0 D: -12
🔎正确答案:
D
【解析】:
a+=a-=a*a
等价于a=a+(a=a-a*a)
,即先计算a=a-a*a
,所以此时a
的值为3-3*3=-6
,再计算-6+(-6)=-12
赋值给a
,所以a
的值为-12
,也就是整个表达式的值,所以应选择D
- 下列
不能实现
死循环的是( )
A: while(1){} B: for(;1;){} C: do{}while(1); D: for(;0;){}
🔎正确答案:
D
【解析】:
只有条件为真时才进行循环,ABC中1为真,D中0为假
🌴编程题
📌记负均正
【牛客网链接:HJ97 记负均正】
【题目信息】:
【答案解析】:
- 这道题其实通过
scanf
捕捉数据即可,统计负数个数,以及正数个数,并且在统计正数个数的过程中求取正数总和,最后计算得出平均数即可。需要注意的是所有数字中0是不统计在内的。
#include <stdio.h> int main() { int n; while (~scanf("%d", &n))//多组输入 (也可以写成 scanf("%d",&n)!=EOF ) { int count1 = 0, count2 = 0, tmp; double sum = 0; for (int i = 0; i < n; i++) { scanf("%d", &tmp);//对每次输入的整数进行判断 if (tmp < 0) { count1++; //统计负数个数 } else if (tmp > 0) { sum += tmp; //正数求和 count2++; //统计大于0的正数个数,这样是因为题目说明0不算在内 } } printf("%d ", count1); if (count2==0)//如果没有正数,则平均值为0 { printf("%.1lf\n",0.0); } else//若有正数,则平均值为所有正数的和除以正数的个数 { printf("%.1lf\n",sum / count2); } } return 0; }
📌旋转数组的最小数字
【牛客网链接:JZ11 旋转数组的最小数字】
【题目信息】:
【答案解析】:
- 暴力破解:遍历数组找出最小值即可(时间复杂度:O(N) )
//暴力破解:遍历数组找出最小值即可 int minNumberInRotateArray(int* nums, int numsLen) { int i = 0; for (i = 0; i < numsLen - 1; i++) { if (nums[i] > nums[i + 1])//只要出现降序则说明出现了最小值,比如[4,5,1,2,3] :5到1是降序,则1就是最小值; return nums[i + 1]; } return nums[0];//如果没出现降序,说明没旋转,则第一个数就是最小值。 }
- 更优思想:采用二分查找,这个题主要分析三种旋转情况
[1, 2, 3, 4, 5]
,使用中间值与右端进行比较。(时间复杂度:O(logN))
- 中间大于右边
[3, 4, 5, 1, 2]
,这种情况下,最小数一定在右边;则left = middle + 1
- 中间等于右边
[1, 0, 1, 1, 1]
, 这个是[0, 1, 1, 1, 1]
旋转过来的,这时候需要缩小范围right--
;,注意不能是left++
,因为是非降序数组,所以要缩小右边范围,把较小值向右推,符合我们的判断规则。 - 中间小于右边
[5, 1, 2, 3, 4]
, 这种情况下,最小数字则在左半边;则right = middle
//更优思想:采用二分查找 int minNumberInRotateArray(int* nums, int numsLen) { int left = 0; int right = numsLen - 1; while (left < right) { int mid = left + (right - left) / 2;//避免整数溢出 if (nums[mid] > nums[right]) { left = mid + 1;//最小值在[left+1,right] } else if (nums[mid] == nums[right]) { right--;//缩短数组,将最小值范围右移 } else { right = mid;//最小值在[left,mid] } } return nums[left]; }
🔥今天的内容就到这里了,有什么问题的话欢迎大家在评论区讨论,也可以私信博主为你解答,如果觉得博主的文章还不错的话, 请👍三连支持一下博主哦🤞