目录
选择题
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
解析:
本题考察了函数在调用过程中,实际参数和形式参数的匹配关系,本题函数原型为int fun(char b[10], int *a);
,第一个形参是数组形式的参数,第二个形参是指针类型的参数,故在调用时传递的实际参数也需要为数组和指针类型(地址),所以第一个参数传数组的数组名,即数组首元素地址,第二个参数传变量d
的地址
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
答案:ABCD
解析:
本题考察了用const
修饰的指针类型,对于指针变量c
,由于const
修饰的是指针变量整体,即*c
,而因为c
并没有得到实际有效的地址,所以解引用c
会导致野指针问题,并且因为被const
修饰,所以不可以使用解引用操作符改变变量c
指向的空间中的值,对于指针变量d
,同样也是const
修饰指针变量整体,但d
得到了a
变量的地址,故d
当前指向a
变量所在的空间,但是因为被const
修饰,所以同样不可以使用解引用操作符通过指针变量d
改变a
空间中的内容,对于指针变量e
,const
直接修饰变量,而不是修饰指针变量整体,并且指针变量e
得到了b
的地址,故此时可以使用*e
修改b
所在空间的内容,但是不可以改变指针变量e
所指向的空间,对于指针变量f
来说,同时被const
修饰指针变量整体和变量名,此时既不可以改变f
指向的地址,也不可以通过*f
改变指向的空间的值
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
* * *
答案:A
解析:
本题中的变量i
为全局变量,作用域为整个文件中,生命周期为持续到程序结束,故main
函数中的变量i
改变时,prt
函数中的i依旧会改变,所以总共就执行了三次打印
4、下面代码段的输出是
int main()
{
int a=3;
printf("%d\n",(a+=a-=a*a));
return 0;
}
- A -6
- B 12
- C 0
- D -12
答案:D
解析:
本题考察了运算符的优先顺序以及C语言赋值运算符的赋值顺序,对于表达式a+=a-=a*a
来说,先计算a*a
结果为9,但是这个计算没有副作用,所以a
变量中的值还是3,再执行a-=
,即a = a - 9
,因为a
中当前为3,故a
此时为3-9=-6
,接着执行a+=
,因为a
当前值为-6,所以a=(-6)+(-6)
,故a
的值为-12
5、下列不能实现死循环的是( )
- A
while(1){}
- B
for(;1;){}
- C
do{}while(1);
- D
for(;0;){}
答案:D
解析:
在C语言中,循环执行的条件时判断表达式部分为真,而只要该部分中的值不为0即为真,故只有循环D无法实现死循环
编程题
记负均正
题目链接:记负均正_牛客题霸_牛客网 (nowcoder.com)
描述
首先输入要输入的整数个数n,然后输入n个整数。输出为n个整数中负数的个数,和所有正整数的平均值,结果保留一位小数。
0即不是正整数,也不是负数,不计入计算。如果没有正数,则平均值为0。
数据范围:1≤ n ≤2000 ,输入的整数都满足 ∣val∣≤1000
输入描述:
首先输入一个正整数n,
然后输入n个整数。
输出描述:
输出负数的个数,和所有正整数的平均值。
思路解析:
本题处理好负数和0的个数即可,在最后求平均值的过程中需要考虑到除数为0的情况
参考代码:
#include <stdio.h>
int main() {
int num = 0;
int sum = 0;
int input = 0;
int count = 0;//记录负数的个数
int zero = 0;//记录0的个数
scanf("%d", &num);
for(int i = 0; i < num; i++)
{
scanf("%d", &input);
if(input > 0)
{
sum += input;
}
else if(input < 0){
count++;
}
else {
zero++;
}
}
//如果输入的数值中不全是负数和0时计算平均数,否则不计算平均数
if(num != count && num != zero)
{
printf("%d %.1f", count, (float)sum/(num - count - zero));
}
else {
printf("%d %.1f", count, 0.0);
}
return 0;
}
旋转数组的最小数字
题目链接:旋转数组的最小数字_牛客题霸_牛客网 (nowcoder.com)
描述
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围:1≤ n≤10000,数组中任意元素的值: 0≤ val≤10000
要求:空间复杂度: O(1) ,时间复杂度: O( logn)
思路分析:
因为原数组是一个非降序(即非严格递增)的数组,所以旋转后的数组将被分为两个有序的数组,对于二分查找来说,只需要查找的数组是有序即可,对于本题,因为存在两个有序的部分,故需要分别进行判断,确定好边界后缩小范围再进行二分查找,故本题有三种情况
范围内的中间数值比右侧范围中的数值大。此时说明,数组中的最小数值在中间值的右侧,此时运用二分查找算法的思想,在右侧的部分中找最小值
范围内的中间数值比右侧范围中的数值小。此时说明,数组中的最小数值在中间值的左侧,此时运用二分查找算法的思想,在左侧的部分中找最小值
范围内的中间数值和右侧范围中的数值相等。此时无法判断数组中的最小数值在哪一侧,此时逐渐缩小区间,重复判断直到出现上面两种情况中的一种再执行上面的两种情况的处理方法
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @param numsLen int nums数组长度
* @return int整型
*/
int minNumberInRotateArray(int* nums, int numsLen )
{
int left = 0;
int right = numsLen - 1;
while(left <= right)
{
//指向中间位置的变量
int mid = (left + right) / 2;
if(nums[mid] > nums[right])
{
//当中间值大于右侧的值
//注意此处是left = mid + 1,left用于和right确定边界,当需要缩小范围时,mid位置的数值可以不再包括在内,因为当前数值已经比nums[right]大
left = mid + 1;
}
else if(nums[mid] < nums[right])
{
//当中间值小于右侧的值
//注意此处不是right = mid - 1,因为要与nums[right]进行比较从而确定边界,可能mid位置就是一侧边界
right = mid;
}
else
{
//当中间值等于右侧的值
right--;
}
}
return nums[left];
}