typedef unsigned int uint32_t;//_t意味着是typedef定义
typedef unsigned long uLint32_t;
typedef unsigned long long uint64_t;
typedef unsigned short int uint16_t;
---------------------------------------------------
#ifndef __int8_t_defined
# define __int8_t_defined
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
# if __WORDSIZE == 64
typedef long int int64_t;
# else
__extension__
typedef long long int int64_t;
# endif
#endif
---------------------------------------------------
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
*size_t 和 int 比较
**size_t在32位架构中定义为:
typedef unsigned int size_t;
**size_t在64位架构中被定义为:
typedef unsigned long size_t;
**size_t是无符号的,并且是平台无关的,表示0-MAXINT的范围;int为是有符号的;
**int在不同架构上都是4字节,size_t在32位和64位架构上分别是4字节和8字节,在不同架构上进行编译时需要注意这个问题。
**ssize_t是有符号整型,在32位机器上等同与int,在64位机器上等同与 long int.
#include
*string中find()返回值是字母在母串中的下标位置。
如果没有找到,那么会返回一个特别的标记npos,一般写作string::npos。
#include
#include
using namespace std;
int main()
{
string str;
cin>>str;
//主要字符串是从0开始计数的
cout<<"ab在str中的位置:"<<str.find("ab")<<endl;
//返回第一次出现ab的位置,没有则返回一串乱码
cout<<"ab在str[2]到str[n-1]中的位置:"<<str.find("ab",2)<<endl;
//返回第一次从str[2]开始出现ab的位置,没有则返回一串乱码
cout<<"ab在str[0]到str[2]中的位置:"<<str.rfind("ab",2)<<endl;
//返回ab在str[0]到str[2]中的位置,没有则返回一串乱码
s.find(str,pos);
find(str,pos);//是用来寻找从pos开始(包括pos处字符)匹配str的位置。
return 0;
}
输入1
sdefdwefdadabbababab
1
输出1
ab在str中的位置:11
ab在str[2]到str[n-1]中的位置:11
ab在str[0]到str[2]中的位置:18446744073709551615
Program ended with exit code: 0
输入2
abfeofihwabab
输出2
ab在str中的位置:0
ab在str[2]到str[n-1]中的位置:9
ab在str[0]到str[2]中的位置:0
Program ended with exit code: 0
输入3
asdfghjk
输出3
ab在str中的位置:18446744073709551615
ab在str[2]到str[n-1]中的位置:18446744073709551615
ab在str[0]到str[2]中的位置:18446744073709551615
Program ended with exit code: 0
#include
#include
using namespace std;
int main()
{
string str;
cin>>str;
cout<<"返回str[3]及其以后的子串:"<<str.substr(3)<<endl;
//若小于限制长度则报错
cout<<"从str[2]开始由四个字符组成的子串:"<<str.substr(2,4)<<endl;
//若小于限制长度则报错,4是**字符数**
return 0;
}
输入1
asdfghjkl;'/.,mnbvcxz
输出1
返回str[3]及其以后的子串:fghjkl;'/.,mnbvcxz
从ste[2]开始由四个字符组成的子串:dfgh
Program ended with exit code: 0
示列1
#include
#include
using namespace std;
int main()
{
string line = "this@ is@ a test string!";
line = line.replace(line.find("@"), 1, ""); //从第一个@位置替换第一个@为空
cout<<line<<endl;
return 0;
}
输出
this is@ a test string!
Program ended with exit code: 0
示列2
#include
#include
using namespace std;
int main()
{
string line = "this@ is@ a test string!";
line = line.replace(line.begin(), line.begin()+6, ""); //用str替换从begin位置开始的6个字符
cout << line << endl;
return 0;
}
示列3
#include
#include
using namespace std;
int main()
{
string line = "this@ is@ a test string!";
char* str = "12345";
line = line.replace(0, 5, str); //用str替换从指定位置0开始长度为5的字符串
cout << line << endl;
return 0;
}
输出
12345 is@ a test string!
Program ended with exit code: 0
#include
#include
using namespace std;
int main()
{
string str;
cin>>str;
cout<<"从2号位置插入字符串jkl并形成新的字符串返回:"<<str.insert(2, "jkl")<<endl;//会返回一个新的字符串,需要接收.
return 0;
}
输入
sdfgh
输出
从2号位置插入字符串jkl并形成新的字符串返回:sdjklfgh
Program ended with exit code: 0
#include
#include
using namespace std;
int main()
{
string str;
cin>>str;
cout<<"在字符串str后面添加字符串ABC:"<<str.append("ABC")<<endl;
return 0;
}
输入
diguwhdcow
1
输出
在字符串str后面添加字符串ABC:diguwhdcowABC
Program ended with exit code: 0
#include
#include
using namespace std;
int main()
{
string str1,str2;
cin>>str1>>str2;
cout<<"str1:"<<str1<<endl;
cout<<"str2:"<<str2<<endl;
swap(str1, str2);
cout<<"str1:"<<str1<<endl;
cout<<"str2:"<<str2<<endl;
}
输入
qwertyui
asdfghjk
输出
str1:qwertyui
str2:asdfghjk
str1:asdfghjk
str2:qwertyui
Program ended with exit code: 0
#include
#include
using namespace std;
int main()
{
string str1,str2;
cin>>str1>>str2;
cout<<str1.compare(str2)<<endl;
return 0;
}
输入
diwguc
aschsdnv
输出
3
Program ended with exit code: 0
#include
#include
using namespace std;
int main()
{
string str1;
cin>>str1;
cout<<str1.size()<<endl;
cout<<str1.length()<<endl;
return 0;
}
输入
dchiascnsc
输出
10
10
Program ended with exit code: 0
#include< string.h >
strcpy(s1,s2)
复制字符串s2到s1
strcat(s1,s2)
连接s2到s1的末尾
strlen(s1)
返回字符串s1的长度
strcmp(s1,s2)
若s1和s2是相同的,则返回0,s1< s2,返回值小于0,若s1>s2,返回值大于0
strchr(s1,ch)
返回一个指针,指向字符串s1中字符ch第一次出现的位置
strstr(s1,s2)
返回一个指针,指向字符串s1中字符串s2的第一次出现位置
memcpy (void *dest, const void *src, int size)
从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
strcpy与memcpy的区别
*对变量起另外一个名字(别名),这个名字就成为该变量的引用。
int a;
int &ref_a = a;
**ref_a并没有在内存中开辟单元,只是引用a的单元。
**地址相同,但有两个名字。
*引用在被定义时,必须要初始化
*引用只能被定义一次,不可改成其他变量的引用。(唯一)
*常数值对应的引用必须是常引用
const double &rPI = 3.14;
//具有读写权限,而不是副本/拷贝,只可读。
//实参是变量而不是地址
void swap(int &x, int &y){
}
*常量引用
const int &x;//防止通过引用修改数值。
****warning****
int& m4(int x){
int &y = x;
return y;
}
指针可以保存一个地址
数据类型 * 指针变量名
int * p;
让指针记录变量的地址
p = &a;
解引用
*p = 123213; //修改指向地址的数值
*区分指针的地址和指针所指向的地址
**已知int a,*pa=&a,输出指针pa 十进制的地址值的方法是cout<
空指针和野指针都不是我们申请的空间,不要轻易访问
*智能指针有助于避免内存泄漏
*智能指针借助于引用计数来确定其所指向的对象的回收时机
*智能指针借助于操作符重载实现与普通指针类似的功能,包括-> 及 * 操作符
const int * p = &a;
**特点:**指针的指向可以修改,但是指针指向的值不可以修改
int * const p = &a;
**特点:**指针的指向不可以改,指针指向的值可以改
const int * const p = &a;
**特点:**指针的指向不可以改,指针指向的值不可以改
int arr[105];
int * const p = arr;
*因为数组的首地址不会更改,所以指针应用const修饰
*不用const修饰,可以用来遍历数组。
**int * p = arr; // arr是数组的首地址
**p++; // 指针向后偏移四个字节
*数组运算符优先级高于引用和指针
*指针数组
**存放指针的数组
int *arr[5];
*数组指针
**指向数组的指针
int(*arr)[5];
point (*p)[3];point是类名,p为定义指向对象数组的指针。
point *p[3];point是类名,p为对象指针数组 。
*在说明语句int *f()中,标识符 f 代表是一个返回值为指针型的函数名。
*与 int (*f)() 不同
函数形参会发生改变,但是实参并没有发生改变
void max(int a){
}
max(a);
void max(int *p){
}
max(&a);
总结
*int *p
int *p表示的是一级指针,表示p所指向的地址里面存放的是一个int类型的值。
一级指针存放变量的地址,指向的值是变量的内容。如int* p={1,2,3}, p=数组的首地址,*p=数组的第一个值;
一级指针通过形参,可以修改实参中指针所指向的地址中的值。修改不了实参中指针所指向的地址。需要借助二级指针才可以。
*int **p
int **p表示的是二级指针,表示p所指向的地址里面存放的是一个指向int类型的指针。
二级指针存放一级指针的地址,指向一级指针。如int *p ={1,2,3}, int **pp=&p,pp=指针p的首地址,*pp=数组的首地址,**pp=数组第一个值1。
指针数组的数组名传递参数对应为指针的指针即二级指针,二维数组的数组名传递参数对应为数组指针即指向一维数组的指针
*int (*p)()
简单的理解,这就可以理解为调用函数,其中(*p)这个整体可以看作是函数名称,p代表函数的入口地址。很简单的理解吗,c语言中()就代表了函数,所以把 *p用括号括在一起变作 (*p)就代表了一个函数。
*int *p()
为了便于理解,可以把这个p换成一个函数的名字 ,比如fun,那么int *fun()代表的是调用这个函数后,这个函数的返回值是一个指针。
*int *p[n]
int *p[n] 就是一个指针数组,数据类型为int ,元素为地址(变量地址,数组地址,函数地址等),也就是说定义了n个不同指向int型的指针。在字符优先级表中,[]的优先级大于*,所以,int *p[n] 就等价于int *(p[n])。
*int (*p)[n]
同上,根据优先级,int (*p)[n]表示定义一个指针,指向一个int[n]型的指针。
sizeof()
struct Student
{
int num;
char name[20];
char sex;
}s1,s2;
Student s3,s4; //可在之后声明添加.
--------------------
struct
{
int num;
char name[20];
char sex;
}s1,s2;//不可以在之后声明添加.
--------------------
struct Student
{
int num;
char name[20];
char sex;
Date birthday;
}s1;
struct Date
{
int month;
int day;
int year;
};
//赋值时
s1.birthday.day = 25;
*注意
**结构体成员名与程序变量名不冲突,如s1.name与局部变量name不冲突。
**不能对结构体变量整体输入和输出,只能分别使用各个成员。
***wrong cin>>s1; cout<<s1;
struct Student
{
int num;
char name[20];
char sex;
};
Student s1 = {123,"lihua",'M'}; //初始化
Student s2 = s1;
*注意
**s2 = s1;
***java
两者指向同一块地址,同时修改。
***c++
将s1复制给s2,两者之后的更改互不影响。
struct Student
{
int num;
char name[20];
char sex;
}stu[3] = {
{123,"lihua",'M'},
{123,"lihua",'M'},
{123,"lihua",'M'}
};
*每个数组元素都是一个结构体的值,在内存中连续存放。
*指向运算符 ->
Student stu,*p;
p = &stu;
直接访问 | 间接访问 | 基于指向运算符的间接访问 |
---|---|---|
stu.name | p->name |
*结构体变量名作为参数,将实参值传递给形参,一般较少使用这种方法
**时间和空间开销大,但要传入基本数据类型时,可以采用。
**结构体拷贝,效率不高。
void print (Student s){
cout<name<
*typedef 已定义的类型 新的类型
typeof float real
real x,y;//等同于float x,y;
*作用:有利于程序的通用和移植。
//无论什么平台,real都表示最高精度小数。
#ifdef_win64
typedef long double real;
#else
typedef double real;
#endif
real r1,r2;
*typedef VS #define
**typedef float real:编译时处理,定义(复杂)数据类型。
**#define real float:预编译处理,所有real替换为float。
*复杂使用方法
typedef char STRING[81];
STRING s1;//char s1[81];
*应用
**图像,图形行业
double img1[1920][1080];
typedef double IMAGE[1920][1080];
IMAGE imag1;
const修饰的变量称为常量。
const修饰的成员数据称为常数据成员
const修饰的成员函数称为常函数
函数的执行不会改变对象成员变量。getXXX()
const声明的对象为常对象。
对象的数据成员的值不被改变
Time const t1(12,34,46); //t1是常对象
常对象必须进行初始化,不能被更新(修改)
C/C++中的实型常量必须符合一定的格式要求,包括小数点、指数符号等。如果不符合这些要求,就无法被编译器正确解析,因此是非法的实型常量。例如,以下几种实型常量都是非法的:
因此,编程时应该注意实型常量的格式要求,避免出现非法的常量。
Main
True
String
string
printf
While
main
都可以用来命名
++ ++x
自增两次++x++
会报错x++ ++
会报错(++x)++
自增两次int i = stoi(string);
to_string(int)
static_cast < type-id > ( expression ) 强制类型转换
(type-id)( expression )
double(a) + b / 2 //注意运算顺序
cpp
string strToBinary(string str) {
int num = stoi(str);//stoi将字符串转化为整数
string binary_str;//空字符串binary_str,用于存储最终的二进制结果
while (num > 0) {
int last_bit = num & 1;//num & 1 与运算得到num的最后一位
binary_str = to_string(last_bit) + binary_str;
num >>= 1;//将num右移一位
}
return binary_str;
}
int main() {
string binary = strToBinary("255");
cout << binary << endl; // 11111111
}
----------------------------------------------------------------
cpp
string hexToBinary(string hex) {
int num = stoi(hex, 0, 16);
int binary_len = 8; // 设置二进制字符串长度为8位
string binary;
while (num > 0 || binary.length() < binary_len) {
if (num > 0) {
int last_bit = num & 1;
binary = to_string(last_bit) + binary;
num >>= 1;
} else { // 若num已转化完,则给binary补零
binary = "0" + binary;
}
}
return binary;
}
int main() {
string binary = hexToBinary("FF");
cout << binary << endl; // 11111111
}
-----------------------------------------------------------------
cpp
cout << setfill('0') << setw(8) << hex << endl;
//另一种补零方式
//map
#include
#include
#include
#include
;;;//;;;//正确
{{{ }}}//正确
((()))//错误
for(;;);//正确
do;while(0)//错误
do while(0);//错误
do;while(0);//正确
int a = 1, *p = &a; cout << (a/*p);//错误
*类的成员函数可以在类体中提供实现;但通常声明和实现分离。
**a.h
class A{
float x,y;
public:
void Setxy(float a,float b);
void Print(void);
};
**a.cpp
*成员变量属于对象,每个对象都有独立的成员变量。成员函数属于类,所有对象共享同一个成员函数。
*区别
(*p).hour
*p.hour
*目的
让一个函数或者类访问另一个类中的私有成员
*关键字
friend
*注意
友元的关系是单向的而不是双向的,友元关系不能传递。
友元函数不一定是独立函数,也可以是另外一个类的函数。
外部函数f(),在类A中用friend修饰声明,则f()为类A的友元函数,f可以访问A的所有成员。
friend void f();
//代码演示
#include
#include
using namespace std;
class Point { //Point类声明
public: //外部接口
Point(int x=0, int y=0) : x(x), y(y) { }//初始化
int getX() const{ return x; }//const,getX不能修改数据成员(x或y)
int getY() const{ return y; }
friend float dist(
const Point &a, const Point &b);
private: //私有数据成员
int x, y;
};
double dist( const Point& a, const Point& b) {
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x * x + y * y);
}
int main() {
Point p1(1, 1), p2(4, 5);
cout <<"The distance is: ";
cout << dist(p1, p2)<
#include
#include
using namespace std;
// 房屋类
class Building
{
// 告诉编译器 laoWang全局函数是 Building类 的好朋友,可以访问Building对象的私有成员
friend void laoWang1(Building *building);
friend void laoWang2(Building &building);
friend void laoWang3(Building building);
public:
Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
string m_SittingRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
//全局函数
void laoWang1(Building *building)
{
cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_SittingRoom << endl;
cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_BedRoom << endl;
}
void laoWang2(Building &building)
{
cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_SittingRoom << endl;
cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_BedRoom << endl;
}
void laoWang3(Building building)
{
cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_SittingRoom << endl;
cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_BedRoom << endl;
}
void test()
{
Building building;
laoWang1(&building);
laoWang2(building);
laoWang3(building);
}
int main()
{
test();
}
隔壁老王 全局函数 正在访问:(地址传递) 客厅
隔壁老王 全局函数 正在访问:(地址传递) 卧室
隔壁老王 全局函数 正在访问:(引用传递) 客厅
隔壁老王 全局函数 正在访问:(引用传递) 卧室
隔壁老王 全局函数 正在访问:( 值传递 ) 客厅
隔壁老王 全局函数 正在访问:( 值传递 ) 卧室
#include
#include
using namespace std;
class Building;
class LaoWang
{
public:
LaoWang();
void visit1(); //让visit1()函数 可以 访问Building中的私有成员
void visit2(); //让visit2()函数 不可以 访问Building中的私有成员
Building *building;
private:
};
class Building
{
// 告诉编译器,LaoWang类下的visit1()函数是Building类的好朋友,可以访问Building的私有成员
friend void LaoWang::visit1();
public:
Building();
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};
LaoWang::LaoWang()
{
building = new Building;
}
void LaoWang::visit1()
{
cout << "隔壁老王LaoWang类中的visit1()函数正在访问:" << building->m_SittingRoom << endl;
cout << "隔壁老王LaoWang类中的visit1()函数正在访问:" << building->m_BedRoom << endl;
}
void LaoWang::visit2()
{
cout << "隔壁老王LaoWang类中的visit2()函数正在访问:" << building->m_SittingRoom << endl;
//cout << "隔壁老王LaoWang类中的visit2()函数正在访问:" << building->m_BedRoom << endl; //错误!私有属性不可访问
}
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
void test()
{
LaoWang lw;
lw.visit1();
lw.visit2();
}
int main()
{
test();
return 0;
}
隔壁老王LaoWang类中的visit1()函数正在访问:客厅
隔壁老王LaoWang类中的visit1()函数正在访问:卧室
隔壁老王LaoWang类中的visit2()函数正在访问:客厅
在类A中声明另一个类B声明为friend,则类A所有数据类B可以访问:friend class B;
#include
#include
using namespace std;
// 类作友元
class Building;
class LaoWang
{
public:
LaoWang();
void visit(); //参观函数 访问Building中的属性
Building * building;
private:
};
// 房屋类
class Building
{
// 告诉编译器,LaoWang类是Building类的好朋友,可以访问Building类的私有成员
friend class LaoWang;
public:
Building();
string m_SittingRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
// 类外定义成员函数
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
LaoWang::LaoWang()
{
// 创建建筑物对象
building = new Building;
}
void LaoWang::visit()
{
cout << "隔壁老王LaoWang类正在访问:" << building->m_SittingRoom << endl;
cout << "隔壁老王LaoWang类正在访问:" << building->m_BedRoom << endl;
}
void test()
{
LaoWang lw;
lw.visit();
}
int main()
{
test();
return 0;
}
隔壁老王LaoWang类正在访问:客厅
隔壁老王LaoWang类正在访问:卧室
class A{
float x,y;
public:
A(){ x = 0; y = 0;}
A(float a, float b = 10){
x = a;
y = b;
}
void Setxy(float a,float b);
void Print(void);
};
void main(){
//a4的定义方式相当于Java中A a = new a();
//a1后面不加()
A a1,a2(20.0),a3(3.0,7.0),*a4 = new A();
a1.Print();
a4->Print();
delete a4;//释放空间
}
*构造函数使用参数初始化表
//height,width是成员变量
Box::Box(int h,int w):height(h),width(w){}
//等同于
Box::Box(int h,int w){height = h; width = w;}
*委托构造函数:构造函数调用其他构造函数
Clock():Clock(0,0,0)//对应this(0,0,0)
*复制构造函数:被用于一个已存在对象初始化(赋值)另一个对象
A a1,a2 = a1;//等价于A a2(a1);
a2是a1的(数据)克隆。
**整体赋值通过复制构造函数,c++提供缺省的复制构造函数
**可以自己写复制构造函数。
class A{
float x,y;
public:
A(){ x = 0; y = 0;}
A(float a, float b = 10){
x = a;
y = b;
}
//复制构造函数
//const提供可读权限而不可以修改
//形参必须是同类型对象的引用
//浅拷贝
A(const A &a) {x = a.x; y = a.y;}
void Setxy(float a,float b);
void Print(void);
};
**浅拷贝
***缺省的复制函数,如果数据成员是指针,则复制函数拷贝指针,不拷贝指针指向的内存空间。
***使用new申请空间,通常需要自定义复制函数,实现深拷贝。
****原因:两个类,析构时,若是浅拷贝,new开辟的空间,会被释放两次,会造成运行错误。
**深拷贝
***将对象自身及关联的空间、对象都进行一边复制。
**被自动调用的三种情况
***定义一个对象时,以本类另一个对象作为初始值,发生复制构造;
//本质是构造,在创建对象时,会调用构造函数。
A a2 = a1;//与A a2; a2 = a1不一样,这是赋值,运算符的重载函数
***如果函数的形参是类的对象,调用函数时,将使用实参对象初始化形参对象,发生复制构造;
int func(const A &a)//高效,没有发生复制,起了别名,是引用。
int func(A a)//克隆,低效
***如果函数的返回值是类的对象,函数执行完成返回主调函数时,将使用return语句中的对象初始化一个临时无名对象,传递给主调函数,此时发生复制构造。
*析构函数在对象的生命期结束时,被系统自动调用,作用是收回为对象分配的储存空间。
*析构函数名必须是在类名前面加上字符"~"
ClassName::~ClassName(){...}
*析构函数不能带有任何参数,没有返回值,不指定函数类型。
*一个类只能定义一个析构函数,不允许重载。
*如果没有显式定义析构函数,则编译器自动产生一个缺省的析构函数,其函数体为空。
ClassName::~ClassName(){}
*不同对象的析构
**全局对象
**局部对象
**static定义的局部对象
**用new运算符动态生成的对象
*delete
**对于一个指针只能使用一次delete
**必须用于new返回的指针
**使用它删除对象时,要调用析构函数
class Point{
public:
Point(int x = 0,int y = 0):x(x),y(y){
count++;
}
Point (const Point &p){
x = p.x;
y = p.y;
count++;
}
~Point(){count--;}
int getX() const {return x;}//const:对于x只读,不会修改x的值。
int getY() const {return y;}
private:
int x,y;
static int count;//静态数据成员,初始值为0;
};
int Point::count = 0;//如果要对静态成员进行初始化,不能在类的内部。
*运算符重载:为运算符(+-*/><…)定义
一个(若干个)函数(运算符重载函数),遇到运算符根据不同的运算对象调用对应的函数
– <返回类型> operator <运算符>(<参数表>)
– operator是运算符重载函数关键字,
– operator <运算符>是函数名
*运算符的操作数映射为重载函数的参数
*运算符重载函数通常是类的成员函数或者是友元函数。函数参数通常是类的对象。
*(需要掌握的)重载的运算符
– 双目运算符 + - * / > < +=
– 单目运算符 ++ -- !
– 流运算符 >> <<
– 赋值运算符 =
– 类型转换函数
– (optional)其他运算符([]()等等,不常用)
• 转换构造函数,例如,int Integer
Class Vector{
Vector operator + (Vector &);
}
Vector v2, v3;
Vector v1 = v2 + v3;
v1 = v2.operator+(v3);
v1 = operator+(v3,v2);//友元函数
详见配套PPT-运算符重载
//复数的运算符重载
#include
using namespace std;
class Complex
{
public:
Complex(double r=0, double i=0):real(r), imag(i){ }
Complex operator+(Complex &c) const;//重载双目运算符'+'
void operator-=(Complex &c); //重载双目运算符'-='
//Complex operator-=(Complex &c);
friend Complex operator-(Complex &c1,Complex &c2) const;//重载双目运算符'-'
void Display() const;
private:
double real;
double imag;
};
void Complex::Display() const{
cout << "(" << real << ", " << imag << ")" << endl;
}
Complex operator-(Complex& c1, Complex& c2) const{//const能够使调用该函数的对象的值不改变(只读)不加Complex::和friend
return Complex(c1.real - c2.real, c1.imag - c2.imag);
}
Complex Complex::operator+(Complex &c) const{//类内的函数加Complex::
return Complex(c.real + real,c.imag + imag);
}
void Complex::operator-=(Complex &c){
this->real -= c.real;
this->imag -= c.imag;
}
//Complex Complex::operator-=(Complex &c){
// this->real -= c.real;
// this->imag -= c.imag;
// return *this;最后返回的也是this指针所指的对象
//}
int main()
{
double r, m;
cin >> r >> m;
Complex c1(r, m);
cin >> r >> m;
Complex c2(r, m);
Complex c3 = c1+c2;
c3.Display();
c3 = c1-c2;
c3.Display();
c3 -= c1;
c3.Display();
return 0;
}
//分数计算
#include
#include
using namespace std;
class FS {
public:
FS(double fz=0, double fm=0):fz(fz), fm(fm) { }
FS operator+(FS &f) const;//重载双目运算符'+'
void Display() const;
private:
int fz;
int fm;
};
int gcd(int m,int n) {
int m_sec = max(m,n);
int n_sec = min(m,n);
//cout< 0 && fz > 0) {
fm = abs(fm);
fz = abs(fz);
int temp = gcd(fm,fz);
//cout<>n;
for(int i = 0; i < n; i++) {
string s;
cin>>s;
int fz_one = 0;
int fm_one = 0;
//string -> int
init(s,fz_one,fm_one);
//cout<>s;
init(s,fz_two,fm_two);
FS fs_one(fz_one,fm_one);
FS fs_two(fz_two,fm_two);
FS fs_three = fs_one + fs_two;
}
return 0;
}
cin
是类istream
对象、cout
是类ostream
的对象。>>
和<<
是全局函数不能定义为类的方法//istream& operator >> (istream& _cin, Object& obj);
//ostream& operator << (ostream& _cout, const Object& obj);
class Complex{
public:
Complex(){
real = 0;
imag = 0;
}
Complex(double r =0,double i = 0): real(r),imag(i) {};
friend ostream& operator<<(ostream& output, Complex& c);//通常情况下Object类的数据成员是private,要想让>>和<<操作其数据成员,需要在类的内部声明为这两个重载是友元,因为要改变cin,cout的状态,返回值是引用
private:
double real;
double imag;
}
ostream& operator<<(ostream& output, Complex& c){
output<<"("<
执行初始化列表
调用基类的构造函数,初始化基类对象。
按照成员变量的定义顺序,依次初始化。(包括类内的基类对象)
调用自身构造函数的实现部分
//对象指针
class Person {
Person() { // 构造函数
cout << "Constructing Person" << endl;
}
};
int main() {
Person p; // 调用构造函数,输出"Constructing Person"
Person *ptr; // 只是声明指针,不调用构造函数
ptr = &p; // 让指针指向对象,不调用构造函数
Person *ptr2 = new Person; // 调用构造函数,输出"Constructing Person"
// 因为此处创建了一个新对象
}
与构造顺序相反。(无static和全局变量)
一些使用内联函数的注意事项:
inline int add(int a, int b) {
return a + b;
}
int main() {
int sum = add(1, 2); // 展开为 int sum = 1 + 2;
// 等价于 int sum = 3;
}
//这里,add() 函数被指定为 inline,所以在调用 add(1, 2) 时,会直接将函数体展开,相当于写成了1 + 2。这避免了进行正常的函数调用和返回等操作。
a % b = a - (a / b) * b
C++ 中的 % 运算符结果的正负号和被除数 a 的正负号相同。
优先级 | 操作符 | 描述 | 例子 | 结合性 |
---|---|---|---|---|
1 | () [] -> . :: ++ – | 调节优先级的括号操作符 数组下标访问操作符 通过指向对象的指针访问成员的操作符 通过对象本身访问成员的操作符 作用域操作符 后置自增操作符 后置自减操作符 | (a + b) / 4; array[4] = 2; ptr->age = 34; obj.age = 34; Class::age = 2; for( i = 0; i < 10; i++ ) … for( i = 10; i > 0; i-- ) … | 从左到右 |
2 | ! ~ ++ – - + * & (type) sizeof | 逻辑取反操作符 按位取反(按位取补) 前置自增操作符 前置自减操作符 一元取负操作符 一元取正操作符 解引用操作符 取地址操作符 类型转换操作符 返回对象占用的字节数操作符 | if( !done ) … flags = ~flags; for( i = 0; i < 10; ++i ) … for( i = 10; i > 0; --i ) … int i = -1; int i = +1; data = *ptr; address = &obj; int i = (int) floatNum; int size = sizeof(floatNum); | 从右到左 |
3 | ->* .* | 在指针上通过指向成员的指针访问成员的操作符 在对象上通过指向成员的指针访问成员的操作符 | ptr->*var = 24; obj.*var = 24; | 从左到右 |
4 | * / % | 乘法操作符 除法操作符 取余数操作符 | int i = 2 * 4; float f = 10 / 3; int rem = 4 % 3; | 从左到右 |
5 | + - | 加法操作符 减法操作符 | int i = 2 + 3; int i = 5 - 1; | 从左到右 |
6 | << >> | 按位左移操作符 按位右移操作符 | int flags = 33 << 1; int flags = 33 >> 1; | 从左到右 |
7 | < <= > >= | 小于比较操作符 小于或等于比较操作符 大于比较操作符 大于或等于比较操作符 | if( i < 42 ) … if( i <= 42 ) … if( i > 42 ) … if( i >= 42 ) … | 从左到右 |
8 | == != | 等于比较操作符 不等于比较操作符 | if( i == 42 ) … if( i != 42 ) … | 从左到右 |
9 | & | 按位与操作符 | flags = flags & 42; | 从左到右 |
10 | ^ | 按位异或操作符 | flags = flags ^ 42; | 从左到右 |
11 | | | 按位或操作符 | flags = flags | 42; | 从左到右 |
12 | && | 逻辑与操作符 | if( conditionA && conditionB ) … | 从左到右 |
13 | || | 逻辑或操作符 | if( conditionA || conditionB ) … | 从左到右 |
14 | ? : | 三元条件操作符 | int i = (a > b) ? a : b; | 从右到左 |
15 | = += -= *= /= %= &= ^= |= <<= >>= | 赋值操作符 复合赋值操作符(加法) 复合赋值操作符(减法) 复合赋值操作符(乘法) 复合赋值操作符(除法) 复合赋值操作符(取余) 复合赋值操作符(按位与) 复合赋值操作符(按位异或) 复合赋值操作符(按位或) 复合赋值操作符(按位左移) 复合赋值操作符(按位右移) | int a = b; a += 3; b -= 4; a *= 5; a /= 2; a %= 3; flags &= new_flags; flags ^= new_flags; flags |= new_flags; flags <<= 2; flags >>= 2; | 从右到左 |
16 | , | 逗号操作符 | for( i = 0, j = 0; i < 10; i++, j++ ) … | 从左到右 |
a | 97 |
---|---|
A | 65 |
int 2147483
assert
*作用是如果它的条件返回错误,则终止程序执行。
#include
void assert( int expression );
*每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败。
*assert的作用是先计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
memset(sum,0,sizeof(sum)); = int sum[10] = {0};
int arr[1005] = {0};
int arr[1005];//都可以
cstring和string的区别
Setw() 指定显示字段的宽度(对其后面的一个起作用,每次都要设置)。默认右对齐setiosflags(ios:left)设置为左对齐
Setfill(‘字符’ )设置用于在右对齐显示中填充空格的字符。
cout<
函数前加static,说明函数在整个cpp文件是可见的,但不可在其他cpp文件里调用。
\t
对应空格次数并不是固定的,并不是我们认为的4个空格或者8个空格
令 num = |n-8|%8, 其中n表示\t前面的字符占的位置(前面的字符也可能是转换说明,如%d,%10d等)。
error: control may reach end of non-void function [-Werror,-Wreturn-type]
*s.at(i)//s == ""
*数组越界
.
是结构体变量或类的对象访问其成员。
->
是结构体指针或类的指针访问其成员。
在 C++ 中,this 是一个指向当前对象的指针。this 指针是动态绑定的,它总是指向调用当前成员函数的那个对象。
//两者等价
ptr->name
(*ptr).name
输入
11010519491231002X
440524188001010019
输出
11010519491231002X: 1949-12-31 F
440524188001010019: invalid
#include
#include
#include
#include
using namespace std;
int weg[17] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
int last_num[11] = {1,0,10,9,8,7,6,5,4,3,2};
int month[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};//可改进
bool is_id_number(const string &s) {
if(s.length() != 18) return false;
for(int i = 0; i < s.length() - 1; i++) {
if(s.at(i) < '0' || s.at(i) > '9') {
return false;
}
}
int sum = 0;
for(int i = 0; i < s.length() - 1; i++) {
int num = (int)(s.at(i) - '0');
sum += weg[i] * num;
}
sum = sum % 11;
if(sum != 2) {
if(s.at(s.length() -1) < '0' || s.at(s.length() -1) > '9') {
return false;
}
if((int)(s.at(s.length() -1) - '0') == last_num[sum]) {
return true;
}
} else {
if((s.at(s.length() -1)) == 'X') {
return true;
}
}
return false;
}
bool judge_year(int year) {
if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) ) {
return true;
} else {
return false;
}
}
void cout_sex(int identity) {
if(identity % 2 == 0) {
cout<<" F"<= 1 && Day <= 29) {
cout << setfill('0') << setw(4) << Year <<"-"<< setfill('0') << setw(2) << Month <<"-"<< setfill('0') << setw(2) << Day;
cout_sex(identity);
continue;
} else {
cout<<"invalid"<= 1 && Day <= 28) {
cout << setfill('0') << setw(4) << Year <<"-"<< setfill('0') << setw(2) << Month <<"-"<< setfill('0') << setw(2) << Day;
cout_sex(identity);
continue;
} else {
cout<<"invalid"< 12 || Month == 0) {
cout<<"invalid"<= 1 && Day <= 31) {
cout << setfill('0') << setw(4) << Year <<"-"<< setfill('0') << setw(2) << Month <<"-"<< setfill('0') << setw(2) << Day;
cout_sex(identity);
continue;
} else {
cout<<"invalid"<= 1 && Day <= 30) {
cout << setfill('0') << setw(4) << Year <<"-"<< setfill('0') << setw(2) << Month <<"-"<< setfill('0') << setw(2) << Day;
cout_sex(identity);
continue;
} else {
cout<<"invalid"<
#include
using namespace std;
void SelectSort(int A[],int n)
{
for(int i = 0;i < n;i++){
int index =i;
for(int j = i+1;j < n;j++){ //查找最大元素所在位置与index索引比较即可
if (A[j] > A[index])
index =j;
}
int temp = A[index]; //交换无序后列中首元素与最大元素的位置
A[index] = A[i];
A[i] = temp;
}
}
*字符串
**注意""
*日期类
**月份不能为零
**天数与月份对应,可用数组储存。
*数学
**PI的取法Acos(-1)