📙作者简介: 清水加冰,目前大二在读,正在学习C/C++、Python、操作系统、数据库等。
📘相关专栏:C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。
欢迎点赞 👍 收藏 ⭐留言 📝 如有错误还望各路大佬指正!
✨每一次努力都是一种收获,每一次坚持都是一种成长✨
目录
前言
1. 选择题
📖题目1:
📖题目2:
📖题目3:
📖题目4:
📖题目5:
2. 编程题
📖题目一:
📖题目二:
总结
前言
接下来,我们继续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. 编程题
📖题目一:
示例:
题目链接:记负均正https://www.nowcoder.com/practice/6abde6ffcc354ea1a8333836bd6876b8?tpId=37&&tqId=21320&rp=1&ru=/ta/huawei&qru=/ta/huawei/question-ranking
✨题目解析:
基本功扎实的同学这道题目绝对没有问题的,统计负数个数,以及正数个数,并且在统计正数个数的过程中求取正数总和,最后计算得出平均数即可。需要注意的是所有数字中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; }
📖题目二:
示例:
题目链接:旋转数组的最小数字https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=23269&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
✨题目解析:
这道题目有两种解决方法:
暴力破解:遍历数组找出最小值即可
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语言的学习和编程之路上继续努力,不断追求卓越。祝愿你们在未来的编程之旅中取得更大的成功和成就!