一天极限速成C++,不过大概率G,记录一下
程序结果输出:
1. switch语句
int main() {
int a = 4, c = 0, b = 1;
for (int i = 0; i < 5; ++i) {
switch ((--a) > 0) {
case 0:switch (c++)
{
case 0:cout << "%";
case 1:cout << "#";
} break;
case 1:switch (b)
{
case 0:cout << "*"; --b; break;
case 1:cout << "@"; --b; break;
}
default:cout << "&";
}
cout << "!" << endl;
}
return 0;
}
switch语句,++前置和后置
++i,先+1再运算;i++,先运算再+1
switch( i ){
case 0:
case 1:
…}
switch语句中的i表示起始的位置,i=0则从case 0 开始,一直往后执行(case 1…),如果i=10,case中没有这个数,有default:语句则执行default:语句,没有则直接结束
如果case语句有break则直接在这个case中结束,不执行后面的语句
@&!
*&!
&!
%#!
#!
2. 值传递,引用传递,指针
指针是指向存放某个变量的地址(找一个人,知道你住的地方,就可以把你找到)
声明指针变量:int * i;
将某个变量的地址赋给指针:
int j = 10;
i = &j;
cout << j << endl;//输出j的值
cout << i << endl;//输出j的地址
cout << *i<< endl;//输出j的值
指针传入函数
void chuancan(int *i)
{
*i = …//对 * i的操作才是对所指数据的操作
//如果仅仅对i操作,就是对指针指向的地址操作
}
int main(){
int j=10;
chuancan( &j );
}
//特别注意,如果有数据a[ ],那么a就是指向数组a[ ]的起始地址的指针,将数组传入函数可以有chuancan(a),那么在函数中可以直接写a[1]…这样
值传递
一个函数fun(int a,int b)中,a,b是形参,当在main函数中使用fun(1,2)时,启用临时变量a,b,并将1赋值给a,2赋值给b,那么1和2是实参。
引用
引用&在=的左侧时就是别名(&i = j ,就像你的名字和你的QQ名,两个名字都是你的,所以j是一个变量,i是j变量的另一个名字)
main中swap(a,b)//int a=100,b=200;
函数中void swap(int& x, int& y)
{
int temp;
temp = x; /* 保存地址 x 的值 /
x = y; / 把 y 赋值给 x /
y = temp; / 把 x 赋值给 y */
return;
}
这样就是直接交换变量a,b的实际值
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
void fun(int *a,int *b)
{
int *c;
c = a;a = b;b = c;
}
int main()
{
int x = 7,y=19;
int *p = &x,*q = &y;
cout<<*p<<" "<<*q<<endl;
fun(p,q);
cout<<*p<<" "<<*q<<endl;
return 0;
}
结果
7 19
7 19
因为他在函数中没有像我前面所说的对*i操作,仅仅是对i的临时变量操作,改变的是临时变量的指针,对p,q没有任何影响。所以要么在函数中对 * a, *b操作,即
int c; c= *a; *a=*b;*b=c;
要么直接传递引用void fun(int &a,int &b),int c;后面不变
3. 作用域,全局,局部,static
这个基本是和后面的调用顺序结合着考
在main函数外的声明的是全局变量,一直能活到程序结束
在main,或者其他函数里的就是局部变量,活到函数结束
所以在
int a;
fun(int b){
}
main(){
int c;
fun(c);
}
这样的例子中,a是最先有的,然后是main中的c,最后是b
销毁的顺序是b,c,a
这个思路就是后面类的构造,析构在全局,局部中的调用顺序
Static
这里讲一下在类中的静态成员(变量,函数)
类是所有对象的总和,对象是类中的一个具体实例。一如人是类,张三是对象,一些数据成员是私有的,比如张三的身高体重,每个人都有各自的数据,但是像人类总数这样的数据不好说是每个对象私有,这个数据显然是所有对象共同拥有。
所以有了静态成员,他就是这样类似的定义。在所有的最前面加上static,静态数据成员在使用时使用
类名::静态数据成员//int Human :: count =0;在类外初始化
静态函数成员使用时和静态数据一样的写法,但是静态函数可以直接访问静态数据和函数成员(这里注意),访问非静态成员就得通过对象名了
class A{
public:
static void f(A a,int b);
private:
int x;
static int b;
};
void A::f(A a,int b){
cout<<b;
cout<<a.x;//cout<<x;则错误,x是非静态,需通过对象引用
}
4. 构造,析构函数在派生类、基类、虚基类中的调用顺序
首先,构造函数是用于初始化对象的,析构函数是用于销毁对象的,派生类由基类派生出来,虚基类是某个类的基类中的共同基类(你:你爸,你爷爷,共同基类就是你爷爷;你:你爸,这种情况下共同基类就是你爸)
基类的语法形式
class Base3:virtual public Base0,public Base1{
…//base0有i0,base1有I1
}
class Base4 :public Base3{
public :
int i4;
}
在main中的Base4 b4可以直接使用b4.i0,显然Base3也可以用
执行顺序
1.有虚基类先虚基类(先构造函数)
2.然后按继承声明列表中的基类顺序执行(构造函数)
3.然后是执行这个类的构造函数(可能涉及基类的构造),然后是这个类的数据成员
4.在所有的执行结束后按照执行顺序反过来执行销毁过程
先解释一下第三点,如果Base4的构造函数的初始化列表
class Base4 :public Base3{
public :
int i4;
Base4(int a,inb): Base0(i0), Base3(i3){.....}//再次涉及基类的构造,所以要按这个顺序再执行一次
private:
Base3 x;//按数据成员的顺序再执行一次
Base0 y;
}
在第四点可能有其他情况——虚函数(用virtual定义成员函数)
关于虚函数-他只在类内声明,具体实现要在类外(实现时不带virtual关键字),C++中无虚构造函数,但是可以有虚析构函数,一个类有虚析构函数则由他派生出来的所有子类都是虚析构函数
☆当基类中析构函数并不声明为虚函数,这样delete 基类指针时,派生类析构函数就不会调用,从而造成内存泄漏
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
class M
{
public:
M(){
cout<<"M:start"<<endl;
}
virtual void print()
{
cout<<"this is M class"<<endl;
}
~M()
{
cout<<"end of M"<<endl;
}
};
class B:public M
{
public:
B(){
cout<<"B:start"<<endl;
}
void print()
{
cout<<"this is B class"<<endl;
}
~B()
{
cout<<"end of B"<<endl;
}
};
int main()
{
M *p = new B;
p->print();
delete p;
return 0;
}
M:start
B:start
this is B class
end of M
5. 异常
了解一下
https://www.runoob.com/cplusplus/cpp-exceptions-handling.html
try{
此处写正常语句,一般执行什么函数(在函数中对应的异常情况,如除0这样的,throw x//x为变量),然后出现什么异常
}//throw变量则catch变量,throw “报错//字符串”,则catch(const char* msg)
catch(int i){捕捉异常,然后写个cout意思一下}
补充:
- ascii码
‘\0’,它的ascii码是0
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
int main()
{
char s[] = "2d876fv8d76fv\0hs8c7s8d7c";//注意字符数组中有\0结束符哦
int i=0,num=0;
while(s[i]!=0)
{
if (s[i]<='9' && s[i]>='0')
num++;
i++;
}
cout<<num<<endl;
return 0;
}
- 类的基本知识,构造,析构
https://www.runoob.com/cplusplus/cpp-constructor-destructor.html
- 友元–常用于输入输出流的重载
在类定义中该函数原型前使用关键字 friend
class Box
{
double width;
public:
double length;
friend void printWidth( Box box );//printWidth() 是 Box 的友元,它可以直接访问该类的任何成员
void setWidth( double wid );
};
A是B友元,则由B声明,且A可以直接访问B的任何成员(友元关系是单向的,不可传递的,不被继承的)
class B{
…
friend class A;
…
}
- new,delete
M *p = new B;
必须要有delete p;
- const修饰
https://www.runoob.com/w3cnote/cpp-static-const.html
- 强制类型转换
dynamic_cast,static_cast
浅看一下 https://blog.youkuaiyun.com/u012411498/article/details/80804755
- 函数模板
`在函数前一行加template 《class T>
- 排序算法
https://www.runoob.com/w3cnote/ten-sorting-algorithm.html
了解一下第九章的插入,选择,桶排,折半查找啥的
- 随机数生成
srand(seed)//seed不同保证每次生成真正的随机数,可以将for循环的 i 加入其中
rand()
- ST L
时间紧迫,这部分收益太低,放了
- 拷贝构造函数
和构造函数相似不过参数是const Line &obj(常引用)
除了直接拷贝给新对象时,在将对象传入函数时需要用到拷贝构造,因为函数会生成一个临时变量,需要进行拷贝赋值,注意在临时变量消失的时候还会调用临时变量的析构函数
class Line
{
public:
int getLength( void );
Line( int len ); // 简单的构造函数
Line( const Line &obj); // 拷贝构造函数
~Line(); // 析构函数
private:
int *ptr;
};
// 成员函数定义,包括构造函数
Line::Line(int len)
{
cout << "调用构造函数" << endl;
// 为指针分配内存
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj)
{
cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
ptr = new int;
*ptr = *obj.ptr; // 拷贝值
}
- 进制转换
int a = 10;
cout << "八进制: " << oct << a << endl;
cout << "十进制: " << dec << a << endl;
cout << "十六进制: " << hex << a << endl;
cout << "二进制: " << bitset<sizeof(a)*8>(a) << endl;
stoi函数作用是将 n 进制的字符串转化为十进制,使用时stoi(s)
str.substr(7, 5).
使用substr函数从字符串str中提取从第7个字符开始,长度为5的子串,并将其存储在字符串sub中
填空、编程:
1. 字符串(非string)
定义char s[ ] = “abcdefg”;
输入字符串
https://blog.youkuaiyun.com/Lily13074092022/article/details/112279952
char s[100];
cin.getline(s,99);
cout<<s;
在写编程时可以用string
字符串与int转换
char s[10];
int n;
cin>>n;
s[0]=‘0’+n;
cout<<s[0];
传入函数void Reverse(char *s,int n)//字符串反转
{
for(int i = 0,j = n-1 ; i<j ; i++;j–)
{
char c = s[i];
s[i] = s[j];
s[j] = c;
}
}
2. 文件流
写入文本
打开
ofstream os(“D:/word.txt”);
if (!os) {
cerr << “File cannot be opened!\n” << endl;
exit(EXIT_FAILURE);
}
输入
os<<“字符串”<<char(i)<<i<<endl;
函数输入(接ofstream os(“D:/word.txt”);)
fun(os)
void fun(ofstream& os) {
os << "你好";
os << 10;
os << endl;
}
读取文本内容
ifstream inFile("D:/word.txt");
if (!inFile) {
cerr << "Unable to open file datafile.txt";
exit(1); // call system to stop
}
char temp[1024] = { 0 };
while(inFile >> temp){
};//字符,每次读一行
while (inFile >> x) {//处理数字
sum = sum + x;
}
inFile.close();
3. 运算符重载(输入输出流重载)
重载函数过于简单,就是函数同名,形参类型或者形参个数不同
但是一点–有默认参数值的时候必须无默认值在前,有默认值在后
int a(int b,int c=1,int d=10) √
int a(int b=0,int c,int d=10) ×
运算符重载
类内声明
类名 operator 运算符(const 类名 &对象变量) const;
类外实现
类名:: 类名 operator 运算符(const 类名 &对象变量) const{… }
特别注意,在运算符重载的形参列表中是省略的,省略了运算符中的第一个对象变量(如a+b,省略了a),用this指针替代这个对象
突然发现还是看郑莉老师的那三章课后题最好,有时间可以把下面链接都过一下
4. 定义一个类
看看这三章的课后题
https://blog.youkuaiyun.com/weixin_51704442/article/details/125959160
https://blog.youkuaiyun.com/weixin_51704442/article/details/125971463
https://blog.youkuaiyun.com/weixin_51704442/article/details/126008784
5. 递归编程
没时间了,这个看运气了,把历年真题里的那些递归看看就差不多了