一.C语言基础
1.幂级数展开
解析:
2.逗号表达式和逗号分隔符
①int sum=7,num=7; sum=num++,sum++,++num;//逗号分隔符,sum=8
②int sum=7,num=7; sum=(num++,sum++,++num);//逗号表达式,sum=9
3.指针数组
题目所给参数为指针数组,也就是二级指针,指向指针的指针。B是二级指针数组,数组的内容是二级指针,不符合。D是数组指针,不符合。
4. 运算符优先级(1)
一开始掉坑先算z+=x,结果为4,没这个选项才反应过来。
复合赋值运算符 +=
关系运算符 >
条件运算符 ? :
增强运算符 ++
优先级:增强运算符>关系运算符>条件运算符>赋值运算符
5.运算符优先级(2)
%和*优先级相同。。。运算符优先级表
6. typedef
7.函数指针
要选错误的。。。函数指针的定义格式为 函数类型(*指针变量名)(形参列表),函数是有地址的,但是写不写&都可以
8. 宏定义
编译器在编译时会将宏定义展开,isum(i, (i+j), j)被展开为 ii+(i+j)+j。因此,若想宏定义sum(a, b, c)为a,b,c的和,应该定义为 # define sum(a, b, c) (a+b+c)
9.函数的定义
A.x为整形,不是指针,错误。
C.fun返回值为int*, return x += y可以转化为地址位移y个int大小,将位移后的值再赋给x, x作为函数返回。正确
10.二维数组的赋值
ptr是数组指针,第一次ptr=a+0表示指向数组a的第一行第一个元素,即a[0][0],所以 a[0][0]=1,
ptr指向下一行,所以 a[1][0]=2
11. const
只要看const出现在 * 的哪边,如果在左边表示被指物是常量,如果在右边表示指针本身是常量。
第一个 a 是指针,const修饰指针指向的内容
第二个 语法错误
第三个 const既修饰指针a指向内容,又修饰指针a
第四个与第三个相同,因为int const *a 和 const int *a 意义相同
12.C语言内存相关,malloc
malloc申请的是虚拟内存,并不是物理内存。
13 文件输入输出
注意打开文件采用的是w方式,该方法表示会将原文件清除,然后再重新写入
14. 三目运算符
铭记 表达式1 ? 表达式2 : 表达式3,把题目看成a<b?a:(c<d?c:d)
15. 指针
记住32位机器long是4个字节,而指针++是指加一个指向数据类型的大小,所以q++应该是往后移动了4个字节,指向了e
16.柔性数组
1.如果行列都写了维度可以不初始化
2.如果只写了列维度,必须初始化
17.指针++
short类型大小是2字节,char类型大小是1字节;
++p是地址偏移量为2字节,但是对于short类型来说就是相差1,转化为char*类型就是2;
18. char*字符常量区
p1和p2指向的是常量存储区的字符串常量,而strcat(p1,p2)试图修改p1的内容,p1指向文字常量区,其指向的内容无法修改
19.函数指针
使用函数指针时,指针可以像函数名一样,直接加括号和参数列表调用;也可先解引用再调用。
pt(256);(pt)(256);(*pt)(256)
20.有符号数与无符号数比较
有符号数与无符号数比较,会自动转换为无符号数
int a=-1;
unsinged int b=2;//则a大于b
21.数组传参
数组传参会降维,退化成指针
22.++(a++)
a++的结果是4,然后进行++4是不对的,++运算只是针对于变量的,不能对常量来进行++运算
23.extern和auto
函数的形参或变量的储存类型为auto。比如int age; 其实是auto int age, 在局部变量中,age的作用域就是当前局部变量的范围,一旦程序运行 出当前域,则此变量被隐藏或自动释放。
函数的隐含储存类型是extern,它属于变量声明,extern int a和int a的区别就是,前者告诉编译器,有一个int类型的变量a定义在其他地 方,如果有调用请去其他文件中查找定义。
24.gets函数
gets函数会覆盖原始初始化数据。
第一步 ss[10] = “1,2,3,4,5”;
第二步gets()之后,ss[10] = “A,B,C,\0,5"
第三步strcat()之后,ss[10] = “A,B,C,6,7,8,9”
strcat会在遇到第一个\0时开始拼接
25. float
二.C++基础
1.数组合法定义
一开始不知道D问题在哪,经指点:数组变量 a是常量指针,地址固定不可更改(char* const) ,不能赋值。
2.判断偶数
代了几个特殊值发现可以就选择正确了,后来经指点代6发现不满足,据说这个是判断是否是2 的n次方幂。。
3.容器特点
属于是忘了。。set底层是红黑树 O(logn),Hash_map 底层哈希表 O(1),Deque尾部可以直接修改O(1)
4.求类的大小(1)
纯属是把c++类的知识忘透了。子类在内存中占用的字节数 = 父类占用字节数 + 自身成员所占的字节数,如果有虚函数,要算上虚函数表指针。char[3] 占3个字节,虚函数表指针4字节,32位系统需地址对齐,故占8字节
5.求类的大小(2)
成员函数不占用内存
static静态成员变量存储在静态存储区,共享量,无需分配空间
存在虚函数,虚函数需要构建虚函数表,在该类中存在一个指向虚函数表的指针
6.父类子类+virtual
- 如果父类中f()不是虚函数:对象指针进行的普通成员函数的调用,仅仅与指针的类型有关,而与此刻指针正指向什么对象无关。所以p指针是父类指针,会调用A::f(),这是静态联编。
若要想实现当指针指向不同对象时执行不同的操作,就必须将基类中相应的成员函数定义为虚函数,进行动态联编。所以该题中的p指针会调用子类对象的函数B::f() - 由于f() const在基类中未声明为虚函数,故p->f() const 根据指针类型(A)调用A::f() const,此时编译器对非虚方法使用静态联编,输出A::f() const。
7. strcpy与strcat应用
strcat(p1 + 2, p2 + 1);//表示将p2+1所指字符串"BCD"拼接在"cd"字符串后面形成"cdBCD";
strcpy(str + 2, “cdBCD”);//将字符串拷贝到str +2 的未知形成"xycdBCD"
8. 联合体
d.x,d.y以及d.s.x都是前四个字节,所以他们的值永远相等,
d.x=1;///d.x=d.y=d.s.x=1;
d.y=2;///d.x=d.y=d.s.x=2;
d.s.x=d.xd.x;///d.x=d.y=d.s.x=22=4;
d.s.y=d.y+d.y;///d.x=d.y=d.s.x=4+4=8;
9.基类派生类
当基类构造函数需要外部传递参数才能进行初始化时,派生类必须显式定义构造函数,为基类传递参数;基类如果不需要传递或者可以不传递参数,派生类可以不用显式定义构造函数。
10.extern
extern "C"指令中的C,表示的一种编译和连接规约,而不是一种语言。C表示符合C语言的编译和连接规约的任何语言,如Fortran、assembler等。
11.纯虚函数
纯虚函数的格式:virtual 返回值类型 函数名(参数列表) = 0;
12.运算符重载
13.类和对象
Qiniuome a();是函数声明.
14.dynamic_cast和static_cast
dynamic_cast:允许不同类型的转换,只要被转换类型存在多态方法。
static_cast:把子类的指针或引用转换成基类表示是安全的,但把基类指针或引用转换成子类指针或引用时,由于没有动态类型检查,所以,它是不安全的。
struct B1{
virtual ~B1(){}
};
struct B2{
virtual ~B2(){}
};
struct D1 : B1, B2{};
int main()
{
D1 d;
B1* pb1 = &d;
B2* pb2 = dynamic_cast<B2*>(pb1);//L1:编译成功,B1有虚函数
B2* pb22 = static_cast<B2*>(pb1); //L2:编译失败
return 0;
}
15.运算符重载
(1)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。
(2)单目运算符最好重载为成员函数。
(3) 对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。
(4) 对于其它运算符,建议重载为友元函数。
三.数据结构
1.层序遍历
看到队列先进先出,应首先想到二叉树层序遍历,一开始没看懂for循环,原来child_node意思就是左孩子与右孩子
2.求字符串子串个数
非空子串的个数共有n(n+1)/2=55个,相同子串算一个,1个字符时有3个w,2个q,2个. 2个字符时有2个ww 故应减去:(2+1+1+1)=5
3.二叉排序树
大意了。。比如排序树1->2->3,最小元素1为根节点
4.子集树问题
5.求n个节点构成二叉树的种类
公式:卡特兰数
6. 败者树
牛客网友提供的答案。