C-C++语言程序设计参考文档[自制]
编程规范
加入代码:#include
一、基础语法
非法:int x; x(2); 合法:int x(2), y, z(3);
const int Max=60;//占内存,只读变量,能进行类型检查,更安全
#define Max 60//符号常量,不安全,无参的宏,不占用存储空间
const修饰指针:
const int *p=20;//指针所指对象被冻结,即不能改变这个指针指向的值
int *const p=20;//指针被冻结,即不能改变这个指针的地址
const int *const p=20;//指针和所指对象均被冻结
凡是在类的类体中实现的成员函数都是内联函数
c++默认把类内实现的成员函数是inline函数,类外实现的成员函数是非inline函数,想为inline要在类内加inline(即时性要求高和使用次数多时使用inline函数)
① 内联函数内不允许有循环语句和开关语句,否则当普通函数处理
② 内联函数通常适用于短函数
④ 用替换代替调用,从而提高效率,用空间换时间
⑥ 内联函数不能递归调用,其中不能定义静态变量和数组
注意,在C语言中使用带参数的宏定义来实现这个功能,例如:
#define sum(x) x+x
C++中:inline int sum(int x){ return x+x; }
① 减少目标代码,实现程序代码和数据的共享,代码复用
② 让使用者只看函数的功能和用法,不必关心实现,屏蔽实现细节
③ 函数调用浪费时间浪费空间(保护现场,恢复现场),故它是以降低效率为代价的
允许函数的形参变量带缺省值(默认值)
实质为函数重载的另一种形式,提高了函数调用的灵活性
函数调用时,编译器按从左至右的顺序将实参与形参变量匹配
当实参个数不够时,则采用形参缺省值来补足所缺实参
所有取缺省值的形参都必须出现在不取缺省值的参数的右边
当函数有原型时,形参的缺省值应在函数原型中声明,即缺省参数的说明,必须出现在函数调用之前
在一定条件下允许函数同名,即重载,C语言不允许
它在任一特定环境下所表述的意义还必须由其所处的上下文环境来决定
包括函数重载、运算符重载等
单单返回值不同,不能构成重载
当两个或两个以上普通全局函数的形参个数、类型和顺序不完全相同时,它们可以同名
当同一个类的两个或多个成员函数的形参个数、类型和顺序不完全相同时,它们可以同名
同名函数根据参数个数或类型或顺序来区分
普通全局函数与类的成员函数之间可以同名
基类(父类)成员函数和派生类的成员函数之间也可同名
同名函数根据对象名或类名来区分
#include
using namespace std;
float a=13.5;
int main()
{
int a=5;
cout<<::a<
return 0;
}
//C语言:
int x;
float y=16.02;
x=(int) y;
//C++:
int x;
float y=16.02;
x=int (y);//等同于x=(int) y;
浮点数向整型转换时:负数向0靠近,整数去尾法
① float i=-2.8; int j=int(i);则j=-2 i=-2.8
② float i=2.8; int j=int(i);则j=2 i=2.8
动态分配内存和动态释放内存,
int *p,*q,*r;
p=new int;
r=new int[10];
q=new int(100);//括号是赋值,不是指指针数组
*p=10;
cout<<*p<<”,”<<*q<
delete p;
delete q;
delete [] r;
output:10,100
主要用作函数的参数或函数的返回值,实现双向传递功能
引用传别名,指针传地址,返回引用的函数,其函数调用可作赋值语句的左值为了在函数间传递数据,指针的别名,也就是引用。
int a = 10;//定义一个整型变量a,并给a赋值10
int *p=&a;//定义一个指针变量p指向a,即p=&a
int *&q = p;//定义p的别名为q,*&q是给指针变量起别名的表达形式,这样定义后,对q的操作就是对p的操作,*q=*p=a=10
在定义返回引用的函数时,不能返回该函数内的局部变量
② int & f( )
{int x=5; return x; } //(×)
③ int & f(int x)
{return x;} //(×)
④ int * f(int & x)
{return & x;} //(√)
⑤ int & f(int & x)
{return x;} //(√)
⑥ int & f(int * p)
{return * p;} //(√)
⑦ int f(int & x)
{return x;} //(√)
⑧ int & f( )
{static int x=5; return x; } //(√)
OOP的三大特性:封装性、继承性和多态性
面向对象的程序设计=对象+对象+对象,对象=算法+数据结构
每个对象都是由数据和函数组成的,静态的为属性,即数据,动态的叫做行为,即函数
封装与信息隐蔽:对一个对象进行封装处理,把他的一部分属性和功能向外界屏蔽,在外面看不到这些属性和功能,即public,private
数据/属性是private,函数/行为是public
抽象:对象是具体的,类是对象的抽象,对象是类的具体实例,比如某个学生和学生类
多态性:由继承产生的新类
面向过程:围绕功能进行,一个函数一个功能,操作复杂,难操作,C语言,面向过程的程序设计是以数据结构为基础的算法设计。
① 用对象名引用对象成员:用成员运算符“.”
对象名.数据成员名;
或对象名.成员函数名(参数表)
stu1.sex;
stu1.name();
② 用对象指针引用对象成员:
对象指针名->数据成员名或对象指针名->成员函数名(参数表)
stu2->sex;
stu2->name();
2) 用成员运算符“.”
(* 对象指针名)•数据成员名或(* 对象指针名)•成员函数名(参数表)sex;
例如:(*stu).sex
用普通成员函数进行对象初始化,须显式调用,麻烦且不安全
15.1 构造函数:
① 在创建对象时,用给定值将对象初始化。实例化一个类,分配资源
② 是一个成员函数,其名字与类名相同
③ 通常是由系统自动调用的,常定义于公有部分
④ 无函数类型,无返回值
⑤ 可以有参数,故可以重载
⑥ 构造函数也可以采用构造成员初始化列表方式对数据成员进行初始化,但若数据成员存放在堆中或数组中,则不能用此法,而只能在构造函数中使用赋值语句
⑦ 构造函数不能用常规调用方法调用,不可取其地址,不能被继承
15.2 缺省构造函数:即不带形参的构造函数
① 若类中用户未自定义任何构函,则系统将自动生成一个默认构函
② 是构函的一种重载形式,是公有成员
③ 它无参数,是一个空函数
④ 系统自动调用它将外部或静态对象的数据成员初始化为0或空
而自动对象的数据成员的值是无意义的(随机的)
⑤ 默认构函可由用户自定义,但格式应为:类名::类名( ){}
⑥ 若程序中已显式定义了构函,无论它是否带形参,系统都不会提供缺省构函,此时若需要缺省构函,必须显式定义
15.3 析构函数:
① 其功能与构函相反,是在释放对象时,用它来做一些清理工作
② 是公有成员函数,其名字与类名相同,且前面加“~”。
③ 它无参数,不能重载;也无函数类型,无返回值,一个类有且仅有一个析构函数,通常定义于公有部分
⑤ 通常由系统自动调用:对象生存期结束时或用delete释放堆对象时
⑥ 具有相同作用域和生存期的若干同类对象,其构函调用顺序与析构顺序恰好相反。
注意:当一个类未显式定义析构函数时,系统将自动生成一个默认析构函数
15.4 拷贝构造函数:
① 是一种特殊的构函,是构造函数的另一种重载形式
② 它只有一个参数,且是本类对象的引用
③ 它通过将一个已知同类对象的值拷贝给一个新对象,来完成对新对象的初始化,即成员级复制或浅复制,把作为参数的对象的数据成员逐个拷贝到目标对象中
④ 每个类都必须有一个拷贝构造函数
⑤ 其名字与类名相同,无函数类型且无函数返回值,由系统自动调用
⑥ 在下述三种情况下,需调拷贝构函:
a.明确表示用一个对象初始化另一个对象时
b.当对象作为函数实参传递给函数形参时
c.当对象作为函数返回值时
注意:当一个对象创建时,分配了资源;或当一个类需要析构函数来显式析构资源时,则应深拷贝,即自定义拷贝构函,使之既拷贝数据成员值,又拷贝对象资源
15.5 缺省构造函数:
① 当用户未显式定义拷贝构函时,系统将自动生成一个缺省拷贝构函
② 是公有成员,是构造函数的重载形式
③ 其格式为:
类名 :: 类名(const 类名 & 对象名)
{* this=对象名;}
浅拷贝:只拷贝数据成员的值,可采用缺省拷贝构函,浅拷贝构造是创建一个对象B,并使B与A指向同一地址。
深拷贝:既拷贝数据成员的值,也拷贝对象的资源,如:堆内存、打开文件、占有硬件设备服务(如打印机)等,深拷贝构造是创建一个对象B,使B与A所指向的地址里面的东西一模一样。
如果类中含有指针变量,默认的拷贝构造函数必定出错。因此这时候就必须使用显式自定义的拷贝构造函数,即使用深拷贝
16. 空类:没有显式定义任何成员
空类对象大小不为零,即各对象具有不同的地址,常用空类作基类
空类中的缺省成员有5种:
a.缺省构造函数:类名( ) { }
b.缺省析构函数:~类名( ) { }
c.缺省拷贝构函:
类名(const 类名 & 对象名){*this=对象名;}
d.缺省赋值运算符重载函数:
类名& operator=(const 类名 & 对象名);
e.缺省取地址运算符重载函数:
类名*operator & ( ) {return this;}和
const 类名*operator & ( ) const {return this;}
① 是C++对C的扩展,它不仅可以有数据成员,还可以有成员函数
② 它只有两类成员:私有成员private和公有成员public(visual C++有protected成员)
③ 在缺省(默认)情况下,结构中的成员是公有的(class类中缺省成员为私有的,这是两者的唯一区别)
④ 是另外一种形式的类,很少用
⑤ 它可以有构造函数和析构函数
① 是C++对C的扩展,联合中既可有数据成员,又可有成员函数
② 其数据成员共享同一段内存,即存储在同一位置上
③ 可以有构造函数和析构函数
④ 联合的所有成员只能为公有成员(Visual C++中可以有public、protected、private三种成员,缺省为public成员)
⑤ 联合不能从其他类继承属性
⑥ 联合不能作为基类派生子类
⑦ 联合不能包含任何静态成员
⑧ 联合成员对象不能拥有自己的构函和析构函数
① 是在一个函数体内定义的类
② 它只能在定义它的函数体内使用,即它被隐藏在定义它的函数体内
③ 不能在类中说明静态的成员函数
④ 所有成员函数均须在类体内实现
⑤ 实践中,很少用
⑥ 目的:减少全局标识符(名字空间,命名冲突)
① 是在一个类中定义的类
② 目的是为了隐藏类名,减少全局标识符,限制类的使用范围,提高类的抽象能力
③ 当它在外围类作用域外使用时,需加外围类名限定
④ 嵌套类与外围类相互独立,它们只是语法书写格式上的嵌套
⑤ 当嵌套类的定义内容写于外围类体外时,须加外围类名限定
21.1临时对象
① 当函数返回一个对象时,要创建一个临时对象以带回返回值
② 系统调用拷贝构函,将返回对象拷贝到新创建的临时对象中
③ 创建的临时对象,只在整个创建它们的外部表达式范围内有效
④ 临时对象在外部表达式结束时析构
21.2 无名对象
① 即没有名字的对象
② 可用无名对象初始化一个引用
③ 可用无名对象拷贝构造一个对象
④ 可用无名对象作实参传递给形参
21.3 堆对象:
① 是在程序运行中,根据需要动态创建的对象
② 存放于内存堆中,用new分配,用delete释放
③ 创建堆对象时要调构函,释放时要调析构函数
④ 从堆中分配对象数组,只能调用默认构函,若该类无默认构函,将出错
21.4 子对象:
① 即对象成员,也称类的组合或类的聚集
② 是指一个类的对象作另一个类的数据成员
③ 内嵌子对象的类(组合类)的构造函数应包含对子对象的初始化。常采用成员初始化列表的方式来初始化子对象
④ 当创建对象时,其各个内嵌子对象也将被自动创建
⑤ 先执行子对象构函,再执行本类构函,析构顺序相反
⑥ 当有多个子对象时,其构函调用顺序取决于类中声明的顺序,而不是构函中冒号后的成员初始化列表顺序
⑦ 它体现的是聚合关系,即一个复杂对象可以化解为简单对象的集合,在一个描述复杂事物的类中,可以包含有若干个描述简单事物的类的对象。即它体现了客观世界中对象之间的包含关系
⑧ 只有在定义构函时,才能带成员初始化列表,在构函原型中,不能带成员初始化列表
23. 在main之外的class之后必须要有分号,在main之外的函数除了只是声明的之外,必须没有分号,类中定义的函数必须没有分号,只是声明的必须要有分号,定义的变量等要有分号,为便于记忆 ,可以把class看做一个main函数,规则是一致的。
class Student{private:int sex;public:void name(){};};
//Student stu1,*stu2;则Student是类名,stu1是对象名
24. C语言文件操作:https://www.cnblogs.com/saolv/p/7793379.html
#include
另外,windows下文件路径必须是双反斜杠“\\”(转义)
功能 |
名称 |
描述 |
打开 |
fopen()/fopen_s() |
FILE *fopen(char *pname,char *mode) errno_t fopen_s( FILE** pFile, const char *filename, const char *mode ); |
从文件读 |
fgetc //从文件中读一个字符 |
int fgetc( FILE * fp ); |
fgets |
char *fgets( char *buf, int n, FILE *fp ); |
|
fscanf //格式化读取文件中数据 |
int fscanf (FILE *fp,char *format,arg_list); |
|
fread//以二进制形式读取文件中的数据 |
int fread(void *buffer,unsigned sife,unsigned count,FILE *fp) |
|
getw//以二进制形式读取一个整数 |
int getw(FILE *fp) |
|
向文件写 |
fputc //写一个字符到文件 |
int fputc( int c, FILE *fp ); |
fputs |
int fputs( const char *s, FILE *fp ); |
|
fprintf //往文件中写格式化数据 |
int fprintf(FILE *fp,char *format,arg_list) |
|
fwrite//以二进制形式写数据到文件中去 |
int fwrite(void *buffer,unsigned sife,unsigned count,FILE *fp) |
|
putw//以二进制形式存贮一个整数到文件中 |
int putw(int n,FILE *fp) |
|
刷新 |
fflush |
int fflush(FILE *fp)//刷新流 stream 的输出缓冲区 用于读写转换时,即带‘+’ |
关闭 |
fclose |
int fclose( FILE *fp ); |
结束 |
feof//判断文件是否结束 |
int feof(FILE *fp) |
位置 |
ftell// fp当前读/写位置,相对文件开头的位移 |
long ftell(FILE *fp) |
重置 |
rewind//重置fp到文件开头 |
void rewind(FILE *fp) |
移动 |
fseek//使fp移到base的相对位置offset处 |
int fseek(FILE *fp,long offset,int base) |
终止 |
exit()函数使程序立即终止执行,同时将缓冲区中剩余的数据输出并关闭所有已经打开的文件 |
void exit(int status) |
返回值 |
fp/0/NULL/EOF |
fopen正常返回fp,异常返回NULL; 其余函数正常返回0或者读取的结果,异常返回EOF |
文件操作模式:b表示二进制文件,t表示文本文件,+表示可读写。一般使用r+、w+和a+即可
名称 |
功能 |
名称 |
功能 |
r |
只读,要求文件存在 |
r+ |
读写,要求文件存在 |
rb |
|
rb+ |
|
rt |
|
rt+ |
|
w |
只写,存在格式化,不存在创建 |
w+ |
读写 |
wb |
|
wb+ |
|
wt |
|
wt+ |
|
a |
追加只写,存在追加写,不存在创建 |
a+ |
追加可读写 |
ab |
|
ab+ |
|
at |
|
at+ |
|
https://blog.csdn.net/Sub_lele/article/details/78007919
#include
名称 |
功能 |
名称 |
功能 |
scanf() long long: %lld; float: %f; double: %lf; |
scanf("%s",&s)输入字符串时,遇到空格和回车都会结束,只能输入一个单词。 scanf("%c",&c)可以读入空格和换行 |
printf() |
long long: %lld; float: %f; double: %f;//%lf也可以,但推荐%f |
getchar() |
char/int ch2 = getchar(); 可用于吸收回车键 |
putchar(c) |
printf("%c",ch) |
gets(x) |
scanf("%s",&s) 遇到空格不结束,回车才结束,输入一行 |
puts(x) |
printf("%s\n",s) |
getch() #include |
不建议使用 输入一个字符不显示,不回车就会进行,用于屏幕暂停 |
getche() #include |
不建议使用 输入一个字符显示,不回车就会进行,用于屏幕暂停 |
二、C++ STL 标准模板库
1. 常用容器 #include
vector、set、string、map、queue、priority_queue、stack、pair
名称 |
定义 |
常见函数 |
vector-向量/变长数组#include 用途:
|
vector vector vector 访问:
vector
vi[i] = *(vi.begin()+i)
|
vi.begin();//左闭右开 vi.end(); vi.push_back(x);//添加到末尾 vi.pop_back();//删除尾元素 vi.size();//元素个数 vi.clear();//清空 vi.insert(it,x);//it处插入x vi.erase(it);//删除it处元素 vi.earse(first,last); |
set-集合 自动去重且有序 #include 用途: 自动去重且排序 multiset-自动去重不排序 |
set set set 迭代器访问
|
st.begin(); st.end(); st.insert(x);//无插入位置 st.find(value);//返回对应值的it,和其它函数配合使用 st.erase(it); st.erase(first,last); st.size(); st.clear(); |
string-字符串 #include string.h和string是不一样的头文件 #include strlen(str); strcmp(str1,str2); strcpy(str1,str2); strcat(str1,str2); |
string str; string str=”abcd”; 访问:
string::iterator it=str.begin();
vi[i] = *(vi.begin()+i)
|
str.begin(); str.end(); +=;//拼接 ==;!=;<;<=;>;>=;//比较大小,字典序ASCII str.length();str.size(); str.nsert(pos,string);//pos处插入string str.insert(it,it2,it3);//it处插入string的[it2,it3) str.erase(it); str.erase(first,last); str.clear(); str.substr(pos,len);//返回从pos开始的长度为len的字符串 string::npos;//常数-1,用作find函数失配时地返回值 str.find(str2);//返回str匹配到str2第一个的位置,否则string::npos str.find(str2,pos);//从pos开始查找,同上 str.replace(pos,len,str2);//将str从pos开始长为len的str替换为str2 str.replace(it1,it2,str2);//将str的[it1,it2)替换为str2 |
map-映射 #include 不能使用char数组 按照键从小到大排列,key和value唯一,字典序ASCII multimap一个key可以对应多个value 用途:
|
map map 访问:
map ::iterator it=mp.begin();
|
mp.begin(); mp.end(); mp.find(key);//返回迭代器 mp.erase(it); mp.erase(key);//删除对应key mp.erase(first,last); mp.size(); mp.clear(); mp.insert(pair);//详见pair |
queue-队列 #include 先进先出 用途: 广度优先搜索BFS 使用q.front()和q.back()前需要使用q.empty()判断是否为空 |
queue 访问: 只能通过q.front()和q.back()访问首尾元素 |
q.front(); q.back(); q.push(x);//x入队 q.pop();//首元素出队 q.empty();//判断是否为空,空则true q.size();
|
priority_queue-优先队列 #include 队首元素优先级最高 由堆(heap)实现,只能访问队首/堆顶元素 使用q.top()前需要使用q.empty()判断是否为空 用途:
|
priority_queue 访问: 只能使用q.top()访问队首元素 |
q.push(x); q.top(); q.pop(); q.empty(); q.size(); 优先级设置: priority_queue vector priority_queue vector greater friend bool operator < (fruit f1,fruit f2){ return f1.price |
stack-栈 #include 后进先出,只能操作栈顶元素 |
stack |
st.push(x); st.pop(); st.top(); st.empty(); st.size(); |
pair-对组 #include #include |
pair pair 访问: p.first;p.second; 首先比较first,相等再比较second |
临时pair:
用途:
mp.insert( pair mp.insert( make_pair(“hh”,5)) |
2. algorithm常用函数
max()、min()、abs()、swap()、reverse()、
名称 |
用法 |
max(x,y)/ min(x,y) |
返回最大值/最小值 |
abs(x)/fabs(y) |
abs(x)//整型绝对值 fabs(y)//#include |
swap(x,y) |
交换x和y的值 |
reverse(it,it2) |
顺序反转[it,it2) |
next_permutataion(a,a+3) |
给出全排列的下一个序列 |
fill(a,a+i,value) |
给数组或容器某一区间赋相同的初值 |
sort(a,a+4,cmp) |
默认从小到大排序 bool cmp(int a,int b){ return a |
lower_bound(first,last,value) upper_bound(first,last,value) |
第一个大于等于value的值的地址 >= 第一个大于value的值的地址 > 欲查元素的下标: lower_bound(first,last,value)-a a[lower_bound(first,last,value)-a] |
三、Algorithm
算法笔记
第1、2章 技巧
long long bigNum = 12345678955LL;
//常把long long类型如下代替
typedef long long ll;
#include
名称 |
用法 |
double fabs(double x) |
浮点数绝对值 |
double floor(double x) |
向小的取整 |
double ceil(double x) |
向大的取整 |
double pow(double x,double y); |
xy |
double sqrt(double x) |
x的算术平方根 |
double log(double x) |
logex,以e为底x的对数 |
double sin(double x)/cos/tan |
三角函数 |
double asin(double x)/acos/atan |
反三角函数 |
double round(double x) |
四舍五入 |
switch(表达式){
case 常量表达式1:
…
break;
…
case 常量表达式n:
…
break;
default:
…
}
//不建议使用,建议使用fill
memeset(ArrayName,Value,sizeof(ArrayName));
fill(a,a+5,value);
//直接赋值
char a[15]=“Hello”;
sscanf(str,“%d”,&n);//将字符数组str内容以%d的形式输入到n
sprint(str,“%d”,&n);//将n内容以%d的形式输入到字符数组str中
由于==是完全相同才是true,因此需要引入极小值eps来处理误差
const double eps=1e-8;
#define Equ(a,b)(fabs((a)-(b))<(eps))
时间复杂度
空间复杂度+
第3章 入门模拟
第4章 算法初步
第5章 数学问题
第6章 C++ STL
第7章 数据结构专题1
四、常见问题
int i;
const int &a=i;
a=3;//错误
i=8;//可以,i不是常量
/**************/
int a=3,b=4;
int &c=a;//c是a的别名
int &c=b;//错误的用法,一个别名只能对应一个变量
int a=3;
int &b=a;
int &c=a;
//一个变量可以有多个别名
/*************/
3. (*this).fun();*this->fun();
4. 静态数据成员不能通过构造函数方法进行初始化
如果是char a[10];那这10个元素都是随机的
如果是char a[10] = {'a','b','c'};那除了赋值的3个元素, 其他都是0
实际上在C语言中,NULL通常被定义为如下:
#define NULL ((void *)0)
也就是说NULL实际上是一个void *的指针,然后吧void *指针赋值给int *和foo_t *的指针的时候,隐式转换成相应的类型。而如果换做一个C++编译器来编译的话是要出错的,因为C++是强类型的,void *是不能隐式转换成其他指针类型的,所以通常情况下,编译器提供的头文件会这样定义NULL:
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
原型是:
double pow(double x, double y);
注意:double a = pow(13,0); a的值是1.0
Int a = pow(13,0); a的值是0
int num[20]={0}; //全部都是0
定义之后num[20]={0};//全部初始化为0
能当做局部变量的,就当做局部变量,尽量减少全部变量的使用,比如上面如果在函数外定义全局变量num[20],在函数内num[20]={0};时可能会出错,尚未找到出错原因
11. boolean类型:bool a = true; bool b = false;
12. getch(),#include