c语言试题集锦

####2020.05.26

1. 

s=10*s+p[i][j]-'0'是什么意思

#include<stdio.h>
main()
{
char ch[2][5]={"6937","8254"},*p[2];
int i,j,s=0;
for(i=0;i<2;i++)
p[i]=ch[i];
for(i=0;i<2;i++)
for(j=0;p[i][j]>'\0';j+=2)
s=10*s+p[i][j]-'0';
printf("%d\n",s);
}
 
答:

这个程序是通过循环,将字符数组copy第二维下标是偶数的字符选出,转换为整数并输出。

依次找出是字符是6、3、8、5,而语2113句s=10*s+p[i][j]-'0';就是转换为整数。

s=0;//即s的初始值是0

for(j=0;p[i][j]>'\0';j+=2)//依次找出数组第二维下5261标是偶数的字符

s=10*s+p[i][j]-'0';//转换为整数。4102

转换的过程如下:

s=10*0+'6'-'0',字符6对应的ASCII码值1653减去字符0对应的ASCII码值,就得到数字6,此时s=6 

//这个是char型转换成int型的小技巧,记住;

s=10*6+'3'-'0','3'-'0'得到3,此时s=60+3=63

s=10*63+'8'-'0','8'-'0'得到8,此时s=630+8=638

s=10*638+'5'-'0','5'-'0'得到5,此时s=6380+5=6385,这样就得到了整数6385

printf("%d\n",s);//直接输出这个整数。

2.函数fun的声明为int fun(int *p[4]),以下哪个变量可以作为fun的合法参数()

int a[4][4];
int **a;
int **a[4]
int (*a)[4];

答:

可以看出fun函数的形参是一个指针数组,也就是指针指向一个地址,地址中存放的内容也是指针。


A,二维数组,不符合
B,二级指针,也就是指针指向的内容也还是存放指针的,符合
C,二级指针数组,数组的内容是二级指针,不符合
D,数组指针,不符合

解答一下A为什么是错的:
1.G++4.8.4
源码:int func(int* p[4]) {return 0;}
 int main() {int a[4][5]; func(a);  return 0;}
编译出错:
te.cpp:22:11: error: cannot convert ‘int (*)[5]’ to ‘int**’ for argument ‘1’ to ‘int func(int**)’
     func(a);
原因:
函数参数形参是一个指向指针的指针(作为参数时与数字4无关,相当于int**),
而a[4][5],把a作为参数传入时得到int (*)[5]是一个数组指针,该指针指向一个数组,并且这个数组长度为5,存储类型为int。
(a[4][5]含义:该数组a拥有4个数组类型的元素,其中每个元素都是一个拥有5个整型元素的数组。)

3.设变量n为f1oat类型,m为int类型,则以下能实现将n中的数值保留小数点后两位,第三位进行四舍五入运算的表达式是()。

 

n=(n*100+0.5)/100.0
m=n*100+0.5 ,n= m/100.0
n=n*100+0.5/100.0

n=(n/100+0.5)*100.0

答:  

B
float是实数,Int是整数,float的除法操作中,小数点后位数跟是否除尽有关。若除尽,小数点后位数保留到除尽的位数,不除尽,那就很长了。所以A、C、D是对float类型进行数据处理,小数点后位数跟n的具体值有关,不一定保留2位数。
但m是整数,保留到个位数,小数部分四舍五入,因此,再除以100就会保留2位小数,符合题意。
顺便一提,n中小数点第三位数在“n*100”的情况下成为整数的小数部分,“+0.5”后按整数的小数部分四舍五入到个位数,就实现了n中小数第三位数四舍五入到第二位数。

4.已知:char str1[8],str2[8]={"good"};则在程序中不能将字符数组str2赋值给str1的语句是()。

str1=str2;
strcpy(str1,str2);
strcpy(str1,str2,6)
memcpy(str1,str2,5);

答:

数组名是一地址常量,数组名之间是不能彼此赋值的,所以A是错误的。故

选择答案是A。

strcpy 和 memcpy函数。
1、strcpy 其一般形式为strcpy(字符数组1,字符串2)作用是将字符串2复制到字符数组1中去。
2、memcpy c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。 用法:void *memcpy(void *dest, const void *src, size_t n);
3.区别 
  1)复制的内容不同    前者只能复制字符串   后者可以复制任意内容
  2)复制的方法不同    前者复制时可以不用制定长度   后者需要指定长度 
  3)用途不同              通常复制字符串时用前者,复制其他内容时用后者。
 
5.c语言的二维数组由若干个一维数组构成。表达式int a[M][N],i,j;以下元素的七种表达式等价:

  a[i][j]        //第i行j列的元素的数值
  *(a[i]+j)       //二维数组中a[i]等价于&a[i][0];是第i行的首地址;+j是地址偏移;再用*取值,就是 a[i][j],第i行j列的值;
  *(*(a+i)+j)      //a是指针常量,是整个二维数组的地址指针,是个地址;所以a+i 就相当于首地址偏移i 就是a[i]的地址,即&a[i]
           //*(a+i) 等价于*&a[i] 就是a[i] a[i]在二维数组里是地址,就是行第一个元素的地址,等价于 &a[i][0]
           //所以*(*(a+i)+j) 等价于*(&a[i][0]+j)等于*(&a[i][j]) 即 a[i][j]
  (*(a+i))[j]      // *(a+i) 等价于 a[0+i] ,所以(*(a+i))[j] 就是a[i][j];而 *a+i 等价于 a[0]+i;
  *(&a[0][0]+N*i+j)   //a[0][0]是首元素内容,&a[0][0]是周元素取地址,&a[0][0]+N*i+j 是首地址后移N*i+j个元素,则指向了第i行j列元素;
           //*(&a[0][0]+N*i+j)给其取内容,则得到第i行j列元素的值,即 a[i][j]
  *(a[0]+N*i+j)    //a[0] 等价于&a[0][0] 第一行元素首指针;指针偏移N*i+j 后取指针指向的内容就是a[i][j] 了
  *(*a+N*i+j)     //a是整个二维数组名,是指针常量,保存的是二维数组首地址;*a 取指针内容得到的就是首地址,+N*i+j就是指针偏移了N*i+j;
           //变成了指向a[i][j]的指针;所以再使用*取内容,就是a[i][j]了;

  关键点:
    a是指向整个二维数组的指针常量,是个地址; a+i 是首地址偏移i个单位,相当于 &a[0][i] 第i个元素的数值取地址;
    a[i]在二维数组里不是值,是个地址,指的是第i行的首地址 等同于 &a[i][0] ;这点一定要和一维数组的a[i]进行区分;

####2020.05.27

1.以下叙述中正确的是()

  

在语句char str[] = "string!";中,数组str的大小等于字符串的长度
语句 char str[10] = "string!"; 和 char str[10] = {"string!"}; 并不等价
对于一维字符数组,不能使用字符串常量来赋初值
对于字符串常量 "string!",系统已自动在最后加入了"\0"字符,表示串结尾

解析:
A 选项中 数组的长度包含\0 ,求字符串的长度时 strlen()是不计算\0的长度的(求字符串占得空间是即sizeof才算\0的长度),所以数组要长一个;
字符串中的字符依次存储在内存中一块连续的区域内,并且把空字符 ' \0' 自动附加到字符串的尾部作为字符串的结束标志。故字符个数为 n 的字符串在内存中应占( n+1 )个字节
B 选项中是等价的 类比int数组 部分赋初值是 未赋值的部分自动赋0 此处一样 未赋值的字符自动赋值\0,所以两者一致;
C 选项中可以使用字符串常量来给一维字符数组赋值,就像 B 选项中一样;
D 字符串中包含隐含的结尾符;

2. 在16位C编译系统上,以下程序的输出结果是().

  

void main()
{
int y=2456;
printf ( "y=│%3o│ y=│%8o│y=│%#8o│ y=│%08o│" ,y,y,y,y);
}
 
y=│4630│ y=│□□□□4630│ y=│□□□04630│ y=│00004630│

解析:
int y=2456;此时的y为10进制。因下条语句中输出是以%o(八进制)格式输出的,所以需要将2456转为八进制(2456)10=(4630)8。
printf()中的:
  1> %3o表示以八进制数形式输出,占3个空格的位置,右对齐,左边多余的位置补 空格。但是4630是4位数,所以按照实际宽度输出。y=│4630│
  2> %8o表示以八进制数形式输出,占8个空格的位置,右对齐,左边多余的位置补 空格。4630是4位数,靠右。此时左边补空格。y=│□□□□4630│
  3> %#8o表示以八进制数形式输出,占8个空格的位置,右对齐,左边多余的位置补 空格,并且前导o需要加上。 │□□□04630│
  4> %08o表示以八进制数形式输出,占8个空格的位置,右对齐,左边多余的位置补0 │00004630│
 
  

3. 在64位系统中,有如下类:

1
2
3
4
5
6
7
8
9
10
class A
{
public :
     void *p1;
private :
     void *p2;
protected :
     void *p3;
};
class B:  public A {};

那么sizeof(B)的数值是()

指针在64位系统中占用8个字节,A类中有3个指针,故占用24个字节。B类继承自A类且无成员变量和虚函数表,占用字节和A相同。答案是24

            32位系统    64位系统     (单位Bytes)   
char         1                  1
short        2                  2
int            4                  4 
指针         4                  8
long         4                  8
float         4                  4
double     8                  8

4. 链接:https://www.nowcoder.com/questionTerminal/b813a6117ea541c8b173ac229eda0213
来源:牛客网

下列程序的运行结果是YY,78,96,请为横线处选择合适的程序( )

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>
typedef struct
{
     char name[9];
     float score[2];
}STU;
void f(STU   _______)
{
     STU b={ "YY" ,78,96};
     int i;
     strcpy (a->name,b.name);
     for (i=0;i<2;i++)
         a->score[i]=b.score[i];
}
main()
{
     STU c={ "LL" ,90,80};
     f(&c);
     printf ( "%s,%.0f,%.0f\n" ,c.name,c.score[0],c.score[1]);
}
  A *a
  B  a
  C  &a
   D a[]
   答案: AD   由a->name知a为指针,那么A肯定正确,D说的是数组作为函数的参数会退化成指针,所以D也是正确的;
 
 
5.

猜你喜欢

转载自www.cnblogs.com/fsz304203330/p/12969195.html