非正式纳新题解(C语言)
非正式纳新题目(C语言)
注意本文不是正式的面试题
正式的面试题:ACAT2021纳新题目(C语言)
说明
本试题一共分为12道题,考核点全部以C语言为主,难度有层次划分,希望你尽最大努力完成,我
们不需要你每道题都能得到正确答案,但希望你能有良好的学习态度。我们期待在面试那天与你相
遇!
(编程题只用写出核心代码或者想出解题思路,你也可以在面试时电脑写出完整代码运行,直接展示
你的结果!)
题目
参考
一、写出下面函数的运行结果。
#include <stdio.h>
#define PI 3
#define S(r) PI*r*r
int main(){
float x,y,area;
x=2;
y=1;
area=S(x+y);
printf("r=%f\narea=%f\n",x+y,area);//9
//area=PI*x+y*x+y
}
二、选做题
1分析以下代码
#include<stdio.h>
int main(){
int i=0,s=0;
for(;;){
i++;
if(i==3||i==5)continue;
if(i==6)break;
s+=i;
}
printf("%d",s);//7
return 0;
}
执行上述程序后的输出结果是(C)
A.5
B. 6
C. 7
D. 死循环
2分析以下代码
//本题考查的是if-else嵌套、if-else语句的执行过程。
//主要考查对多分支if-else语句执行过程的理解
//注:else总是与它之前最近的f匹配
//注:if-else语句有且只有一个会得到执行
//1、有以下程序
#include <stdio.h>
int main(){
int a=5,b=4,c=3,d=2;
if(a>b>c)//表达(a>b>c,计算为a>b=1,1>c,但1<c,表达式值为否,不执行
printf("%d\n",d);
else if((c-1>=d)==1)//表达(c-1>=d,计象为,1==1,执行
printf("%d\n",d+1);//结果3
else//不执行
printf("%d\n",d+2);
}
执行上述程序后的输出结果是(B)
A.2
B.3
C.4
D.编译时有错,无结果
三、下列表达式中,不满足“当x的值为偶数时值为真,为奇数时值为假”要求的是( )
A: x%20
B: !x%2!=0
C: (x/2*2-x)0
D: !(x%2)
//正确答案:B
//解析:
//B:当X为2(偶)时,非2为0,0%20为假;当X为1(奇)时,非1也为0,0%2 0也为假,故B不能满足题目要求。
//C:当X为2(偶)时,为真;当X为1(奇)时,结果为-1!=0为假,所以C满足题目要求。
四、若有以下定义和赋值语句,
int b[2][3]={0}, (*p)[3];
p=b;
则对b数组的第i行第j列(假设i,j已正确说明并赋值)元素的非法引用为()。
A: *(*(p+i)+j)
B:*(p[i]+j)
C: *(p+i)+j
D:(*(p+i))[j]
#include<stdio.h>
int main(){
int b[2][3]={0}, (*p)[3];
p=b;
int i=1,j=2;
printf("%d\n",&b[i][j]);//6487556
printf("%d\n", *(*(p+i)+j)); //0
printf("%d\n", *(p[i]+j)); //0
printf("%d\n", *(p+i)+j); //6487556
printf("%d\n", (*(p+i))[j]); //0
}
//标准答案:C 解析:
//C:取的是地址,如果需要取值则要像A选项一样再套个星号。
//D:(*(p+i))取的是第i行的元素,后面的[j]取的是第j列的元素,因此这种写法完全是合法的。
五、给出部分语句填写一行语句实现找出三个整数中的最大值
#include <stdio.h>
int main(){
int x=1;
int y=2;
int z=3;
int max;
//一行语句
max=(x>y)?((x>z)?x:z):((y>z)?y:z);//答案
printf("%d",max);
}
六、二-十进制代码(BCD代码)
相关概念:有权BCD代码是指在表示0-9十个十进制数码的4位二进制代码中,每位二进制数码都有确定的位权值。例如,表1-3-2中的8421码、2421码等。对于有权BCD代码,可以根据位权展开求得所代表的十进制数。例如:
(0111)8421 BCD=0x8+1x4+1x2+1x1=(7)10
(1101)2421 BCD=1x2+1x4+0x2+1x1=(7)10
最常用的有权码是8421 BCD码,由于其位权值是按基数2的幂增加的,这和二
进制数的位权值一致,所以有时也称8421 BCD码为自然数权码。
十进制数码 8421码 2421码
0 0000 0000
1 0001 0001
2 0010 0010
3 0011 0011
4 0100 0100
5 0101 1011
6 0110 1100
7 0111 1101
8 1000 1110
9 1001 1111
用BCD码表示十进制数
在BCD代码中,4位二进制代码仅表示1位十进制数,对一个多位的十进制数进行编码,需要有与十进制位数相同的几组BCD代码来表示,每组代码之间按十进制进位。
例如,用8421BCD码来表示十进制数863,则
(863)10=(1000 0110 0011)8421 BCD
如果用2421 BCD码来表示十进制数863,则
(863)10=(1110 1100 0011)2421 BCD
程序设计:输入任意一个十进制数,将其用2421 BCD码表示
(提示:类似于念数字)
#include<stdio.h>
void DtoBCD(int n){
switch(n){
case 0:printf("0000");break;
case 1:printf("0001");break;
case 2:printf("0010");break;
case 3:printf("0011");break;
case 4:printf("0100");break;
case 5:printf("1011");break;
case 6:printf("1100");break;
case 7:printf("1101");break;
case 8:printf("1110");break;
case 9:printf("1111");break;
}
}
int main(){
int num;
scanf("%d",&num);
if(num==0){
DtoBCD(num);
}
int a[100];
int len=0;
while(num){
int n;
n=num%10;
a[len++]=n;
num/=10;
}
int i=len-1;
for(i;i>-1;i--){
DtoBCD(a[i]);
}
}
七、写出输出内容
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void OutPut(int data){
printf("%d",data);
}
void change1(int data){
data=1;
printf("11---");
OutPut(data);//1
printf("\n");
}
void change2(int *data){
*data=1;
}
int change3(){
int data=1;
return data;
}
int main(){
int data;
data=0;
printf("0---");
OutPut(data);//0
printf("\n");
change1(data);
printf("1---");
OutPut(data);//0
printf("\n");
change2(&data);
printf("2---");
OutPut(data);//1
printf("\n");
int data1;
data1=change3();
printf("3---");
OutPut(data1);//1
printf("\n");
}
八、遍历数组:用不同的方法遍历数组(至少三种)
//不同方法输出数组元素
#define N 10
#include <stdio.h>
int main(){
int a[N];
int i;
int *p;
p=a;
for(i=0;i<N;i++){
a[i]=i;
}
printf("\n");
for(i=0;i<N;i++){
printf("%d ",a[i]);//下标法
}
printf("\n");
for(i=0;i<N;i++){
printf("%d ",p[i]);//下标法
}
printf("\n");
for(i=0;i<N;i++){
printf("%d ",*(a+i));//指针法
}
printf("\n");
for(i=0;i<N;i++){
printf("%d ",*(p+i));//
}
printf("\n");
for(p=a/*数组的首地址*/;p<(a+N);p++/*加的是类型单元int: 4*/){// 指针法
printf("%d ",*p);//
}
printf("\n");
}
九、输出选做题
1.回形数
回形数格式方阵的实现
从键盘输入一个整数(1~20)
则以该数字为矩阵的大小,把1,2,3…n*n 的数字按照顺时针螺旋的形式填入其中。例如: 输入数字2,则程序输出:
1 2
4 3
输入数字3,则程序输出:
1 2 3
8 9 4
7 6 5
输入数字4, 则程序输出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
#include<stdio.h>
void main() {
printf("输入");
int num;
scanf("%d",&num);
int a[num][num];//声明一个 num行 num列的数组
int i=0,j=0,n=1;//i:行 j:列
int maxi=num-1,maxj=num-1,mini=0,minj=0;//maxi:行最大值 maxj:列最大值 mini:列最小值 minj:行最小值
int k=1;//决定向哪个方向走
while(n<=num*num) {
//向右
if(k==1) {
if(j<=maxj && a[i][j]==0)
a[i][j++] = n++;
else {
k=2;
j--;
i++;
maxj--;
}
}
//向下
if(k==2) {
if(i<=maxi && a[i][j]==0)
a[i++][j] = n++;
else {
k=3;
i--;
j--;
maxi--;
}
}
//向左
if(k==3) {
if(j>=minj && a[i][j]==0)
a[i][j--] = n++;
else {
k=4;
j++;
i--;
minj++;
}
}
//向下
if(k==4) {
if(i>=mini && a[i][j]==0)
a[i--][j] = n++;
else {
k=1;
i++;
j++;
mini++;
}
}
}
//遍历数组并输出
for(i=0;i<num;i++) {
for(j=0;j<num;j++) {
printf("%d\t",a[i][j]);
}
printf("\n");//换行
}
}
2.完成输出下列字符
输入n,输出以下字符
*
*.*.
*..*..*..
*...*...*...*...
*....*....*....*....*....
*.....*.....*.....*.....*.....*.....
*......*......*......*......*......*......*......
*第n行*
#include<stdio.h>
#include<stdlib.h>
/*
*
*.*.
*..*..*..
*...*...*...*...
*....*....*....*....*....
*.....*.....*.....*.....*.....*.....
*......*......*......*......*......*......*......
*/
static a = 0;
void print2(int n)
{
if (n == 0)
return;
else
{
printf(".");
print2(n - 1);
}
}
void print1(int n)
{
if (n == 0)
return;
else
{
printf("*");
print2(a - 1);
print1(n - 1);
}
}
void run(int n)
{
if (n == 0)
return;
else
{
run(n - 1);
a = n;
print1(n);
printf("\n");
}
}
int main()
{
run(7);
printf("\n");
}
十、C语言编写一个程序,去掉给定字符串中重复的字符。例如将google转化为gole。
#include <stdio.h>
#include <string.h>
int main()
{
char buf[1024]={0};
printf("请输入一个字符串!\n");
scanf("%s",buf); //scanf不能输入带空格的字符串
int len = strlen(buf); //计算字符串长度
int i,j;
for(i=0;i<len;i++)
{
for(j=i+1;j<len;j++)
{
if(buf[j] == buf[i]) //找到一个重复的字符
{
int tmp;
for(tmp=j;tmp<len;tmp++)//数组移动,让下一个字符覆盖当前的重复字符
{
buf[tmp] = buf[tmp+1];
}
j--; //之后要让下一次重新判断当前的新字符是否还是重复的
len--; //由于删除了一个重复的字符,导致字符串长度减少一个
}
}
}
printf("去重后:%s\n",buf);
return 0;
}
十一、结构体,共用体的字节对齐
//64位系统
#include<stdio.h>
union UNode{
char ch;
int in;
char *p;
};
struct SNode{
char ch;
short sh;
int in;
float f;
double db;
char *p;
char arr[5];
union UNode UN;
};
int main(){
printf("%d",sizeof(struct SNode));//48
printf("%d",sizeof(union UNode));//8
}
十二、逻辑选做题(可以不做)
ACAT2021纳新题(旧)
ACAT2021纳新题(旧)
说明:
本试题一共分为12道题,考核点全部以C语言为主,难度有层次划分,希望你尽最大努力完成,我们不需要你每道题都能得到正确答案,但希望你能有良好的学习态度。我们期待在面试那天与你相遇!
(本测试题目省略#include…,编程题只用写出核心代码,你也可以在面试时带上U盘或者电脑直接展示你的结果!)
题目
参考
1. 请分析下列代码的运行结果,并解释其原因。
解析:考点:无 break 的 switch case 语句的执行流程
# include <stdio.h>
int main() {
int n=1,a=0,b=0;
switch(n)
{
case 0://n=0跳过
b++;
case 1://n=1进入
a++;//a变成1
//无break继续,不会跳出switch case 语句,继续向下执行
case 2:
++a;//a变成2
b++;//b变成1
}
printf("a=%d,b=%d\n",a,b);// a=2,b=1
}
2.请分析下面函数的运行结果,并解释其原因。
考点:带参数的宏定义
若修改为
#define S(r) PI*(r)*(r)
就是计算以x与y的和为半径的圆的面积
# include <stdio.h>
#define PI 3
#define S(r) PI*r*r
int main(){
float x,y,area;
x=2;
y=1;
area=S(x+y);//S=PI*x+y*x+y=3*2+1*2+1=9
printf("r=%f\narea=%f\n",x+y,area);//r=3.000000 //area=9.000000
}
3.请分析下列代码的运行结果,并解释其原因。
考点:运算符的优先级和结合性
下表按照题目中运算符出现顺序排列
优先级 | 运算符 | 含义 | 结合性 |
---|---|---|---|
15 | , | 逗号运算符 | 自左至右 |
2 | ++ | 自增运算符 | 自右至左 |
10 | ` | ` | |
14 | = | 赋值运算符 | 自右至左 |
2 | -- | 自减运算符 | 自右至左 |
注意:在逻辑表达式的求解中,并不是所有的逻辑运算符都要被执行,只有在必须下一个逻辑运算符才能求出表达式的解时,才执行该运算符。
例如:
int x=-1;
执行++x||++x||++x后,x的值是多少?
分析:根据逻辑“||”自左至右的结合性,先计算第一个“”左边的运算对象++x,得到结果为0。
对于“||”运算符来说还不能确定这个表达式的值,必须再计算右边的++x,得到结果为1。
此时第一个“||”结合的表达式的值就为1,这样无论第二个“||”运算符后面的运算对象值为多少,整个表达式的值已经确定为1。所以不需再计算第三个++x了,因而x的值为1。
说回题目
int main(int argc, char const* argv[])
{
int a = 0, b = 5;
++a || ++b, a - b;//a变成1 ||表达式的值为1,后面的++b不会执行
b = b--;//b=5 --
printf("%d %d\n", a, b);//1 5
return 0;
}
4.请分析下列代码的运行结果,并解释其原因。
考点:运算符
# include <stdio.h>
int main() {
int a = 0;//a为0
int b = 0 == a;//0==a的值为1 ,b为1
int c = -1;//c为1
if (a = 1) {//a赋值为1
c = a && b;//c=1&&1=1
}
printf("%d%d%d", a, b, c);//111
return 0;
}
5. 分析下列代码,请计算 x,y,z的大小
考点:struct 的内存对齐
以下引用自https://blog.csdn.net/weixin_30432007/article/details/97729396
1、字节对齐的细节和编译器实现相关,但一般而言,如在windows下,就VC而言,满足一下三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
即:在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量:sizeof(类型)或其倍数
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)
即:最大sizeof(类型)的整数倍
类型
对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)
Char 偏移量必须为sizeof(char)即1的倍数
int 偏移量必须为sizeof(int)即4的倍数
float 偏移量必须为sizeof(float)即4的倍数
double 偏移量必须为sizeof(double)即8的倍数
Short 偏移量必须为sizeof(short)即2的倍数
说回题目
# include <stdio.h>
int main(){
struct x{ //16 2*8
int a; //4 Bytes ,此时偏移量为4
char b; //1 Byte ,偏移量4是1的倍数,此时偏移量为5
double c; //8 Bytes ,此时偏移量5不是8的倍数,填充3,使偏移量为8,然后为c开辟8个空间,此时偏移量为16
};
struct y{ //16 2*8
float b; //4 Bytes ,此时偏移量为4
int a; //4 Bytes ,偏移量4是4的倍数,此时偏移量为8
double c; //8 Bytes ,偏移量8是8的倍数,此时偏移量为16
};
struct z{ //24 3*8
int a; //4 Bytes ,此时偏移量为4
double c; //8 Bytes ,偏移量4不是8的倍数,填充4,此时偏移量为8,然后为c开辟8个空间,此时偏移量为16
char b; //1 Byte , 此时偏移量16是1的倍数,偏移量为17,结构体的总大小为结构体最宽基本类型成员大小的整数倍,即需是8的整数倍,需要编译器会在最末一个成员之后加上填充字节(trailing padding),填充8*3-17=7个,此时偏移量为24
};
printf("%d\n",sizeof(struct x)); //16
printf("%d\n",sizeof(struct y)); //16
printf("%d\n",sizeof(struct z)); //24
}
6.下面是一个交换两个变量的函数,看看这种方法可以实现吗?如果可以,还有其他方法吗?如果不可以,说说原因。
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
7.请分析以下代码的运行结果,并解释其原因。
考点:scanf的返回值的含义
scanf函数返回 int型 成功读入的数据项数,
读入数据时遇到了“文件结束”则返回EOF。
# include <stdio.h>
int main() {
int n;
printf("%d", scanf("%d", &n));//输入非数值型为0,输入数值型为1
return 0;
}
8.你知道哪些排序算法?你知道它们是怎样实现的吗?(大致思路)
9.字符串翻转
设计一个程序实现字符串翻转,即将abcdefg反转成gfedcba,已经为你写好了部分代码,请在规定的区域添加代码来实现程序。
不允许在规定地方之外写代码,不允许删除写过的代码。
代码本来就定义了一个字符串和一个字符变量和一个整型数,不允许声明新的任何类型的变量。
考点:字符串翻转
要求:空间复杂度为O(1),即不允许声明新的任何类型的变量。
实现:字符串内部操作
# include <stdio.h>
# include <string.h>
int main() {
char s[32];
scanf("%s", s);
int n = strlen(s);
int i;
char ch;
/* 规定区域开始 */
for(i = n-1;i>=n/2;i--){
ch=s[n];
s[n]=s[n-i];
s[n-i]=ch;
}
/* 规定区域结束 */
printf("%s", s);
return 0;
}
补充用递归实现
#include<stdio.h>
void reverseSentence();
int main(){
printf("输入:");
reverseSentence();
return 0;
}
void reverseSentence(){
char c;
scanf("%c",&c);
if(c != '\n'){
reverseSentence();
printf("%c",c);
}
}
10.水仙花数
“水仙花数”是指一个三位数其各位数字的立方和等于该数本身,
例如153是“水仙花数”,因为:153 = 13 + 53 + 33,
所以判断一个数是否为“水仙花数”,最重要的是要把给出的三位数的个位、十位、百位分别拆分,并求其立方和(设为s),
若s与给出的三位数相等, 三位数为“水仙花数”,反之,则不是。
请你编写一段代码,判断一个三位数数是否是水仙花数。
11.打印杨辉三角形
输入一个任意正整数n,请你编写一段代码,打印n行的杨辉三角形。
例:n = 4
输入结果:
1
1 1
1 2 1
1 3 3 1
12.逻辑图
哲学家就餐问题是在计算机科学中的一个经典问题
哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。
吃东西的时候,他们就停止思考,思考的时候也停止吃东西。
餐桌中间有一大碗米饭,每两个哲学家之间有一只筷子。
哲学家想要吃饭必须拿到两个筷子。
哲学家从来不交谈,这就很危险。
有可能导致什么情况呢?
每个哲学家都拿起来自己左手边的筷子,然后眼巴巴地等着自己右边的哲学家放下筷子好让自己集齐一双筷子来吃饭。
请问如何避免这种现象发生呢?(想法越多越好)