牛客C语言题

2021.1.5
1.
A.在语句char str[ ]=“string!”;中 数组str的大小等于字符串的长度

错误 
--数组的长度包含终止符\0
--字符串的长度不包含\0

B.语句char str[10]=“string!”; 和 char str[10] = {“string!”}不等价

错误 对于字符串来讲 未赋值的部分自动赋值“\0”  两个时等价的

C. 对于一位字符数组,不能使用字符串常量来赋初值

错误 char str[10] = "string";成立

D 对于字符串常量"string",系统已自动在最后加入了"\0"字符表示串尾

正确
#include < stdio. h >
int d = 1;
void fun( int p )
{
    int d=5;
    d += p++;
    printf("%d", d );
}
main()
{
    int a=3;
    fun(a);
    d += a++;
    printf( "%d\n",d);//最终打印结果为8 4 
i++  在进行运算的时候  用i 参与运算 然后i自增
++i  先对i进行自增  然后用自增后的i参与运算

3.用变量 a 给出下面的定义
一个有10个指针的数组,该指针指向一个函数,该函数有一个二整形参数并返回

/*
int *a[10]   //指向int类型的指针数组a[10]
int (*a)[10]  //指向有10 个int类型数组的指针a
int(*a)(int)  //函数指针, 指向有一个参数并且返回类型均为int的函数
int (*a[10])(int);//函数指针的数组,指向有一个参数并且返回类型均为int的函数的数组

*/

4.当/的两边都是整数时。/表示整除,是否正确?

//   5/3得到的时一个float数,

5.下列选项中正确的语句时
A.char s[8]; s={“Beijng”};
B char *s; s={“Beijing”};
C char s[8]; s=“Beijing”;
D char *s; s=“Beijing”;

/*
数组名是不可修改的常量
char s[8];写完之后就已经初始化了数组 每个元素默认为 "\0" 而后只能是对某个元素进行修改  或是令其等于另一个数组。
AB两个已经进行了初始化,在惊醒初始化就得修改数组名,而数组名是不允许修改的,所以A B 错误
*/ 

若有以下语句:
int a[4][5],(*p)[5];
p=a;
下面哪个选项表示a数组中的元素?

A. p+1
B *(p+3)
C *(p+1)+3
D *(*p+2)

/*
首先明确 a是一个二维数组  p 是一个二维数组的指针
那么此时 p表示的是a[0] 的地址 而p+1 表示的是 a[1]的地址
*(p+1) 表示进入该行,在此处表示的是第二行即a[1][0]的地址 , 那么*(P)+1表示的是第二行第二个元素的地址
(*(p)+1) 表示的是第二行第二个元素
因此本题 ABC 表示的都是地址,只有D表示的是元素
*/

不考虑任何编译器优化(如:NRVO),下述代码的第10行会发生

#include //1
class B//2
{//3
};//4
B func(const B& rhs){//5
  return rhs;//6
}//7
int main(int argc,char **argv){//8
  B b1,b2;//9
  b2=func(b1);//10
}//11

A.一次默认构造函数,一次拷贝构造函数,一次析构函数,一次(拷贝赋值运算符)operator=
B.二次拷贝构造函数,一次析构函数

C.一次(拷贝赋值运算符)operator=,一次析构函数
D.一次拷贝构造函数,一次析构函数,一次(拷贝赋值运算符)operator=

b2=func(b1);//10
一次拷贝构造函数发生在func函数调用完成,返回B类型的对象时,因为返回的不是引用类型,所以会生成一个对象,
不妨称为TEMP,将返回的对象通过拷贝构造函数复制给TEMP,然后,返回值所对应的对象会被析构。如果返回值是引用类型,
则不会调用拷贝构造函数。

赋值运算符在func函数执行完成后,将上面提到的TEMP,通过赋值运算符赋值给b2,值得注意的是赋值运算符重载函数如果不自己定义,
程序会认为是调用缺省的赋值运算符重载函数。

下面哪种情况下,B不能隐式转换为A?
A.class B:public A{}

B.class A:public B{}

C.class B{operator A();}

D.class A{A(const B&);}

A 派生类转换为基类
B 基类转派生类,不能隐式转换
C 是隐式类型转换操作符
D 通过拷贝构造函数进行隐式转化

关于浅复制和深复制的说法,下列说法正确的是
A.浅层复制:只复制指向对象的指针,而不复制引用对象本身。

B.深层复制:复制引用对象本身。

C.如果是浅复制,修改一个对象可能会影响另外一个对象

D.如果是深拷贝,修改一个对象不会影响到另外一个对象

答案 ABCD
浅拷贝:只复制指针内容,不复制指针所指对象,结果为两个指针指向同一块内存;
深拷贝:重新为指针分配内存,并将原来指针所指对象的内容拷贝过来,最后结果为两个指针指向两块不同的内存;
浅拷贝是指针拷贝,深拷贝是对象拷贝

10.设fp已定义,执行语句fp=fopen(“file”,“w”);后,以下针对文本文件file操作叙述的选项错误的是:

A.可以随意读和写

B.只能写不能读

C.可以在原有内容后追加写

D.写操作结束后可以从头开始读

牛客C语言题_第1张图片
2020.1.7
1.
已知int i=0, x=1, y=0;,在下列选项中,使i的值变成1的语句是( )。
A.if( x&&y ) i++;

B.if( x==y ) i++;

C.if( x||y ) i++;

D.if( !x ) i++;

选C
if()中  括号中为真  则执行
&& 与运算
|| 或运算
! 取非
== 相等

如果不使用多态机制,那么通过基类的指针虽然可以指向派生类对象,但是只能访问从基类继承的成员。

正确
不使用多态机制(虚函数),派生类就不会生成虚函数表,用基类指针指向派生类对象时,通过基类指针只能访问派生类的成员变量,不能访问派生类的成员函数

再看题干:如果不使用多态机制,那么通过基类的指针虽然可以指向派生类对象,但是只能访问从基类继承的成员。

划线处我认为叙述有问题,派生类添加的新的成员变量也是可以通过基类指针访问的。
#include < stdio. h >
main ( )
{ 
    char w [20] , a[ 5 ][ 10 ] = { "abcdef", "ghijkl", "mnopq", "rstuv", "wxyz"} ; 
    int p [ 6 ] [ 2 ] = { {0,1},{1,5},{0,0},{0,2},{1,4},{4,4}}, i ;
    for (i =0; i < 6 ; i + +) 
        w[i] = a[p[i][0]][p[i][1]];
    printf( w ) ;
}

运行结果为:black 此题按照程序执行即可

语言源程序的基本结构单位是 main 函数。请问这句话的说法是正确的吗?

错误
对于语言源程序来讲  基本组成单位是 函数  而非主函数

当顺利执行了文件关闭操作时,fclose.函数的返回值是()。

顺利执行返回0  否则返回1
main()
{  
	char a[7]="a0\0a0\0";
	int i,j;
   
 	i=sizeof(a);  j=strlen(a);
   
	printf("%d  %d\n",i,j);
}

程序输出结果为

sizeof 输出的是a的内存空间大小所以会包含终止符 输出7
strlen() 输出的是字符串的长度  遇到"\0"就停止输出2
int a[]={1,2,3,4};
int *b=a;
*b+=2;
*(b+2)=2;
b++; 
printf("%d,%d\n",*b,*(b+2));

代码的运行结果为

24
首先确定 b是 一维数组的指针
那么此时 b 表示的是a[0]的地址
*b 表示的是此时b所指向的值 即1 所以第二行改变的是值 地址未变

以下正确的说法是( )。
A.用户调用标准库函数前,必须重新定义

B.若已包含标准库头文件及相关命名空间,用户也可以重新定义标准库函数,但是该函数将失去原有含义

C.若已包含标准库头文件及相关命名空间,则系统不允许用户重新定义标准库函数

D.用户调用标准库函数前,不必使用预编译命令将该函数所在文件包括到用户源文件中

A 调用库函数是 需要的是利用#include对其进行声明
B C 标准库函数可以被重载而不能重新定义,重载后函数具有不同的形参,但是原有的定义并不失效
D 当用户调用标准库的函数前,必须使用#include 进行预编译命令 将函数所在文件包括到用户源当中
int main(){
   int i=-2147483648;
   return printf("%d,%d,%d,%d",~i,-i,1-i,-1-i);
}

打印结果为

1~i:对每一位 取反运算。为01...1311),是正数,补码即原码,即231-1=21474836472-i: 对该数求补运算,即【每位】取反运算,再加1。取反, 10...0310-> 01...1311),再加110...0310),该 补 码表现为 最小负数- 2147483648,并没有原码和反码;
31-i:补码形式相加,再推回原码得十进制结果。-i( 10...0310) )+0 ...1310) )= 10...1300),此为补码形式,补码转 原码为补码减1,再非符号位取反,即原码1...1321= -(231-1)= - 21474836474-1-i :补码形式相加,再推回原码得十进制结果。即-i( 10...0310) )+1 ...1321) )= 01...1311),是正数形式,原码即补码,为231-1= 2147483647

201.1.8
1.

下列选项中,合法的 C 语言关键字是()
A.var
B.defaut
C.integer
D.cher

A 数据库字符关键字
B 争取
C Java的整型包
D char
int u=010, v= 0x10, w=10;
printf(%d,%d,%d/n”,u,v,w);

输出结果为

0开头表示8进制
0x开头表示16进制
所以 u=8
	 v=16 
	 w=10
int main()
{
int a[5]  = {1, 2, 3, 4, 5};
int *ptr = (int*)(&a + 1);
printf("%d, %d", *(a + 1), *(ptr - 1));
return;
}
输出结果为
a 是长度为5的一位数组
*ptr为一个指针
再此处要辨析  
&(a+1)表示的是a[2]的地址
&a+1 表示的a[5]的位置的地址  因为数组的地址都是连续的,在这里只是没有给数组a分配a[5]的空间,但并不代表a[5]的空间不存在
 所以ptr - 1 指的是a[4]的地址 
 多以打印为2 5 
int func(int x,int y)
{
return(x+y);
}

main()
{int a=1,b=2,c=3,d=4,e=5;
printf("%d\n",func((a+b,b+c,c+a),(d+e)));
} 

求输出结果
再c语言中有 逗号表达式
(表达式1,表达式2,表达式3......)从左到右依次计算,最终表达式的值等于最后一个式子的值
所以最终等于
func(49=13

请问经过表达式a = 5 ? 0 : 1的运算,变量a的最终值是?

三目运算
bool?1:值二  为真等于值一  为假等于值二
a=5!=0 为真 最终为0

6.有以下结构体说明和变量的定义,且指针p指向变量a,指针q指向变量b。则不

能把结点b连接到结点a之后的语句是()。

struct node
{
char data;
struct node *next;
} a,b,*p=&a,*q=&b;

A.a.next=q;

B.p.next=&b;

C.p->next=&b;

D.(*p).next=q;

【解释】p是一指向结构体类型的指针变量,其初始值是让其指向结构体变量a,要通

过指针变量p来引用结构体变量的成员next,通常可使用两种形式:p->next 或(*p).next,

而p.next是非法的引用。故选择答案是B。

以下选项中合法的常量是?
A.9 9 9

B.2.7e

C.0Xab

D.123E 0.2

A:9 9 9 数字间不能有空格
B:e前后必须有数字,且后面的数字必须为整数。
C:十六进制 0X...
D:同B

常 量:整型常量: 123     实型常量:3.14     字符常量: 'a'     逻辑常量:true、false
常 量:final int i = 0; i的值不可变

s12和s2已正确定义并分别指向两个字符串。若要求:当s1所指串大于s2所指串时,执行语句S;则以下选项中正确的是 ( )

A.if(s1>s2)S;

B.if(strcmp(s1,s2))S;

C.if(strcmp(s2,s1)>0) S;

D.if(strcmp(s1,s2)>0)S;

答案 D
C语言库函数  int strcmp(str1,str2)
如果str1 > str2 return >0
	str1 < str2 return <0
	str1 == str2 return 0

下面关于数组的初始化正确的是:
A.char str[2] = {“a”,“b”};

B.char str[2][3]={“a”,“b”};

C.char str[2][3]={{‘a’,‘b’},{‘e’,‘d’},{‘e’,‘f’}};

D.char str[] = {“a”, “b”};

区分单引号‘’与双引号“”的区别,单引号为单个字符;’双引号为字符串,系统会默认添加‘\0
char a=101;
int sum=200;
a+=27;sum+=a; 
printf("%d\n",sum);

求输出

char为有符号类型,占1个字节,也就是8位,其中最高位位符号位,取值范围为-128~127;
a=101+27=128>127; 表示为1000 0000,计算机中以补码形式存储, 即为-128;
sum=200+(-128)=72;

2020.1.9
1.

int f(int a)
{ return a%2; }
main()
{ int s[8]={1,3,5,2,4,6},i,d=0;
  for
(i=0;f(s[i]);i++) d+=s[i];
 
printf("%d\n",d);
}

本题按照程序执行即可
2.
设float x=2.5,y=4.7;int a=7;,printf(“%.1f”,x+a%3*(int)(x+y)%2/4)的结果为()
A.2.5
B.2.8
C.3.5
D.3.8

本题要注意的是在强制转换和一般运算同事存在是,强制转换优先执行
最终答案为 2.5

3.若有定义语句: char a =’\82’; 则变量a
A.说明不合法
B.包含一个字符
C.包含两个字符
D.包含三个字符

有一个‘\’,那么首先想到的是转义字符常量,‘\ddd’  是用八进制数的ASCII码表示一个字符,但是本题中'\82',有一个8,显然已经不是八进制,那么这个时候实际上就'\82'中包含3个字符,分别是‘\’,'8','2',赋值时是将字符'2'给了a,实际上这个题和 char a = 'fdz'变量a的值是‘z’是一个道理,只是\具有迷惑作用而已,可以试验把‘\82’换成‘\zz’,则a的值为z,因此这道题选择包含一个字符。

牛客C语言题_第2张图片
在构造函数XB的下列定义中,正确的是()
A.XB::XB(int a,int b):x(a),y(b){ }

B.XB::XB(int a,int b):XA(a),y(b){ }

C.XB::XB(int a,int b):x(a),XB(b){ }

D.XB::XB(int a,int b):XA(a),XB(b){ }

派生类中的数据成员有基类中的数据成员和新增加的数据成员构成,如果新增加的数据成员中还包含有对象成员,则这些新增加的数据成员还会间接的包含这些对象中的成员,因此如果要对派生类中的成员进行初始化,就应该对以上这些数据成员进行初始化。
在类外定义派生类的构造函数的一般形式有两种为:
(1<派生类名>::<派生类名>(参数总表):基类名(参数表),对象名1(参数表1),对象名2(参数表2),...对象名n(参数表n)
{
    初始化语句;
}
参数总表中是需要进行初始化的三类数据成员(基类中的数据成员、派生类中新增加的普通类型的数据成员、派生类中新增加的对象中的数据成员)。对于使用默认构造函数的基类和对象成员,可以不给出类名或对象名以及参数表。

(2)也可以有另一种形式,那就是像本题中的,写成成员列表初始化的形式,也就是将(1)中构造函数体内的初始化语句搬到冒号后面去:
<派生类名>::<派生类名>(参数总表):基类名(参数表),对象名1(参数表1),对象名2(参数表2),...对象名n(参数表n),派生类中的成员(参数表){ }3)中成员列表初始化的方式更常用。
XB::XB(int a,int b): XA(a),y(b){}   派生类构造函数不能直接初始化类中的基类成员,因为它们在基类中可能是私有的,不能访问赋值。要想初始化这些基类成员,必须通过基类的构造函数才能完成。
调用基类构造函数  语法形式:
派生类构造函数名(形参列表):基类名(形参1),基类名(形参2),····
{
    ······初始化派生类成员变量
}
假定x=65530,下面函数的返回值是多少?()
int func(x)
{
    int countx = 0;
    while (x)
    {
        countx++;
        x = x & (x - 1);
    }
    return countx;
}

求代码输出

做对此题有两个关键点:
1、知道函数的功能是求1的个数
2、能够快速将65530换算成二进制
6553516165530=65535-55101,有21,则65530141
union X
{
    int x;
    char y[4];
};
如果
X a;
a.x=0x11223344;//16进制
则:()

A.y[0]=11

B.y[1]=11

C.y[2]=11

D.y[3]=11

这里需要考虑存储模式:大端模式和小端模式。
大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
union 型数据所占的空间等于其最大的成员所占的空间。对union 型的成员的存取都是相对于该联合体基地址的偏移量为0 处开始,也就是联合体的访问不论对哪个变量的存取都是从union 的首地址位置开始。

数组在大端小段情况下的存储

在这里一、以value=0x12345678为例
Big-Endian 大端  :低地址存放高段位
buf[3] (0x78) – 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) – 高位

`Little-Endian:低地址存放低位,如下:
高地址
buf[3] (0x12) – 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) – 低位

C代码中可能会出现如下类型的结构体定义:

 typedef struct holder {
  struct holder *next;
  struct holder *prev;
  char buffer[ 0 ];
  }holder;

A.方便管理内存缓冲区
B.减少内存碎片化
C.是结构题数据对其
D.没有作用

答案 A B

下面是网络上一些关于柔性数组的知识
typedef struct{ 
char a; 
char b[0]; 
};

其中 char b[0], 叫做柔性数据。

这是个广泛使用的常见技巧,常用来构成缓冲区。比起指针,用空数组有这样的优势:  
1.不需要初始化,数组名直接就是所在的偏移  
2.不占任何空间,指针需要占用int长度空间,空数组不占任何空间。  
 
“这个数组不占用任何内存”,意味着这样的结构节省空间;“该数组的内存地址就和他后面的元素的地址相同”,意味着无需初始化,数组名就是后面元素的地址,直接就能当做指针使用。 

方便管理内存缓冲区
减少内存碎片化

若变量已正确的定义为float类型,要通过输入函数scanf(“%f%f%f”,&a,&b,&c)给a赋值10,b赋值22,c赋值33,以下不正确的输入形式是

A 10
  22
  33
B 10.0,22.0,33.0
C 10.0
  22.0,33.0
D 10       22
  33 	

答案为BC
scanf的引号内不存在逗号

你可能感兴趣的:(牛客C语言题)