前言:
每日一练系列,每一期都包含5道选择题,2道编程题,博主会尽可能详细地进行讲解,令初学者也能听的清晰。每日一练系列会持续更新,暑假时三天之内必有一更,到了开学之后,将看学业情况更新。
五道选择题:
1、下列定义数组的语句中正确的是【多选】( )
A、
#define size 10
char str1[size], str2[size+2];
B、char str[]; C、int num['10'];
D、int n=5; int a[n][n+2];
解析:在c中数组长度的初始化只能是常量,不能为变量,也就是说,c语言不支持变长数组。不过想要在c中使用变长数组还是有办法的,通过指针可以实现,这里就先不提,知道数组长度初始化在c中只能为常量即可 选项A将str1初始化为size,size是个宏定义,在编译的过程中会直接被对应内容替换掉,在这里它的对应内容为10,因此把它看作10即可。10是个常量,没问题。又将str2初始化为了size+2,常量+常量本质还是常量,没问题。A正确。
B选项非法定义,当未对数组进行初始化时,必须定义数组的长度,B错。C选项,将数组的长度定义为字符10,字符10的本质是ASCII码值,可看作常量,C正确。D选项,使用变量n初始化数组a的长度是不符合c语言的规则的,故D错。综上所述,答案为AC
2、已知 i,j 都是整型变量,下列表达式中,与下标引用 X[i][j] 不等效的是【多选】( )
A、*(X[i]+j) B、*(X+i)[j] C、*(X+i+j) D、*(*(X+i)+j)
A、*(X[i]+j) B、*(X+i)[j] C、*(X+i+j) D、*(*(X+i)+j)
解析:从这张图片可以看出,[]和()的优先级为1,解引用*的优先级为2。那么我们就根据优先级来做题。目标是找到与下标引用 X[i][j] 不等效的,x[i][j]取x数组第i行第j列的元素。
看到A选项,先走x[i]那么就是第i行,再走被包裹在括号内的+j,故走到第i行第j列的地址,再解引用得到内容,故与目标等效,故不选A。走到B,()和[]优先级相同从左往右即可,但*的优先级最低,最后走,故走出来为**((x+i)+j),显然越界,不等效,选B。
C选项,X是二维数组的数组名,数组名相当于第一行的地址,X+i+j,跳过了i+j行,就越界了,不等效,选C。D选项,*(x+i)走到第i行,第0列,受到解引用*的影响,+j相当于走到第j列,再解引用,故得到第i行第j列的元素,等效,故不选D。综上所述,答案为BC
3、二维数组X按行顺序存储,其中每个元素占1个存储单元。若 X[4][4] 的存储地址为Oxf8b82140 X[9][9] 的存储地址为 Oxf8b8221c ,则 X[7][7] 的存储地址为( )
A、Oxf8b821c4 B、Oxf8b821a6 C、Oxf8b82198 D、Oxf8b821c0
解析:这道题是有难度的,需要有足够的细心。首先,我们在计算数组对应的存储地址时,应该要知道数组一行到底有多长。设二维数组X一行的长度为n,x[9][9]-x[4][4]=5n+5,观察发现,两个地址之间只有后三位不同,那么只需要看后三位,21c-140,由于是十六进制的,我们得先把它们转换为10进制,(2*16*16+1*16+12*1)-(1*16*16+4*16+0*1)=(512+16+12)-(256+64+0)=(540)-(320)=220=5n+5,所以n=43。
这个数组一行有43个元素,目标是计算出x[7][7]的地址,设x[7][7]的地址为z,那么x[7][7]的地址-x[4][4]的地址就会等于z-Oxf8b82140=3n+3,故z=Oxf8b82140+132,132转换为十六进制为84,所以最后z=Oxf8b821c4,所以答案为A
4、下列代码运行后的结果是什么( )
#include<stdio.h>
int main()
{
char a = 'a', b;//1
printf("%c,", ++a);//2
printf("%c\n", b = a++);//3
return 0;
}
A、b,b B、b,c C、a,b D、a,c
解析:基础题,但不少人会错误的把代码1看作逗号表达式,以为只定义了一个a,展开来写,代码1可写作char a='a';char b;一共定义了两个字符变量,代码2先++后使用,打印出'b'。代码3先使用后++,字符变量b最终被赋值为'b',故打印出'b',所以答案选A
5、求函数返回值,传入 -1 ,则在64位机器上函数返回( )
int func(int x)
{
int count = 0;
while (x)
{
count++;
x = x&(x - 1);//与运算
}
return count;
}
A、死循环 B、64 C、32 D、16
解析:先看代码构成,一个循环,一个循环计数器,最后返回循环的次数。与运算,一起为1才为1,否则为0,操作的是补码。传入了-1,-1的原码为10000.....00001,反码为11111.....11110,补码为11111.....11111,每次与比自己小1的数&运算,都会将自己的一位给修改为0,一共修改32次,全为0循环停止,因为int只能够存放4个字节,32个位故最后值为32。跟64位机器没半毛钱关系。选C
编程题1:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路:numsSize 大小的数组,其中每个元素的数据在 [1, numsSize] 区间之内,以数组元素的绝对值作为下标,将对应位置的数据置为负数 比如 0 号位置是 3 ,则把 3 号位置的数据重置为负值,等到数组遍历重置完毕,只有缺失的这个数字对应的位置保留正数,其他出现过的数字位置都会是负数, 要注意不要重复设置负数,因为负负得正。
举个例子int a[4]={1,2,3,3};4是丢失的,走到1,把第一个位置也就是下标为0的位置变为1的负数,走到2,把第二个位置也就是下标为1的位置变为2的负数,走到3把下标为2的位置变为负数,还是走到3继续把下标为2的位置变为负数,最后就会发现,下标为3的位置不是负数,+1得缺失的数。
综上所述,两次遍历搞定,一次遍历把数据对应的下标对应的位置变为负数,第二次遍历找非负位置的下标即可
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize){
int i=0;*returnSize=0;
int*new=(int*)malloc(sizeof(int)*numsSize);
//创建数组
for(i=0;i<numsSize;i++)
{
int tmp=abs(nums[i]);
//下标不能为负数
tmp-=1;
//因为是1到n的范围,对应的下标减1才能得到
nums[tmp]=-abs(nums[tmp]);
//把对应下标变为负数,用绝对值避免负负得正
}
for(i=0;i<numsSize;i++)
{
if(nums[i]>0)
{
new[*returnSize]=i+1;
//+1得对应的位置
(*returnSize)++;
}
}
return new;
//返回数组
}
编程题2:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路:遍历一遍,是1话计数器就加1,一旦不是1,就与之前储存的最多连续1次数比较,若计数器上的更大则更新,然后将计数器归零继续计算连续1的个数。 需要注意的一点便是,出来之后还要再比较一次,避免数组的最后是一串连续的1导致漏判
int findMaxConsecutiveOnes(int* nums, int numsSize){
int i=0;int count=0;int max=0;
for(i=0;i<numsSize;i++)
{
if(nums[i]==1)
{
count++;
}
else
{
max=max>count?max:count;
//比较当前连续的次数和之前连续的次数,大的赋值给max
count=0;
}
}
max=max>count?max:count;
//出来之后再判定一次,避免漏判
return max;
}
好了,今天的练习到这里就结束了,感谢各位友友的来访,祝各位友友前程似锦O(∩_∩)O