前言
接下来,我们继续C语言刷题。本期为第三期,在这个阶段,我们将继续挑战自己,探索更深入的C语言知识和编程技巧。这将是一个更加具有挑战性的阶段,但也将带来更多的成长和收益。
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是指针,要接收地址,BD错误。
参数b可以接收的是char*,而&c的类型是char(*)[10],C错误
正确答案:A
📖题目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 位于 * 的左侧,则 const 就是用来修饰指针所指向的变量,即指针指向为常量;*c和*d不能变(指针指向的内容不能改变,但可以使用其他指针来修改)。
如果 const 位于 * 的右侧,则 const 就是修饰指针本身,即指针本身是常量;e和f不能变。
正确答案:ABCD
详细可见文章:const函数和assert函数:提高代码质量的利器
📖题目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,在main()中修改为5,第一次在prt()中执行循环输出三次'*',i被修改为8,回到main()中第二次调用prt()时,i<8为假,循环结束没输出,执行一次print("\t"),再次回到主函数后i++变为9,i<=8为假,循环结束;
正确答案:A
📖题目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+(a=a-a*a),即先计算a=a-a*a,所以此时a的值为3-3*3=-6,再计算-6+(-6)=-12赋值给a,所以a的值为-12,也就是整个表达式的值
正确答案:D
📖题目5:
5、下列不能实现死循环的是( )
A: while(1){}
B: for(;1;){}
C: do{}while(1);
D: for(;0;){}
✨题目解析:
这道题目主要考察对循环的理解。
只有条件为真时才进行循环,ABC中1为真,D中0为假 。
正确答案:D
2. 编程题
📖题目一:
示例:
题目链接:
✨题目解析:
基本功扎实的同学这道题目绝对没有问题的,统计负数个数,以及正数个数,并且在统计正数个数的过程中求取正数总和,最后计算得出平均数即可。需要注意的是所有数字中0是不统计在内的
#include <stdio.h> int main() { int n; while (~scanf("%d", &n)) { float sum = 0; int t = 0; int count1 = 0, count2 = 0; for (int i = 0; i < n; i++) { scanf("%d", &t); if (t < 0) count1++; //统计负数个数 else if (t > 0) { sum += t; //正数求和 count2++; //统计大于0的正数个数,这样是因为题目说明0不算在内 } } printf("%d %.1lf", count1, (count2 == 0) ? 0 : sum / count2);//最后输出时判断一下正数是否为0 } return 0; }
📖题目二:
示例:
题目链接:
✨题目解析:
这道题目有两种解决方法:
暴力破解:遍历数组找出最小值即可
int minNumberInRotateArray(int* nums, int numsLen ) { int min=nums[0]; for(int i=1;i<numsLen;i++) { if(min>nums[i]) { min=nums[i]; } } return min; }
暴力求解代码相对简单,但时间复杂度过高。
更优思想:采用二分查找,这个题主要分析三种旋转情况 [1, 2, 3, 4, 5],使用中间值与右端进行比较。通过观察我们可以发现规律:
- 中间大于右边 [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 ) { if (numsLen == 0) return 0;//数组长度为0就直接返回0 int left = 0, right = numsLen - 1, mid;//right为数组最右边的下标 if (nums[right] > nums[left]) return nums[0];//如果数组第一个数大于最后一个那就没有旋转,第一个数为最小 while(left < right) { mid = (left + right) / 2; if (nums[mid] > nums[right]) left=mid+1;//如果中间大于右边,那最小数一定在mid右边 else if (nums[mid] == nums[right]) right--;//如果相等就排除最右边的一个数据,不可以left++ else right = mid;//中间小于右边,那最小数就在mid左边 } return nums[left];//最后right和left相等,此时就是最小值的下标 }
总结
好的,本期内容到此结束。最后,我要衷心感谢每一位参与刷题的读者,你们的支持和参与是我们前进的动力。希望你们在C语言的学习和编程之路上继续努力,不断追求卓越。祝愿你们在未来的编程之旅中取得更大的成功和成就!