【C++】专项练习(2)(牛客)

  • 1、按位与运算符(&)
    • 按位与运算符(&)
    • 按位或运算符(|)
      • 拓展函数:
  • 2、指针是否偏移
  • 3、二维数组与指针
    • 知识点
  • 4、面向对象特点
    • 封装
    • 继承
    • 多态
  • 5、ASCII 码、BCD码、内部码、十进制码
  • 6、递归
  • 7、带默认形参值的函数
    • 知识点
  • 8、指针数组和数组指针
    • 指针数组
    • 数组指针
    • 区分
  • 9、常对象(const)与常函数
    • 常对象
  • 10、构造函数与析构函数的调用顺序
  • 11、非零即为真
  • 12、**%d在遇到非数字字符时scanf认为输入结束**
  • 13、vector
    • vector::at()
      • 代码示例
    • vector::operator[]
  • 14、迭代器 遍历
  • 15、fork()遇到for循环
    • fork
  • 16、父类子类继承
  • 17、合法的浮点型数据
  • 18、*p++ 运算符优先级
    • **运算符优先级表**
  • 19、if、else匹配
  • 20、gcc与g++

1、按位与运算符(&)

题目
下面程序中, 输出是什么?

int fun(int x){int count = 0;while(x){count++;x = x &(x-1);}return count;
}
int main(){cout << "fun(2015)=" << fun(2015)<<endl;
}

思路
该函数的功能:用于查找数值的二进制中有多少个1
x = x &(x-1);是什么意思:按位与运算将x用二进制表示时最右边的一个1变为0

按位与运算符(&)

参加运算的两个数,按二进制位进行“与”运算。

运算规则:只有两个数的二进制同时为1,结果才为1,否则为0。(负数按补码形式参加按位与运算)

按位或运算符(|)

参加运算的两个数,按二进制位进行“或”运算。
运算规则:参加运算的两个数只要两个数中的一个为1,结果就为1。

拓展函数:

用于查找数值的二进制中有多少个0
每一次或运算,x的二进制从低位到高位,遇到bit为0依次少一个0

while(x){count++;x = x | (x+1);}//统计x的二进制中有多少个0

来源:牛客网
解析
每执行一次x = x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1将会将该位(x用二进制表示时最右边的一个1)变为0。
2015 二进制 11111011111
2014 二进制 11111011110
按位与运算(有0则0)得:11111011110
该函数旨在计算二进制有多少个1----10个

2、指针是否偏移

题目
以下程序的运行结果是()

#include <iostream>
using namespace std;int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};void fun(int* pa, int n);int main() {int m = 10;fun(a, m);cout << a[6] << endl;
}void fun(int* pa, int n) {for (int i = n - 1; i > 0; i--)*(pa + 6) += pa[i];
}

思路

*(pa+6)=pa[6]
第一次循环:
pa[6]=pa[6]+pa[9]=7
2:pa[3]=pa[3]+pa[8]=13
指针一直向前偏移6位,会从头开始吧。
3:8
4:13
5:8
6:13
7:8
8:3
9:8
10:3
错因:以为 *(pa+6)=pa[6]是指针偏移并赋值的意思,其实一直都是指向数组的第7个元素。
解析:
关键点: *(pa + 6) += pa[i];是什么意思? *(pa + 6):数组中的第七个元素
i=9: a[6]=a[6]+a[9]=7+0=7
i=8:a[6]=a[6]+a[8]=7+9=16
i=7:a[6]=a[6]+a[7]=16+8=24
i=6:a[6]=a[6]+a[6]=24+24=48
i=5:a[6]=a[6]+a[5]=48+6=54
i=4:a[6]=a[6]+a[4]=54+5=59
i=3:a[6]=a[6]+a[3]=59+4=63
i=2:a[6]=a[6]+a[2]=63+3=66
i=1:a[6]=a[6]+a[1]=66+2=68
此时i=1>0,i++,i不满足循环条件,退出循环。

3、二维数组与指针

题目

知识点

解析

1、&a+1整个变量(二维数组)。
2、a+1一维数组
3、a[0]+1跨一个int

a是数组首地址,也就是a[0]的地址,
&a是对象(数组)首地址,
a+1是数组下一元素的地址,即a[1],
&a+1是下一个对象的地址。

所以int*(&a+1)意思是ptr指向下个数组变量的地址,ptr-3表示指针向前偏移三个元素的位置,也就是指向a[1][2]的地址,加*意思是取该地址存储的内容数据,也就是9.

4、面向对象特点

题目
面向对象方法的多态性是指()
一个类可以派生出多个特殊类
一个对象在不同的运行环境中可以有不同的变体
针对一消息,不同的对象可以以适合自身的方式加以响应
一个对象可以是由多个其他对象组合而成的
知识点
C++ 面向对象三大特征(封装、继承、多态)—BC菜鸟

封装

封装(encapsulation)即信息隐蔽。它是指在确定系统的某一部分内容时,应考虑到其它部分的信息及联系都在这一部分的内部进行,外部各部分之间的信息联系应尽可能的少。

public:对外公开,访问级别最高
protected:只对同一个包中的类或者子类公开
默认:只对同一个包中的类公开
private:不对外公开,只能在对象内部访问,访问级别最低

struct 和 class 区别:struct默认权限是public ;class默认权限是private

继承

我们发现,定义这些类时,下级别的成员除了拥有上一 级的共性,还有自己的特性。这个时候我们就可以考虑利用继承的技术,减少重复代码
继承:让某个类型的对象获得另一个类型的对象的属性和方法。继承就是子类继承父类特征行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
1)继承父类成员变量/方法
2)重写父类方法
3)重载父类方法
重载方法必须满足以下条件:
1、方法相同
2、方法的参数类型、个数、顺序至少有一项不同
3、方法的返回类型可以不同
4、方法的修饰符可以不相同

多态

多态:对于同一个行为不同子类对象具有不同表现形式
多态存在的3个条件:
1)继承 2)重写 3)父类引用指向子类对象。
多态的实现方式分析:
覆盖:是指子类重新定义父类的虚函数的做法。
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

静态多态:函数重载运算符重载属于静态多态,复用函数名
动态多态:派生类虚函数实现运行时多态
参考:什么是面向对象,它的三个基本特征:封装、继承、多态—冰棍hfv
解析

5、ASCII 码、BCD码、内部码、十进制码

题目
字符型常量在内存中存放的是
ASCII码
BCD码
内部码
十进制码

解析

√ASCII 码使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符
BCD码(Binary-Coded Decimal‎)亦称二进码十进数或二十进制代码。用4位二进制数来表示1位十进制数中的0~9这10个数码。是一种二进制的数字编码形式。
内码是指汉字系统中使用的二进制字符编码
十进制码面向的是开发人员,经过转化对应的编码给计算机使用。

6、递归

题目
根据下面递归函数:调用函数Fun(2),返回值是多少()

int Fun(int n)
{ if(n==5)     return 2;        else        return 2*Fun(n+1);
}

解析
Fun(2)=2Fun(3)=22Fun(4)=222Fun(5)=222*2=16

7、带默认形参值的函数

题目
考虑函数原型void test(int a,int b=7,std::string z=“*”),下面的函数调用中,属于不合法调用的是( )
test(5)
test(5,8)
test(6,“#”)
test(0,0,“#”)

知识点

1、函数定义或者声明的时候,给形参赋默认值
调用函数时,如果没有给出实参,按指定的默认值进行工作

2、可能产生二义性:编译器不能确认调用的是哪个函数
3、需要从右向左为参数赋默认值,不然会报错
4、调用的时候,实参给的顺序:从左向右
5、函数声明时指定默认值后,定义时就不能再赋默认值

  • 有默认值的参数必须在放在形参列表的最
  • 形参的默认值必须从右往左写。这点条件来自于函数调用堆栈,形参在入栈的时候是从右往左入栈的

解析
此题可能无解
传递实参不能跳过

C选项的意图是希望跳过第二个参数,传递第三个参数,但是实际上会发生类型转换把#转换为int,所以编译起来其实是通过的

8、指针数组和数组指针

题目
对于int *pa[5];的描述,正确的是()

pa是一个具有5个元素的指针数组,每个元素是一个int类型的指针;
pa[5]表示某个数组的第5个元素的值;
pa是一个指向数组的指针,所指向的数组是5个int类型的元素;
pa是一个指向某个数组中第5个元素的指针,该元素是int类型的变量;

指针数组

定义:多个同类型指针的集合,指针类型的数组
int *ptr[5];指针数据类型 *指针数组名[指针元素个数]

数组指针

int (*ptr)[5];将变量名与*括起来,表示这是一个指针,指向一个数组的首地址

区分

区分int *p[n]; 和int (*p)[n]; 就要看运算符的优先级了。
int *p[n]; 中,运算符[ ]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组。
int (*p)[n]; 中( )优先级高,首先说明p是一个指针,指向一个整型的一维数组。
解析
正确答案: A 你的答案: C (错误)
int *pa[5];为指针数组。

9、常对象(const)与常函数

常对象

常对象就是创建初始化之后不能改变的对象
常对象只能调用常函数,就是说函数声明是有const关键字的成员函数。

一旦将对象定义为常对象之后,不管是哪种形式,该对象就只能访问被 const 修饰的成员了(包括 const 成员变量和 const
成员函数),因为非 const 成员可能会修改对象的数据(编译器也会这样假设),C++禁止这样做。

10、构造函数与析构函数的调用顺序

题目

class A;
class B;
int main() {A a;  B b;  return 0;
}

在 main 函数中,变量 a 和 b 的构造函数和析构函数的调用顺序是()
答案:a构造 - b构造 - b析构 - a析构
解析

在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反,即先构造的后析构,后构造的先析构。它相当于一个栈,先进后出。

11、非零即为真

题目
对于条件表达式(k)?(i++):(i–)来说,其中的表达式k等价于()
k0
k1
k!=0
k!=1
解析
k为真(非零)i++,k为假(0)i–

12、%d在遇到非数字字符时scanf认为输入结束

有如下程序,输入数据:12345M678<CR>后(表示回车),x的值是()

#include<stdio.h>
int main(){int x;float y;scanf("%3d%f", &x, &y);return 0;
}

12345
123
45
345
解析
%3d表示输入的整数,其宽度为3,因此,只取123
输出结果123 45.000000(因为M对于单精度来说是非法数字遇到它就结束)
%d在遇到非数字字符时scanf认为输入结束

如果遇到非数字字符,scanf(“%d”)是会自动忽略的,且认为读入已经结束了,如果是给数组赋值,非数字字符之后的空间其实都没有被成功赋值,

13、vector

w3school-vector
顺序容器:向量、双端队列、链表
1、向量
特点:地址是连续的,方便高效的访问单个元素,动态结构,大小不固定,可以在程序运行时增加或减少
 内存用尽时,向量自动分配更大(成倍)的连续内存区,将原先的元素复制到新的内存区,并释放旧的内存区。永远不会存在越界的情况
怎么用
a.加头文件
b.实例化一个类模板:初始化:vector<数据类型> vec;
vector<数据类型> 对象名;创建向量对象的时候会走构造函数
c.查看容器大小vec.size() //元素个数

d.插入数据:vec.insert(vec.begin(),200);
vec[0] 第一个元素

e.删除
e1.删除第三个:从头开始偏移2位
e2.删除第三个以及后面的

f.清空

g.访问向量中所有的元素
g1.for循环

g2.迭代器访问
容器的end在最后一个元素的后面,所以迭代器不能为end
迭代器定义:
for循环

end为最后一个元素的下一个

vector::at()

但at()是我们的首选,因为at()进行了边界检查,如果访问超过了vector的范围,将抛出一个例外

代码示例

#include <iostream>
#include <vector>
#include<stdio.h>
using namespace std;
int main()
{vector<int>test;//建立一个vector
test.push_back(1);
test.push_back(2);//把1和2压入vector,这样test[0]就是1,test[1]就是2
printf("%d\n",test.at(0));
return 0;
}

vector::operator[]

operator[]主要是为了与C语言进行兼容。它可以像C语言数组一样操作。由于operator[]容易造成一些错误,所有我们很少用它。
题目:

T是一个数据类型,关于std::vector::at 和 std::vector::operator[] 描述正确的是:

at总是做边界检查, operator[] 不做边界检查.
at 不做边界检查, operator[] 做边界检查.
at和operator[] 是一样的

解析

正确答案: A 你的答案: B (错误)
结论:at()总是做边界检查,下标运算符(operator[] )不做边界检查。
解析(详情参看 《C++ Primer》(第5版) P310 ”下标操作和安全的随机访问“):
提供快速随机访问的容器(如:string、vector、deque 和 array)也都提供下标运算符(operator [ ])。
一、下标运算符接受一个下标参数,返回容器中该位置的元素的引用。给定下标必须保证”在范围内“(即,大于等于0,且小于容器的大小)。保证下标有效是程序员的责任,下标运算符并不检查下标是否在合法范围内。使用越界的下标是一种严重的程序设计错误,而且编译器并不检查这种错误。
c[n] : 返回c中下标为n的元素的引用,n是一个无符号整数。若n>=c.size(),则函数行为未定义。
二、如果希望确保下标是合法的,可以使用at成员函数。at成员函数类似下标运算符,但如果下标越界,at会抛出一个out_of_range异常。
c.at(n): 返回下标为n的元素的引用。如果下标越界,则抛出一个out_of_range异常

14、迭代器 遍历

【c++STL——第十一讲】iterator系列 (常用知识点总结)—lyshark 粉丝

C ++迭代器用于对数据结构中的元素进行顺序访问或随机访问。因此,对于根据定义不允许顺序或随机访问的数据结构,迭代器没有任何意义。这就是堆栈和队列没有迭代器的原因。

15、fork()遇到for循环

题目

for (int i = 0; i < 2; i++)
{fork();printf("-\n");
}

会打印出多少个"-"?

fork

一次调用,两次返回。
返回子进程id的为父进程。
返回0的为子进程。
在fork()的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令变量值程序调用栈环境变量缓冲区,等等。
思路
原先:我以为是执行到fork就会复制出一模一样的代码,再执行到各自的fork再复制一直循环。
实际:其实确实也是这样,但是第一次fork生成子进程B后,现在有两个一模一样的进程了,且都运行到了fork语句后面开始打印printf了。此时打印了两次-。然后两个进程都i++,开始第二次循环。两个进程运行到fork又各自生成了进程,且都运行到了fork语句后面,开始打印printf。
此时要注意看,print语句中是否有换行符\n
没有\n,子进程就会把父进程缓存区里的-,一起复制进去。也就是第二次fork的子进程会将父进程缓冲区打印的-,一起复制了。导致第二次循环后,除了两个父进程和两个子进程打印的-之外,还有复制的两个缓冲区的-。也就是一共2(第一次fork的父与子)+2(第二次fork的两个父)+2(第二次fork的两个子)+2(第二次fork的两个子复制的两个父的缓冲区)=8
有\n,就会把数据刷出缓冲区。也就没有那两个缓冲区的-了。一共打印6个-。
参考:for循环中的fork()—Lee_01

16、父类子类继承

题目:
有如下程序段:

#include "stdio.h"class A
{public:int _a;A(){_a = 1;}void print(){printf("%d", _a);}
};
class B: public A
{public:int _a;B(){_a = 2;}
};
int main()
{B b;b.print();printf("%d", b._a);
}

请问程序输出:

22
11
21
12

解析:
因为在继承的时候,允许子类存在与父类同名的成员变量,但是并不覆盖父类的成员变量,他们同时存在。 因为给孩子类中没有定义print函数,所以会按照就近原则去寻找父类中是否有print函数。恰好父类中有这个函数,于是调用父类的print函数b.print(),而这个函数会调用父类的a变量
正确答案: D 你的答案: A (错误)

17、合法的浮点型数据

题目:
在下列选项中,全部都合法的浮点型数据的选项为()
正确答案: B 你的答案: B (正确)
1e3.5 15. 2e4
12.34 1e+5 0.1E12
0.2e2 12345. e5
5.0e(1+4) 0.1 8e+2
知识点
合法的浮点数有两种表示形式:
十进制小数形式。由数字和小数点组成,必须有小数点。例如(123.)(123.0)(.123)。比如 1.和.1也是合法的表达。
指数形式。如123e3。字母e(或E)之前必须有数字,e后面的指数必须为整数
规范化的指数形式里面,小数点前面有且只有一位非零的数字。如1.2345e8
解析
A。1e3.。e后面指数不能是小数,必须是整数。
C:e5 。e之前必须有数字
D:5.0e(1+4)。 e后面只能是整型常量,不能是表达式。

18、*p++ 运算符优先级

题目:
*p++ 自增 p 还是 p 所指向的变量?

自增 p
自增 p 所指向的变量
和机器相关

运算符优先级表


解析:
++优先级比*高,因此先进性指针指向对象的变化,再取取指针指向的内容。

正确答案: A 你的答案: B (错误)
后缀++ 和-- 操作符本质上比前缀一目操作的优先级高, 因此*p++ 和*(p++) 等价, 它自增p 并返回p 自增之前所指向的值。
要自增p 指向的值, 使用(*p)++, 如果副作用的顺序无关紧要也可以使用++*p。

19、if、else匹配

题目:
C++语言的if语句嵌套时,if与else的配对关系是 每个else总是与它上面的最近的if配对。说法是否正确?

正确答案: B 你的答案: A (错误)
正确
错误
解析:
else与它前面最近没有匹配的在同一复合语句中的if匹配。

if(a>b)
{if(b>c)cout<<"b>c"<<endl;
}
else   cout<<"b>=a"<<end;

20、gcc与g++

题目:
以下说法正确的是()

gcc编译.c文件,__cplusplus没有定义,编译器按照c编译代码
gcc编译.cpp文件,__cplusplus有定义,编译器按照c++编译代码
g++编译.c文件, __cplusplus没有定义,编译器按照c编译代码
g++编译.cpp文件,__cplusplus有定义,编译器按照c++编译代码
解析:
gcc和g++都是GNU组织的编译器。 在编译**.cpp**,两者都是将其视为C++来搞; 但是,两者区别地方在于,编译.c文件时,gcc将其视为C程序,而**g++将其视为C++**程序。
正确答案: A B D 你的答案: 空 (错误)

【C++】专项练习(2)(牛客)相关推荐

  1. 爬虫实现爬取牛客网数据结构试题

    1 目标 爬取牛客网上关于<数据结构>的试题. 试题链接 进入网页可以看到,如果选择<数据结构>的某个知识点组卷,一次最多只能出30题. 因此,想法就是用程序一次将30题全部爬 ...

  2. python简单实践作业答案_python入门实践四:爬取牛客网面试专项练习题及答案

    说明:个人练手python用. 操作系统:window10 x64 IDE:Pycharm 2017.2.2 Python版本:3.6.2 目标 牛客网是一个IT笔试面试的平台,提供了很多题库,今天我 ...

  3. 牛客网-Java专项练习11

    牛客网-Java专项练习11 1.关于抽象类和接口叙述正确的是? ( ) A.抽象类和接口都能实例化的 B.抽象类不能实现接口 C.抽象类方法的访问权限默认都是public D.接口方法的访问权限默认 ...

  4. 【牛客网】C/C++牛客网专项刷题(02)

    以下为牛客网C/C++专项刷题: 1.虚函数不可以内联,因为虚函数是在运行期的时候确定具体调用的函数,内联是在编译期的时候进行代码展开,两者冲突,所以没有一起使用的做法. 2.C++中构造函数和析构函 ...

  5. 【牛客网】C/C++牛客网专项刷题(00)

    以下为牛客网C/C++专项刷题: 1.若要打开A盘上user子目录下名为abc.txt的文本文件进行读.写操作,符合此要求的函数调用是( ). KEY:fopen("A:\\user\\ab ...

  6. 【牛客网】C/C++牛客网专项刷题(01)

    以下为牛客网C/C++专项刷题: 1.下面程序会输出什么: static int a=1; void fun1(void){ a=2; } void fun2(void){ int a=3; } vo ...

  7. 【牛客网】C/C++牛客网专项刷题(03)

    以下为牛客网C/C++专项刷题: 1.阅读以下程序,当输入数据的形式为12a345b789↙,正确的输出结果为(). void main() {char c1,c2;int a1,a2;c1=getc ...

  8. 【牛客网刷题】中秋节前开启java专项练习错题总结第一天

    [牛客网刷题]中秋节前开启java专项练习错题总结第一天 概述 写在前面 错题分析 值得记录的错题 总结 写在最后 概述 还有十几天就到中秋节了,从此又老了一岁,也多了一年的知识积累.对于这样一个特殊 ...

  9. 【牛客刷题】SQL专项错题记录三

    1.按照dept_no进行汇总,属于同一个部门的emp_no按照逗号进行连接,结果给出dept_no以及连接出的结果employees CREATE TABLE `dept_emp` ( `emp_n ...

最新文章

  1. c#_foreach遍历
  2. elasticsearch term match multi_match区别
  3. 在网上找了一些j2ee的视频教程,有需要的朋友可以看看
  4. 函数-函数的基本组成
  5. cocos2dx 3.0研究(1)-- hello world程序
  6. 两个vlan如何互通_网络交换机VLAN的常识与划分方法,你知道吗?
  7. POJ 1226 Substrings(后缀数组)
  8. 关于WCDMA中的扩频和调制(更新中)
  9. RBF神经网络-高斯核函数
  10. android怎么改名字,手把手教你如何修改安卓软件的图标和名字
  11. microsoft word无法插入公式
  12. oracle工程师 的职业,数据库工程师的职业规划
  13. 华强盛HQST推出传输速度高达10Gbit/s网络变压器
  14. 黄牛用高性能服务器抢票,还在找黄牛“加速”抢票?成功抢票旅客:黄牛让我去12306候补...
  15. jsp页面打开为空白页
  16. 日常交通工具日语词汇
  17. GPS:一个去中心化的抽奖式Token Offering模型
  18. hibernate Criteria setProjection
  19. Hadoop启停服务命令大全
  20. 【Hadoop大数据分析与挖掘实战】(一)----------P19~22

热门文章

  1. ORACLE 通过数据值查找找表名和字段名
  2. 分析人工智能审核优点及智能审核原理
  3. Visual Studio 不显示SVN 状态图标解决方法
  4. 笑死!新娘吐槽新婚之夜博士老公赶了一晚论文... 网友:科研任务重,抽空结婚...
  5. Python操作常用数据库
  6. Power BI DAX函数学习:EARLIER
  7. 动态规划入门——多重背包与单调优化
  8. js调用文件服务器出现跨域,js 读取本地文件遇到ajax跨域问题
  9. php购物车数量加减代码,购物车商品数量加减效果
  10. 什么是单点登录(SSO)?单点登录(SSO)到底什么意思?【附逻辑Demo实例】