第一题
test.c文件中包括如下语句,文件中定义的四个变量中,是指针类型的是()【多选】
#define INT_PTR int* typedef int* intptr; INT_PRT a,b; int_ptr c,d;
A:a B:b C:c D:d
#define是宏定义,此时在程序中INT_PTR都会被替换为int*,变量a,b的定义如下:
int * a,b;
可以发现a确实为整型指针类型,而b则为整型类型。
而typedef是给该类型定义一个别名,使用该别名创建出的变量都是这个类型的。
第二题
对于以下说法,正确的是()
A:对于struct X {short s;int i; charc},sizeof(X)sizeof(s)+sizeof(i)+sizeof(c )
B:对于某个double变量a,可以使用a==0.0来判断其是否为0。
C:初始化方式char a[14]=“helloworld”;和char a[14];a=“hello world”;的效果相同。
D:以上说法都不对
解析:
A:结构体大小的计算要考虑内存对齐问题。
B:这道题如果在VS上实验一下的话,会觉得B选项就是正确的,然而不然,因为该数据是double类型的数据,浮点数存在误差,不能直接判断两个数是否相等,通常是采用比较两数之差是否小于一个很小的数字,(具体可以自己设定一个这样的数,作为误差)来确定是否相等。
例如:
运行结果是不是超脱预料之外?
调试观察sub1和sub2的数值。
可以发现误差是存在的,所以不能直接用一个浮点数是否等于0.0来判断该数是否为0。
C:a为数组首元素地址,是一个常量不可以改变。
第三题
请问下列表达式,哪些会被编译器禁止()【多选】
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在*前边的位置和const在*后边。如果const在*前边,就修饰的是指针变量指向的结果。
例如
int a=1;
const int *pa=&a;
int const *pa=&a;
只要const在pa的左边,那么const修饰的就是*pa,就不可以利用解引用得到a来修改a的值,此时a的值被固定了。
还有一种情况是const在*的右边
int a=0;
int b=0;
int * const pa=&a;
这种情况下const修饰的是a这个变量的地址,即pa的指向不能发生变化。此时如果要更改pa的指向如pa=&b,这样的操作是不被允许的。
如果觉得不好记忆的话,可以参考趣味讲解const修饰指针变量。
第四题
对于下边代码段,描述正确的是()
t=0; while(printf("*")) { t++; if(t<3) break; }
A:其中循环控制表达式与0等价。
B:其中循环控制表达式与‘0’等价。
C:其中循环控制表达式是不合法的。
D:以上说法都不对。
解析:
这道题目选B,因为printf函数返回打印的字符·个数,所以判断条件恒为1,字符零不是零。
所以在这里B选项就是正确的。其他选项都是错误的。
编程题
题目要求如下
第一种思路
遍历两边,第一遍找出最大值,第二遍判断是否找出的最大值是数组每个元素的二倍,如果满足条件就返回最大数字的下标,如果不满足,那就返回-1。
代码如下:
int dominantIndex(int* nums, int numsSize){ int i=0; int max=0; for(i=0;i<numsSize;i++) { if (nums[i] > max) { max = nums[i]; } } int num=0; int flag=0; for(i=0;i<numsSize;i++) { if(nums[i]==max) { num=i; } else { if(nums[i]*2>max) { flag=1; } } } if(flag==0) { return num; } else { return -1; } return 0; }
代码表达很清晰。
还有一种方法,在找到最大值时,也要保存倒数第二大的值。
代码如下:
int dominantIndex(int* nums, int numsSize){ int i=0; int max=nums[0]; int max1=0; int flag=0; for(i=0;i<numsSize;i++) { if(nums[i]>max) { flag=i; max1=max; max=nums[i]; } if (max1 < nums[i]&&max!=nums[i]) { max1 = nums[i]; } } if(max>=2*max1) { return flag; } else { return -1; } return 0; }
找到最大值的同时,保存第二大值,因为后边可能会出现比已经保存的第二大的值还要大的值,所以要继续向后遍历找到真正第二大的值,。最后进行判断即可。
第二题
只需要创建一个数组,得到right和left之间的所有满足条件的数即可,每一个数求出他的个位数,十位数,等等。
数据范围最大也只有10000。
像这种需要用的数字的每一位的数据进行判断的题目,最好还是创建一个大小为6的数组,装输入的数据的每个位的数字,方便最后进行判断。在解题的过程中要注意返回的数组必须是malloc申请的,不然就会有很多的报错。
代码如下(注释十分清晰)
int* selfDividingNumbers(int left,int right,int *returnsize) { int*ccc=(int*)malloc(sizeof(int)*(right-left+1)); int kkk[6]; int l = 0; for (int i = left; i <= right; i++) { int j = 0; int a = 1; int num = i; while (i > 0)//获取每位数字 { kkk[j++] = i % 10; i = i / 10; } i = num; for (int k = 0; k < j; k++) { if (kkk[k] != 0)//如果数字中包含零,就不满足 { if (i % kkk[k] != 0) { a = 0; } else { a = 1; } } else { a=0; } } if (a != 0)//如果该数字通过前边的测试 { ccc[l++] = i;//将该数字存放在预留数组中。 } } *returnsize = l; return ccc; }
第三题
喝汽水问题
小明喝汽水,一瓶汽水1元,2个空瓶可以换一瓶汽水,小明现在有n元,求小明可以喝到多少瓶汽水?
思路一
将上述问题以代码形式解决,如果有n元,那么刚开始就有n个空瓶,假设全部喝完,然后拿着所有空瓶过去换汽水,就能换到n/2瓶汽水,喝完后于是又获得了n/2的瓶子,然后再去换,直到瓶子数目为0或者为1不足以再换汽水为止。
代码实现如下
int main() { int money = 0;//钱数 int total = 0;//总共喝的汽水的数量 int empty = 0;//空瓶的数量 scanf("%d", &money); total = money; empty = money; while(empty>1)//只要空瓶数大于2,就能继续换 { total += empty/2; empty = empty/2+empty%2; } printf("total = %d\n", total);//最终结果total return 0; }
思路二
利用数学思维求解,我们可以利用上述代码多运行几次观察规律,会发现随着money的增长,能喝到的汽水的数量是一个等差数列。
1元—>1瓶汽水
2元—>3瓶汽水
3元—>5瓶汽水
。。。。
所以只要Money的数量不为0,只需要返回money*2-1即可。
代码如下
int main() { int money = 0; int total = 0; int empty = 0; scanf("%d", &money); //方法2 if(money <= 0) { total = 0; } else { total = money*2-1; } printf("total = %d\n", total); return 0; }