C++大一基础知识

目录

一、程序控制

①输入输出

Ⅰ.cin&cout

Ⅱ.scanf&printf

②运算与符号

Ⅰ常用数学函数#include

Ⅱ.数据类型转换

③控制结构

④函数

Ⅰ.函数定义

Ⅱ函数使用

二、数据结构

①一维数组

排序与查找

②多维数组

③指针

Ⅰ字符,指针运算

Ⅱ字符串函数#include

Ⅲ指针参数与动态内存

④结构:struct

⑤链表

三、文件操作

Ⅰ基本文件输入输出

Ⅱ文件指针

四、类和对象

①类的创建和使用

②静态成员

③构造函数

④类的复合

⑤This指针

⑥友元

Ⅰ友元函数

Ⅱ友元类

五、运算符重载

①原理

②方式

Ⅰ成员函数重载

Ⅱ友元函数重载

③单目与双目运算符重载

Ⅰ单目(目表示操作数)

Ⅱ流插入和流提取运算符的重载

Ⅲ双目

Ⅳ类型转化

六、继承派生多态

①继承

Ⅰ成员函数的重定义

Ⅱ类指针

②多态

Ⅰ虚函数

Ⅱ抽象基类与纯虚函数

Ⅲ虚析构函数

③STL

Ⅰ动态学生信息管理https://www.educoder.net/tasks/p4imnbvy/887783/ok8rac4vzhbx?coursesId=p4imnbvy

Ⅱ还原键盘输入https://www.educoder.net/tasks/p4imnbvy/887783/yf2swgkio7ma?coursesId=p4imnbvy


一、程序控制

①输入输出

Ⅰ.cin&cout

流操作算子 #include<iomanip>

setbase(n),进制,n=8,10,16
setprecision(n),浮点数精度设置为n
setw(n),域宽n,小于n空位填充,大于n输出所有
setiosflags(long),long,流格式状态标志

#include <iostream>
#include<iomanip>
#include<string>
using namespace std;
int main()
{
	//setbase(n),进制,n=8,10,16
	int a = 1000;
	cout << "oct(八进制):"<<setbase(8) << a<<" "<<oct << a << endl;
	cout << "hex(十六进制):" << setbase(16) << a << " " << hex << a << endl;

	//setprecision(n),浮点数精度设置为n
	double b = log(2);
	cout << dec << b << " 保留两位小数:" << setprecision(2) << b << endl;

	//setw(n),域宽n,小于n空位填充,大于n输出所有
	cout << setw(5) << "域宽为5:" << "1234" << endl;
	cout << setw(5) << "域宽为5:" << "hello,world!" << endl;

	//setiosflags(long),long,流格式状态标志
	//ios::left/right/internal 左对齐,右对齐,符号左对齐数值右对齐
	//ios::showpos 显示正负号
	//ios::scientific 科学计数显示浮点数
    //ios::showpoint 显示小数点
	double c = 1010.234;
	cout << c << "科学技术显示浮点数并显示正负号:" << setiosflags(ios::showpos | ios::scientific) << c<<endl;

	return 0;
}

out:

oct(八进制):1750 1750
hex(十六进制):3e8 3e8
0.693147 保留两位小数:0.69
域宽为5:1234
域宽为5:hello,world!
1e+03科学技术显示浮点数并显示正负号:+1.01e+03

其他流输入输出

cin.get(char) 抽取下一个字符
cin.peek() 读取下一个字符
cin.putbact(char) 将字符写入输入流的开头
cin.ingnore(int, char) 忽略前面int个或char及其之前的字符
cin.getline(char*, int, char) 最多读取前面n个字符或读取到char截止

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
using namespace std;
int main()
{
	string line;

	//getline(cin,str)
	//cin.get(char) 抽取一个字符
	char gch;
	cin.get(gch);
	getline(cin, line);//getline抽取整行的输入流
	cout << "cin.get()抽取的字符是:" << gch<<endl;
	cout << "cin.get()抽取后的输入流为:" << line << endl<<endl;

	//cin.peek() 读取下一个字符
	char pch;
	pch=cin.peek();
	getline(cin, line);
	cout <<"cin.peek()预览的下一个字符是:"<<pch<<endl;
	cout << "cin.peek()预览后的输入流为:" <<line<< endl<<endl;

	//cin.putback(char) 将字符写入输入流的开头
	cin.putback('A');
	getline(cin, line);
	cout << "cin.putback('A')操作后的输入流:" << line << endl<<endl;

	//cin.ingnore(int,char) 忽略前面int个或char及其之前的字符
	cin.ignore(3, 'o');
	getline(cin, line);
	cout << "cin.ignore(3, 'o'): " <<line<< endl<<endl;
	cin.ignore(3, 'o');
	getline(cin, line);
	cout << "cin.ignore(3, 'o'): " <<line<< endl<<endl;

	//cin.getline(char*,int,char) 最多读取前面n个字符或读取到char截止,若输入流有剩余则继续操作
	char cs[5];
	cin.getline(cs, 5, 'l');
	cout << "cin.getline(cs, 5, 'l'): " << cs << endl<<endl;
	getline(cin, line);

	cin.getline(cs, 5, 'l');
	cout << "cin.getline(cs, 5, 'l'): " << cs<< endl<<endl;
	getline(cin, line);
	return 0;
}

out:

qwer
cin.get()抽取的字符是:q
cin.get()抽取后的输入流为:wer

qwer
cin.peek()预览的下一个字符是:q
cin.peek()预览后的输入流为:qwer

qwer
cin.putback('A')操作后的输入流:Aqwer

qwerty
cin.ignore(3, 'o'): rty

qoerty
cin.ignore(3, 'o'): erty

hello
cin.getline(cs, 5, 'l'): he

heeeee
cin.getline(cs, 5, 'l'): heee

Ⅱ.scanf&printf

格式化输入输出#include<stdio.h>

printf(<格式化控制>,<参数列表>)
scanf(<宽度>,<转换说明符>)

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>
using namespace std;
int main()
{
	//printf(<格式化控制>,<参数列表>)
	//<标志>:-左对齐,+显示符号,0用0填充域宽
	//<域宽>:小于域宽空白填充,大于按照实际输出
	//<精度>:整数:至少输出的数字个数,少的0补前面,字符串:输出最大长度
	//<转换说明符>:数据转换类型
	double num =-123.456;
	printf("%+015.5f\n", num);//0:缺项补0,15:域宽,5:精度

	//scanf(<宽度>,<转换说明符>)
	char c;
	int d;
	scanf("%3c%3d",&c,&d);
	cout << "c: " << c << endl<<"d: "<<d<<endl;
}

out:

-00000123.45600
qes132245
c: q
d: 132

②运算与符号

Ⅰ常用数学函数#include<math.h>

abs
ceil 向上取整
exp(x) e^x
floor 向下取整
pow(x,y) x^y
log 以e为底数
log10 以10为底数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>

using namespace std;
int main()
{
	cout <<"abs(-1)="<< abs(-1) << endl;
	cout << "ceil(0.5)="<<ceil(0.5) << endl;
	cout << "exp(0.1)="<<exp(0.1) << endl;
	cout << "floor(0.5)="<<floor(0.5) << endl;
	cout << "pow(2, 3)="<<pow(2, 3) << endl;
	cout << "log(10)="<<log(10) << endl;
	cout <<"log10(10)="<< log10(10) << endl;

	return 0;
}
out:

abs(-1) = 1
ceil(0.5) = 1
exp(0.1) = 1.10517
floor(0.5) = 0
pow(2, 3) = 8
log(10) = 2.30259
log10(10) = 1

Ⅱ.数据类型转换

隐式转换
显式转换
ASCII码与BOOL
运算符
三目运算符:<1> ? <2> : <3>

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>
using namespace std;
int main()
{
	//隐式转换
	int e = 3;
	double f = e + 3.12;

	//显式转换
	cout << "double(3/2)="<<double(3 / 2) << endl;//运算后再转换为double
	cout << "double(3.0/2)=" << double(3.0 / 2) << endl;
	cout << "(double)3/2=" << (double)3 / 2 << endl;//所有数据先转换为doble再运算

	//ASCII码与BOOL
	cout << "int('a')=" << int('a') << endl;
	cout << "int(true)=" << int(true) << endl;
	cout << "char(97)=" << char(97) << endl;
	cout<<"(char)(97+256)="<<(char)(97 + 256) << endl; //char占一个字节,256溢出不计

	//运算符
	//+,-,*,/,%
	//==,<=,>=,!=
	//&&,||,!
	//&,|,~,^,<<,>>:按位与,按位或,按位取反,按位异或,左右移位

	//三目运算符:<1>?<2>:<3>
	//if<1>则<2>;else <3>
	int a = 1, b = 2, c = 3;
	a > b ? a = b : a = c;
	cout << a;

	return 0;
}
out:

double(3/2)=1
double(3.0/2)=1.5
(double)3/2=1.5
int('a')=97
int(true)=1
char(97)=a
(char)(97+256)=a
3

③控制结构

两个数的值交换
三个数的排序
switch - case-break - defalut

方便跳出多重循环

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>
using namespace std;
int main()
{
	//两个数的值交换
	int e = 1, f = 2;
	int t = e;
	e = f;
	f = t;

	//三个数的排序
	int a = 1, b = 2, c = 3;
	int maxab = a > b ? a : b;
	int minab = a + b - maxab;
	int max = maxab > c ? maxab : c;
	int temp = (maxab + c) - max;
	int min = temp > minab ? minab : temp;
	cout << "max:" << max << "\n" << "mid:" << (a + b + c) - max - min << endl<<"min:"<<min<<endl;

	//switch-case-break-defalut
	int flag = 1;
	while (flag)
	{
		int command;
		cin >> command;
		switch (command)
		{
			case 1:
				cout << "1号任务" << endl;
				break;//不能缺少break语句
			case 2:
				cout << "2号任务" << endl;
				break;
			case 0:
				flag = 0;
				break;
			default:
				cout << "你干嘛" << endl;
		}
	}

    //goto 方便跳出多重循环
	for (int i = 1; i < 10; i++)
	{
		for (int j = 1; j < 10; j++)
		{
			for (int k = 1; k < 10; k++)
			{
				if (3*i + 4 * j + 5 * k == 100)
				{
					printf("i=%d,j=%d,k=%d是3*i+4*j+5*k=100的解\n", i, j, k);
					goto flag1;
				}
			}
		}
	}
	flag1:
		cout<<"flag1";
	return 0;
}
out:

max:3
mid:2
min:1
1
1号任务
4
你干嘛
0
i=8,j=9,k=8是3*i+4*j+5*k=100的解
flag1

④函数

Ⅰ.函数定义

函数头放前面,具体定义放后面,增强可读性

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>
using namespace std;

//<返回类型><函数名字>(<参数列表>){<语句>}
bool isprime(int n);//函数头放前面,具体定义放后面,增强可读性
void goldbach(int n);

int main()
{
	cout << "15~30的偶数哥德巴赫猜想验证\n";
	for (int i = 16; i <= 30; i+=2)
	{
		goldbach(i);
		cout << endl;
	}
	return 0;
}

// function library
bool isprime(int n) //判断是否为素数
{
	int c = 1;
	for (int i = 2; i <= n; i++)
	{
		if (n % i == 0)
		{
			c++;
		}
	}
	return c == 2 ? true : false;
}
void goldbach(int n)
{
	for (int i = 2; i < n / 2 + 1; i++)
	{
		if (isprime(i) && isprime(n - i))
		{
			printf("%d=%d+%d", n, i, n - i);
			break;
		}
	}
}
out:

15~30哥德巴赫猜想验证
16 = 3 + 13
18 = 5 + 13
20 = 3 + 17
22 = 3 + 19
24 = 5 + 19
26 = 3 + 23
28 = 5 + 23
30 = 7 + 23

Ⅱ函数使用

传值
传引用
函数重载,函数名字可相同,但传参类型个数或顺序不同
作用域:块作用域,{}, 全局作用
存储类别:auto, static.(auto现在已经被淘汰了, 函数内直接定义即可)

递归函数:汉诺塔问题

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>
using namespace std;

int a = 1;
double max(double x, double y);
void swap(double& x, double& y);
int max(int x, int y);
void storeauto(int &x, int &y);
void storesta(int& x, int& y);
void hannuo(int n, char s, char m, char t);//n:规模,s:源柱,m:辅柱,t:目标柱

int main()
{
	//传值
	double x = 1.1, y = 2.2;

	//传引用
	printf("x=%.1f,y=%.1f\t", x, y); 
	swap(x, y);//这里不用写(&x,&y)
	printf("after swapping \tx=%.1f,y=%.1f\n", x, y);
	
	//函数重载,函数名字可相同,但传参类型个数或顺序不同
	int r = 1, s = 2;
	cout << max(r, s)<<endl;

	//作用域:块作用域,{},全局作用
	{int a=1; cout <<"块1:a="<< a << endl; };
	{int a = 2; cout <<"块2:a="<< a << endl; };
	cout << "全局:a=" << a << endl;

	//存储类别:auto,static.(auto现在已经被淘汰了,函数内直接定义即可)
	int q = 2, w = 4;
	printf("q=%d,w=%d\n", q, w);
	for (int i = 1; i <= 2;i++)
	{
		storeauto(q, w);
		printf("storeauto(q,w)调用%d次后,q=%d,w=%d\n", i, q, w);
	}
	cout << endl;
	printf("q=%d,w=%d\n", q, w);
	for (int i = 1; i <= 2; i++)
	{
		storesta(q, w);
		printf("storesta(q,w)调用%d次后,q=%d,w=%d\n", i, q, w);
	}

	//汉诺塔问题
	hannuo(3, 'A', 'C', 'B');

	return 0;
}

// function library
double max(double x, double y)
{
	return x < y ? y : x;
}
void swap(double& x, double& y)
{
	double temp=x;
	x = y;
	y = temp;
}
int max(int x, int y)
{
	return x < y ? y : x;
}
void storeauto(int &x, int &y)
{
	int j=1;//auto int j=0;
	x += j;
	y += j;
	j++;
}
void storesta(int& x, int& y)
{
	static int j =1;//auto int j=0;
	x += j;
	y += j;
	j++;
}
void hannuo(int n, char s, char m, char t)
{
	if (n == 1)
	{
		cout << s <<"->" << t << endl;
	}
	else
	{
		hannuo(n - 1, s, t, m);//n-1个盘子移到辅柱
		cout << s << "->" << t << endl;//最后一个移到目标柱
		hannuo(n - 1, m, s, t);//辅柱变为源柱
	}
}
out:

x=1.1,y=2.2     after swapping  x=2.2,y=1.1
2
块1:a=1
块2:a=2
全局:a=1
q=2,w=4
storeauto(q,w)调用1次后,q=3,w=5
storeauto(q,w)调用2次后,q=4,w=6

q=4,w=6
storesta(q,w)调用1次后,q=5,w=7
storesta(q,w)调用2次后,q=7,w=9
A->B
A->C
B->C
A->B
C->A
C->B
A->B

二、数据结构

①一维数组

排序与查找

一维数组 a[n], n是数据个数
排序 交换(每次找到都交换),选择(先找最值再交换),快排
内置函数#include<algorithm>
查找:二分查找

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;

void quick_sort(int a[], int start, int end);//快排自定义
int binary_search(vector<int>& nums, int target);

int main()
{
	//一维数组 a[n],n是数据个数
	int d[4]; //大小是常量值
	int b[] = { 1,2,3,4 };//根据数目确定大小
	float c[5] = { 1.2 };//缺省值0
	
	//排序 交换(每次找到都交换),选择(先找最值再交换),快排
	//交换排序
	int a[10] = { 1,2,3,5,6,8,10,9,7,4 };
	for (int i = 0; i < 10 - 1; i++)
	{
		for (int j = i+1; j < 10; j++)
		{
			if (a[i] > a[j]) 
			{
				int temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}
	cout << "交换排序结果:";
	for (int i = 0; i < 10; i++) 
	{
		cout << a[i] << " ";
	}
	cout << endl;
	//选择排序
	for (int i = 0; i < 10 - 1; i++)
	{
		int min = i;
		for (int j = i + 1; j < 10; j++)
		{
			if (a[j] < a[i])
			{
				min = j;
			}
		}
		if (i != min)
		{
			int temp = a[i];
			a[i] = a[min];
			a[min] = a[i];
		}
	}
	cout << "选择排序结果:";
	for (int i = 0; i < 10; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	//快排
	quick_sort(a, 0, 10- 1);
	cout << "快排结果:";
	for (int i = 0; i < 10; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	//内置函数#include<algorithm>
	sort(a, a + 10, greater<int>());//左闭右开,greater,降序,int 类型,默认为升序

	//查找:二分查找
	vector<int> nums = { 1, 3, 5, 7, 9, 11, 13, 15, 17 };
	int target = 11;

	int index = binary_search(nums, target);
	if (index == -1) {
		cout << "Target not found" << endl;
	}
	else {
		cout << "Target found at index " << index << endl;
	}

	return 0;
}

// function library
void quick_sort(int a[], int start, int end)
{
	if (start >= end) {
		return;
	}

	int pivot = a[start];
	int left = start + 1, right = end;

	while (left <= right) {
		if (a[left] < pivot && a[right] > pivot) {
			swap(a[left], a[right]);
			left++;
			right--;
		}
		if (a[left] >= pivot) {
			left++;
		}
		if (a[right] <= pivot) {
			right--;
		}
	}

	swap(a[start], a[right]);
	quick_sort(a, start, right - 1);
	quick_sort(a, right + 1, end);
}
int binary_search(vector<int>& nums, int target) 
{
	int left = 0, right = nums.size() - 1;

	while (left <= right) {
		int mid = left + (right - left) / 2;
		if (nums[mid] == target) {
			return mid;
		}
		else if (nums[mid] < target) {
			left = mid + 1;
		}
		else {
			right = mid - 1;
		}
	}

	return -1;
}
out:

交换排序结果:1 2 3 4 5 6 7 8 9 10
选择排序结果:1 2 3 4 5 6 7 8 9 10
快排结果:10 9 8 7 6 5 4 3 2 1
Target found at index 5

②多维数组

初始化 a[m][n], m行n列,按行连续储存
作为函数参数, 指定数组的每一维的大小

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;

int sum(int arr[][3], int rows, int cols);

int main()
{
	//多维数组 初始化 a[m][n],m行n列,按行连续储存
	int a[2][2] = { {2},{2,3} };//缺省值为0
	int b[2][2] = { 1,2,3};//按行读入
	int c[][2] = { {1,2},{1} };//只能省略第一维

	//多维数组 作为函数参数
	//由于多维数组的内存布局是连续的,因此在将多维数组作为形参传递时,必须指定数组的每一维的大小
	int arr[2][3] = { {1, 2, 3}, {4, 5, 6} };
	int s = sum(arr, 2, 3);
	cout << "The sum of the array is: " << s << endl;

	return 0;
}

// function library
int sum(int arr[][3], int rows, int cols)
{
	int s = 0;
	for (int i = 0; i < rows; ++i) {
		for (int j = 0; j < cols; ++j) {
			s += arr[i][j];
		}
	}
	return s;
}
out:

The sum of the array is : 21

③指针

Ⅰ字符,指针运算

加密问题
二维字符数组
指针运算:& 地址运算* 复引用 + -算术运算 前移后移,计算距离,关系运算,赋值
指针操作数组
指针数组:数组存放指针

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;

int main()
{
	//加密问题
	char a[10];
	cin >> a;
	int l = 0;
	while (a[l] != '\0')
	{
		a[l] = a[l] + 'A' - 'a'+3;
		l++;
	}
	cout << "输入字符串长度为:" << l << "\t加密后为:" << a << endl;

	//二维字符数组
	char s[2][10];
	cin >> s[0] >> s[1];
	cout << s[0] << endl << s[1] << endl;

	//指针运算:&地址运算 *复引用 +-算术运算 前移后移,计算距离,关系运算,赋值
	//& 地址运算
	int* yptr;
	int y = 5;
	yptr = &y;//得到指向y的指针
	//*复引用
	int* p1, * p2;//同时定义两个指针都要打*
	int y1 = 2, y2 = 3;
	p1 = &y1;
	p2 = &y2;
	*p1 += 1;
	printf("y1=%d,y2=%d\n*p1=%d,*p2=%d\n", y1, y2, *p1, *p2);
	//+-算术运算 前移后移,计算距离
	cout << "p1-p2=" << p1 - p2 << endl;
	//关系运算
	cout << "p1<p2?" << bool(p1 < p2) << endl;
	//赋值,不同类型需要类型转换
	float f = 0.1;
	int* d = (int*)&f;
	cout << "int* d = (int*)&f,*d=" << *d << endl;//d的输出并不是0,涉及到浮点数的存储方式和类型转换

	//指针操作数组
	int arr1[5] = { 1, 2, 3, 4, 5 };
	int* pa = arr1;
	for (int i = 0; i < 5; ++i) {
		cout << *pa << " ";
		pa++;
	}

	cout << endl;

	//指针数组:数组存放指针
	const char *gender[3][10] = {"man","women","other"};
	cout << "*gender[0]="<< * gender[0] << endl;
	return 0;
}

// function library
out:
helloworld
输入字符串长度为:10    加密后为:KHOORZRUOG
hello world
hello
world
y1 = 3, y2 = 3
* p1 = 3, *p2 = 3
p1 - p2 = -8
p1 < p2 ? 1
	int* d = (int*)&f, *d = 1036831949
	1 2 3 4 5
	* gender[0] = man

Ⅱ字符串函数#include<string.h>

int strlen(const char*) 计算字符串长度
char* strcpy(char* dest, const char* src) 将src指向的空间复制到dest
char* strcat(char* dest, const char* src) 将src指向的空间连接到dest之后
int strcmp(const char* s1, const char* s2)    逐一比较字典序,s1 < s2返回1
char* strchr(const char* s, int c) 在s中查找第一个对应ASCII码为c的字符并返回位置,否则返回NULL
综合应用 : countstring(const chat* s1, const char* s2),查找子串s2在s1中的出现次数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;

int countstring(const char* s1, const char* s2);

int main()
{
	//int strlen(const char*) 计算字符串长度
	const char* c1 = "hello world";
	char c2[] = "hello world"; //两种初始化方式
	cout << "strlen(c1)=" << strlen(c1) << "\tstrlen(c2)=" << strlen(c2) << endl;

	//char* strcpy(char* dest,const char* src) 将src指向的空间复制到dest
	char a[20]="hello", b[20] = "world";
	strcpy(a, b);//a原来有的内容不会保留
	cout << "strcpy(a, b),a=" << a << endl;

	//char* strcat(char* dest,const char* src) 将src指向的空间连接到dest之后
	strcat(a, b);//拼接在一起
	cout << "strcat(a, b),a=" << a << endl;

	//int strcmp(const char* s1,const char* s2)	逐一比较字典序,s1<s2返回1
	char s1[] = "abc", s2[] = "abb";//按照字典,谁在前面谁大
	cout << "strcmp(s1,s2)=" << strcmp(s1, s2) << endl;

	//char* strchr(const char* s,int c) 在s中查找第一个对应ASCII码为c的字符并返回位置,否则返回NULL
	cout << "strchr(s1,'b')返回:" << strchr(s1, 'b') << endl;
	if (strchr(s1, 'd') == NULL)
	{
		cout << "strchr(s1, 'd') == NULL" << endl;
	}

	//char* strstr(const char* s1,const char* s2) 在s1中查找s2出现的首位置并返回,否则返回NULL
	char s3[] = "abcdefabcdef", s4[] = "cd";
	cout << "strstr(s3, s4):" << strstr(s3, s4) << endl;

	//综合应用:countstring(const chat* s1,const char* s2),查找子串s2在s1中的出现次数
	char s5[] = "abcdefhabcewfhabcmkknabc", s6[] = "abc";
	printf("\"%s\"在\"%s\"中出现的次数为:%d\n", s6, s5, countstring(s5, s6));

	return 0;
}

// function library
int countstring(const char* s1, const char* s2)
{
	int count = 0, l = strlen(s2);
	const char* p = s1;
	while ((p = strstr(p, s2)) != NULL) {
		count++;
		p += l;
	}
	return count;
}
out:

strlen(c1) = 11   strlen(c2) = 11
strcpy(a, b), a = world
strcat(a, b), a = worldworld
strcmp(s1, s2) = 1
strchr(s1, 'b')返回:bc
strchr(s1, 'd') == NULL
strstr(s3, s4):cdefabcdef
"abc"在"abcdefhabcewfhabcmkknabc"中出现的次数为:4

Ⅲ指针参数与动态内存

const与指针
动态分布:new& delete, malloc& free

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;

int main()
{
	//const与指针
	const int* p1; // 指向常量的非常量指针
	int a = 1;
	p1 = &a; // OK,p1指向a,但不能通过p1修改a的值
	int b = 2;
	p1 = &b; // OK,p1指向b,但不能通过p1修改b的值
	int* const p2 = &a; // 指向非常量的常量指针
	*p2 = 3; // OK,可以通过p2修改a的值
	int c = 4;
	// p2 = &c; // ERROR,p2是常量指针,不能改变指向的对象
	const int* const p3 = &b; // 指向常量的常量指针
	// *p3 = 5; // ERROR,不能通过p3修改b的值
	int d = 6;
	// p3 = &d; // ERROR,p3是常量指针,不能改变指向的对象
	
	//动态分布:new&delete,malloc&free
	int x; //数组的长度
	cin >> x;//运行时才能确定x的值
	float* scores = new float[x];
	cout <<"分配的内存空间长度:"<< sizeof(float) * x << endl;
	delete[]scores;//及时释放,防止内存泄露,建议每次new就直接写delete

	int* s = (int*)malloc(sizeof(int) * 4);
	for (int i = 0; i < 4; i++)
	{
		cin >> s[i];
	}
	for (int i = 0; i < 4; i++)
	{
		cout << s[i] << " ";
	}
	free(s);

	return 0;
}

// function library
out:

5
分配的内存空间长度:20
1
2
3
4
1 2 3 4

④结构:struct

定义与声明
初始化
结构与函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;

//定义与声明
struct birthday
{
	int year;
	int month;
	int day;
};
struct lifting
{
	char name[20];
	float weight;
	birthday date;//可以包含其他strcut
	lifting* a;//可以是指向本结构类型的指针
}lift1,lift2;//声明两个变量
void print(lifting* l);

int main()
{
	//初始化
	lift1 = { "张三",57,{2005,1,13},&lift2 };//lift1.a指向lift2
	lifting* p1 = &lift1;
	//p1->name = "张三";这里不能直接修改
	strcpy(p1->name, "李四"); // 使用strcpy函数修改name的值
	cout << lift1.name;
	cout << "生日为:" << lift1.date.year<<" "<< lift1.date.month<<" "<< lift1.date.day<<endl;
	
	//结构与函数:结构变量的成员是普通变量,可作为函数的参数或返回值
	print(p1);

	return 0;
}

// function library
void print(lifting* l)
{
	cout << "姓名:"<<l->name << endl <<"体重:"<< l->weight<<endl;
}
out:

李四生日为:2005 1 13
姓名:李四
体重:57

⑤链表

node* insertTail(node* h, node* t) //尾部插入
node* insertHead(node* h, node* t)//头部插入
node* insertSort(node* h, node* t) //从小到大插入
node* search(node* h, int num) //查找指定节点
node* delAt(node* h, int i)//删除指定位置节点
node* delHas(node* h, int n) //删除含有指定元素的节点
int listLength(node* h)//计算链表长度

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<iomanip>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;

struct node 
{
	int data;
	node* next;
};
node* insertTail(node* h, node* t) //尾部插入
{
    if (h == nullptr) 
    {
        return t;// 如果当前链表为空,直接将待插入结点作为链表头并返回
    }
    node* p = h;
    while (p->next != nullptr) {
        p = p->next; // 找到链表的最后一个结点
    }
    p->next = t;// 将链表的最后一个结点的next指针指向待插入结点
    return h;
}
node* insertHead(node* h, node* t)//头部插入
{
    if (h == nullptr)
    {
        return t;
    }
    t->next = h;
    return t;
}
node* insertSort(node* h, node* t) //从小到大插入
{
    if (h == NULL) 
    { 
        t->next = NULL;// 空链表,直接将结点t插入
        return t;
    }
    if (t->data <= h->data) 
    { 
        t->next = h;// 将结点t插入链表头
        return t;
    }
    node* p = h;
    while (p->next != NULL && p->next->data < t->data) {
        p = p->next;
    }
    t->next = p->next;
    p->next = t;
    return h;
}
node* search(node* h, int num) //查找指定节点
{
    if (h == NULL)// 空链表
    { 
        return NULL;
    }
    node* p = h;
    while (p != NULL) {
        if (p->data == num) {
            return p;
        }
        p = p->next;
    }
    return NULL; // 循环结束,未找到该结点
}
node* delAt(node* h, int i)//删除指定位置节点
{
    int num = 0;
    node* p = h;
    while (p->next != nullptr)
    {
        num++;
        p = p->next;
    }
    if (i == 0)
    {
        return h->next;
    }
    else if (i > num)
    {
        return h;
    }
    else
    {
        node* t = h;
        node* m = h;
        for (int j = 0; j < i; j++)
        {
            t = m;
            m = t->next;
        }
        t->next = m->next;
        return h;
    }
}
node* delHas(node* h, int n) //删除含有指定元素的节点
{
    if (h == NULL)  // 空链表
    {
        return h;
    }
    if (h->data == n) 
    { 
        node* p = h;
        h = h->next;// 删除头结点
        free(p);//释放原来头节点的内存
        return h;
    }
    node* p = h;
    while (p->next != NULL && p->next->data != n) 
    { 
        p = p->next;// 找到要删除结点的前驱结点
    }
    if (p->next == NULL) 
    { 
        return h;// 要删除的结点不存在
    }
    node* q = p->next; // 被删除结点
    p->next = q->next; // 将被删除结点从链表中删除
    free(q);//释放内存

    return h;
}
int listLength(node* h)//计算链表长度
{
    int c = 0;
    while (h != nullptr)
    {
        c++;
        h = h->next;
    }
    return c;
}

三、文件操作

Ⅰ基本文件输入输出

打开文件 ios::in打开供读取,out打开供写入, app打开写入末尾
输入输出
example:文本操作与二进制操作

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<fstream>
using namespace std;

struct person
{
	char name[16];
	int number;
}me={"zhangsan",20220001},t,r;
int main()
{
	/*
	//打开文件 ios:: in打开供读取,out打开供写入,app打开写入末尾
	ofstream ofs;
	ofs.open("f1.txt", ios::out);
	//或者:ofstream ofs("f1.txt",ios::out)
	//关闭
	ofs.close();

	//输入输出
	ifstream ifs("f1.txt", ios::in);
	int n;
	ifs >> n;
	ifs.close();
	ofstream ofs("f1.txt", ios::out);
	int n = 123;
	ofs << n; ofs.close();

	//块输入输出 ifstram&read,ofstream&write
	ifstream ifs("f1.txt", ios::in);
	int n;
	ifs.read((char*)&n, sizeof(int));
	ifs.close();
	ofstream ofs("f1.txt", ios::out);
	int n = 123;
	ofs.write((char*)&n, sizeof(n)); ofs.close();
	*/

	//example
	//文本操作
	ofstream f("a.txt", ios::out);
	f << me.name << " " << me.number << endl;
	f.close();
	ifstream f1("a.txt", ios::in);
	f1 >> t.name >> t.number;
	f1.close();
	cout << t.name << " " << t.number << endl;
	//二进制操作
	ofstream g("b.txt", ios::out|ios::binary);
	g.write((char*)&me, sizeof(me));
	g.close();
	ifstream g1("b.txt", ios::in |ios::binary);
	g1.read((char*)&r, sizeof(r));
	g1.close();
	cout << r.name << " " << r.number << endl;



	return 0;
}

// function library
out:
zhangsan 20220001
zhangsan 20220001

Ⅱ文件指针

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<fstream>
using namespace std;

struct date
{
	int year, month, day;
};

int main()
{
	//seekg(streamoff off,ios::seek_dir dir) 读文件时修改FP
	//seekp(streamoff off,ios::seek_dir dir) 写文件时修改FP
	//off:偏移量,单位字节 dir:位置常量,ios:: beg起始,cur当前,end结尾

	//example
	int i,n;
	cin >> n;
	date* t=new date[n]; //动态分配内存
	for (i = 0; i <n; i++)
	{
		t[i].year = 1900 + i;
		t[i].month = i % 12 + 1;
		t[i].day = 1;
	}
	ofstream fout("a.dat", ios::out | ios::binary);
	fout.write((char*)t, sizeof(date)*n);//这里t是指针,要写整个数组的大小
	fout.close();
	date t20, t50;
	ifstream fin("a.dat", ios::in | ios::binary);
	fin.seekg((sizeof(date) * 19, ios::beg));//指针便宜量
	fin.read((char*)&t20, sizeof(date));
	fin.seekg(sizeof(date) * 29, ios::cur);
	fin.read((char*)&t50, sizeof(date));
	fin.close();
	cout << t20.year << "-" << t20.month << "-" << t20.day << endl;
	cout << t50.year << "-" << t50.month << "-" << t50.day << endl;

	return 0;
}

// function library
out:
51
1900 - 1 - 1
1930 - 7 - 1

四、类和对象

①类的创建和使用

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

//类和对象
class complex
{
public:
    complex(double r = 0, double i = 0)
    {
        real = r;
        imag = i;
    }
    ~complex() {};//析构函数,撤销对象时自动调用
    complex mul(complex x)
    {
        double r = real * x.real - imag * x.imag;
        double i = real * x.imag + imag * x.real;
        return complex(r, i);
    }
    complex add(complex x)
    {
        return complex(real + x.real, imag + x.imag);
    }

    void output()
    {
        if (imag >= 0)
        {
            cout << "(" << real << "+" << imag << "i)" << endl;
        }
        else
        {
            cout << "(" << real << imag << "i)" << endl;
        }
    }
private:
    double real, imag;
};

int main()
{
    complex a(1.2, 2.3), b(5, -6.7), c, d;
    c = a.add(b); d = a.mul(b);
    c.output();
    d.output();
    return 0;
}
out:
(6.2 - 4.4i)
(21.41 + 3.46i)

②静态成员

静态成员的声明:static
访问静态成员:对象名 / 对象引用 + 点操作符号,classname + ::,类指针 + 箭头
作用域与析构函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

//静态成员的声明:static
class book
{
public:
    book(const char* bookname);
    ~book();//析构函数
    static int getbooknum();//静态成员函数只能访问静态成员
private:
    char name[50];//书名
    static int booknum;//静态数据,不依赖对象而存在
};

//访问静态成员:对象名/对象引用+点操作符号,classname+::,类指针+箭头
book::book(const char* bookname)
{
    strcpy(this->name, bookname);//类指针+箭头
    booknum++;//对象产生,booknum增加
}
book::~book()
{
    booknum--;//对象撤销时,booknum减少
}
int book::booknum = 0;//初始化类的静态成员
int book::getbooknum()
{
    return booknum;
}
int main()
{
    cout << "Thers is " << book::getbooknum() << " book." << endl;
    {//块1
        book one("C++程序设计");//创建一个对象
        cout << "After book one created,there is " << one.getbooknum() << " book." << endl;//对象名+.
        {//块2
            book two("Python程序设计");
            cout << "After book two created,there are " << two.getbooknum() << " books." << endl;
        }//块2结束,自动撤销two(作用域)
        cout << "After book two destroyed,there is " << one.getbooknum() << " book." << endl;
    }//块1结束,自动撤销one
    cout << "After book one destroyed,there is " << book::getbooknum() << " book." << endl;
    return 0;
}

out:

Thers is 0 book.
After book one created,there is 1 book.
After book two created,there are 2 books.
After book two destroyed,there is 1 book.
After book one destroyed,there is 0 book.

③构造函数

带默认参数的构造函数
复制构造函数(创建信息相同的对象)

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

class circle
{
public:
    //带默认参数的构造函数
    circle(double a = 5.0, double b = 5.0, double c = 5.0)//每个参数的类型都要写清楚
    {
        x = a;
        y = b;
        c > 0 ? r = c : r = 5.0;//三目运算符
    }
    //复制构造函数(创建信息相同的对象)
    circle(circle& c)
    {
        x = c.x; y = c.y; r = c.r;
    }
    ~circle() {};
    void print(circle &c);
private:
    double x, y, r;
};
void circle::print(circle& c)
{
    cout << "x=" << c.x << "\ty=" << c.y << "\tr=" << c.r<<endl;
}
int main()
{
    {
        circle a;//参数被设定为默认参数
        circle b(1.0);//只传第一个参数
        circle c(4.0, 5.0, 6.0);
        circle d(c);
        cout << "a:"; a.print(a);
        cout << "b:"; b.print(b);
        cout << "c:"; c.print(c);
        cout << "d:"; b.print(d);
    }
    return 0;
}
out:
a:x = 5   y = 5     r = 5
b : x = 1   y = 5     r = 5
c : x = 4   y = 5     r = 6
d : x = 4   y = 5     r = 6

④类的复合

成员对象在包含它的对象之前被建立
成员函数的构造函数被大对象的构造函数调用
大对象的成员函数对成员对象来说依然是外部函数,需要遵循访问规则,注意调用格式

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
#define pi 3.14
class circle
{
public:
    //带默认参数的构造函数
    circle(double a = 5.0, double b = 5.0, double c = 5.0);//每个参数的类型都要写清楚
    ~circle();
    double area();
    void print();
private:
    double x, y, r;
};
//function library
circle::circle(double a, double b, double c)
{
    x = a;
    y = b;
    c > 0 ? r = c : r = 5.0;
    cout << "circle object start:x=" << x << "\ty=" << y << "\tr=" << r << endl;
}
circle::~circle()
{
    cout << "circle object end:x=" << x << "\ty=" << y << "\tr=" << r << endl;
}
double circle::area()
{
    return pi * r * r;
}
void circle::print()
{
    cout << "x=" << x << "\ty=" << y << "\tr=" << r;
}
//创建column类
class column
{
public:
    column(double h = 5.0, double a = 5.0, double b = 5.0, double c = 5.0);
    ~column();
    double volume();
private:
    circle circle;//数据成员
    double height;
};
column::column(double h, double a, double b, double c)
    :circle(a, b, c)//为数据成员circle调用其构造函数,初始化列表
{
    h > 0 ? height = h : height = 5.0;
    cout << "coulumn object start : height = " << height << ",";
    circle.print();
    cout << endl;
}
double column::volume()
{
    return height * circle.area();
}
column::~column()
{
    cout << "column object end:height=" << height << ",";
    circle.print();
    cout << endl;
}
int main()
{
    column obj(2.3, 3.4, 4.5, 5.6);
    cout << "The volume of obj is" << obj.volume() << endl;
    return 0;
}
out:

circle object start : x = 3.4       y = 4.5   r = 5.6
coulumn object start : height = 2.3, x = 3.4       y = 4.5   r = 5.6
The volume of obj is226.482
column object end : height = 2.3, x = 3.4      y = 4.5   r = 5.6
circle object end : x = 3.4 y = 4.5   r = 5.6

⑤This指针

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
/*
class test
{
public:
    test(int n = 0)
    {
        data = n;//直接访问
    }
    void print()
    {
        cout << "data=" << this->data << endl;//使用this指针访问
    }
private:
    int data;
};
*/
//静态成员函数没有维护this,访问非静态数据成员需要this
class test
{
public:
    test(int n = 0) { data = n; }
    test& setdata(int n)//返回值类型
    {
        data = n;
        return *this;
    }
    void print()
    {
        cout << "data=" << data << "!" << endl;
    }
private:
    int data;
};
int main()
{
    test obj;
    cout << "obj: ";
    obj.setdata(100).print();//函数连续调用,因为setdata返回的是test&类型
    return 0;
}
out:

obj: data=100!

⑥友元

Ⅰ友元函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
//友元函数具有访问类的所有成员的权限,friend+函数原型
class triangle
{
    friend void seta(triangle& t, int n);//声明友元函数
public:
    triangle(int x = 5, int y = 5, int z = 5);
    void print();
private:
    int a, b, c;
};
triangle::triangle(int x, int y, int z)
{
    if (x + y > z && x + z > y && y + z > x)
    {
        a = x; b = y; c = z;
    }
    else
    {
        a = b = c = 5;
    }
}
void triangle::print()
{
    cout << "triangle:" << a << "," << b << "," << c << endl;
}
void seta(triangle& t, int n)
{
    t.a = n;//访问对象的私有成员
}
int main()
{
    triangle t;
    t.print();
    seta(t, 10);
    t.print();
    return 0;
}
out:

triangle:5, 5, 5
triangle : 10, 5, 5

Ⅱ友元类

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
//一个类的友元类所有成员函数都有访问类的所有成员的权限,friend+class+类名
//友元的声明是单方面不传递的
class B;
class A
{
public:
    void setB(B& b, int m);
    void print(B& b);
};
class B
{
    friend class A;//声明友元,A可以访问B中所有成员
private:
    int data;
};
void A::setB(B& b, int m)
{
    b.data = m;
}
void A::print(B& b)
{
    //访问私有成员
    cout << "Thea private data of class B:" << b.data << endl;
}
int main()
{
    A a;
    B b;
    a.setB(b, 10);//调用A的成员函数修改类B的对象b的私有数据
    a.print(b);//调用A的成员函数访问b的私有数据
    
    return 0;
}
out:
Thea private data of class B :10

五、运算符重载

①原理

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
//操作预定义数据对象的方式,自定义的对象操作方式,operator<运算符>
//.,*,::,?:,sizeof 不能被重载
class complex
{
public:
    complex(double = 0.0, double = 0.0);
    complex operator+(const complex&)const;//常量成员函数,即该函数不会修改类的任何成员变量。
    complex& operator=(const complex&);
    void print() const;
private:
    double real;
    double imaginary;
};
complex::complex(double r, double i)
{
    real = r; imaginary = i;
}
complex complex::operator+(const complex& operand2)const
{
    complex sum;
    sum.real = real + operand2.real;
    sum.imaginary = imaginary + operand2.imaginary;
    return sum;
}
complex& complex::operator=(const complex& right)
{
    real = right.real;
    imaginary = right.imaginary;
    return *this;
}
void complex::print()const
{
    cout << "(" << real << "," << imaginary << ")";
}
int main()
{
    complex x, y(4.3, 8.2), z(3.3, 1.1);
    x = y + z;//x.operator=(y.operator+(z));赋值运算符
    cout << "x=y+z:\n";
    x.print();
    cout << "="; y.print();
    cout << "+"; z.print();
    cout << endl;
    return 0;
}
out:

x = y + z :
    (7.6, 9.3) = (4.3, 8.2) + (3.3, 1.1)

②方式

Ⅰ成员函数重载

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
//成员函数方式重载运算符
//重载!为成员函数
class mystring
{
public:
    mystring(const char* m = NULL);//默认构造函数
    ~mystring();
    //运算符重载成员函数原型
    bool operator!();
private:
    char* str;
};
mystring::mystring(const char* m)
{
    if (m == NULL)
    {
        str == NULL;
    }
    else
    {
        int len = strlen(m) + 1;//留一个放"\0"
        str = new char[len];
        strcpy_s(str, len, m);
    }
}
mystring::~mystring()
{
    if (str != NULL)
        delete[]str;
}
//实现运算符重载函数
bool mystring::operator!()
{
    if (str == NULL || strlen(str) == 0)
        return true;
    return false;
}
int main()
{
    mystring s1, s2("some string");
    if (!s1)
        cout << "s1 is NULL!" << endl;
    else
        cout << "s1 is not NULL!" << endl;
    if (!s2)
        cout << "s2 is NULL!" << endl;
    else
        cout << "s2 is not NULL!" << endl;
    return 0;
}
out:

s1 is NULL!
s2 is not NULL!

Ⅱ友元函数重载

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

class mystring
{
public:
    mystring(const char* m = NULL);//默认构造函数
    ~mystring();
    friend bool operator!(mystring&s);
private:
    char* str;
};
mystring::mystring(const char* m)
{
    if (m == NULL)
    {
        str == NULL;
    }
    else
    {
        int len = strlen(m) + 1;//留一个放"\0"
        str = new char[len];
        strcpy_s(str, len, m);
    }
}
mystring::~mystring()
{
    if (str != NULL)
        delete[]str;
}
//实现运算符重载函数
bool operator!(mystring& s)
{
    if (s.str == NULL || strlen(s.str) == 0)
        return true;
    return false;
}
int main()
{
    mystring s1, s2("some string");
    if (!s1)
        cout << "s1 is NULL!" << endl;
    else
        cout << "s1 is not NULL!" << endl;
    if (!s2)
        cout << "s2 is NULL!" << endl;
    else
        cout << "s2 is not NULL!" << endl;
    return 0;
}
out:

s1 is NULL!
s2 is not NULL!

③单目与双目运算符重载

Ⅰ单目(目表示操作数)

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

//重载运算符前自增++,返回值*this,类型complex&
class complex
{
public:
    complex(double = 0.0, double = 0.0);
    complex& operator++();//成员函数形式
    void print()const;
private:
    double real;
    double imaginary;
};
complex::complex(double r, double i)
{
    real = r;
    imaginary = i;
}
void complex::print()const
{
    cout << "(" << real << "," << imaginary << ")";
}
complex& complex::operator++()
{
    this->real += 1;
    return *this;
}
int main()
{
    complex y(4.3, 8.2), x;
    x = ++y;//x=y.operator++()
    cout << "y:"; y.print();
    cout << "\tx:"; x.print();
    cout << endl;
    return 0;
}
out:

y:(5.3,8.2)     x:(5.3,8.2)

Ⅱ流插入和流提取运算符的重载

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

//如何实现用cout输出自定义类型的对象,重载<<和>>
class mystring
{
    //重载流插入和流提取函数
    friend ostream& operator<<(ostream& output, mystring& s);
    friend istream& operator>>(istream& input, mystring& s);
public:
    mystring(const char* m = NULL);
    ~mystring();
private:
    char* str;
};
mystring::mystring(const char* m)
{
    if (m == NULL)
        str == NULL;
    else
    {
        int len = strlen(m) + 1;
        str = new char[len];
        strcpy_s(str, len, m);
    }
}
mystring::~mystring()
{
    if (str != NULL)
        delete[]str;
}
//定义运算符<<重载函数
ostream& operator<<(ostream& output, mystring& s)
{
    output << s.str;
    return output;
}
//定义运算符>>重载函数
istream& operator>>(istream& input, mystring& s)
{
    char temp[1000];
    cin >> temp;
    if (s.str)delete[]s.str;//释放内存
    int len = strlen(temp) + 1;//"\0"
    s.str = new char[len];
    strcpy_s(s.str, len, temp);
    return input;
}
int main()
{
    mystring s1, s2;
    cout << "Please input two strings" << endl;
    cin >> s1 >> s2;
    cout << "Output is:" << endl;
    cout << "s1——" << s1 << endl << "s2——" << s2 << endl;
    return 0;
}
output:

Please input two strings
dager
fewre
Output is :
s1——dager
s2——fewre

Ⅲ双目

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

//友元函数重载运算符+=
class mystring
{
    friend mystring& operator+=(mystring& x, mystring& y);
public:
    mystring(const char* m = NULL);
    ~mystring();
    void print() const;
private:
    char* str;
};
mystring::mystring(const char* m)
{
    if (m == NULL)
        str == NULL;
    else
    {
        int len = strlen(m) + 1;
        str = new char[len];
        strcpy_s(str, len, m);
    }
}
mystring::~mystring()
{
    if (str != NULL)
        delete[]str;
}
void mystring::print()const
{
    cout << str<<endl;
}
mystring& operator+=(mystring& x, mystring& y)
{
    int len = strlen(x.str) + strlen(y.str) + 1;
    char* temp = new char[len];
    strcpy_s(temp, len, x.str);
    strcat_s(temp, len, y.str);
    delete[]x.str;
    x.str = temp;
    return x;
}
int main()
{
    mystring s1("hello"), s2("world");
    s1 += s2;
    s1.print();
    return 0;
}
output:
helloworld

Ⅳ类型转化

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
//类型转换,必须是类的非静态成员函数,不是友元函数,不能指定返回类型(其实已经指定了)
//operator+类型名 (int)obj等价于obj.operator int()
class Fraction {
private:
    int numerator;
    int denominator;

public:
    Fraction(int num, int den) : numerator(num), denominator(den) {}

    // 将 Fraction 类型转换为 double 类型
    operator double() const {
        return (double)numerator / denominator;
    }
};
int main()
{
    Fraction f(3, 4);
    double d = f; // 将 Fraction 类型转换为 double 类型
    cout << d << endl;
    return 0;
}
out:
0.75

六、继承派生多态

①继承

Ⅰ成员函数的重定义


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
//派生类重定义基类成员函数
class child
{
public:
    void showinfo()
    {
        cout << "I'm child" << endl;
    }
};
class parent:public child
{
public:
    void showinfo()
    {
        child::showinfo();
        cout << "I'm parent" << endl;
    }
};
int main()
{
    parent p;
    p.showinfo();
    return 0;
}
out:
I'm child
I'm parent

Ⅱ类指针

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;
//类指针
class media
{
public:
    media(const char* n, const char* c);
    ~media();
    const char* getname();
    const char* getcompany();
private:
    char* name;
    char* company;
};
media::media(const char* n, const char* c)
{
    name = new char[strlen(n) + 1];
    strcpy(name, n);
    company = new char[strlen(c) + 1];
    strcpy(company, c);
}
media::~media()
{
    if (name != NULL) delete[]name;
    if (company != NULL) delete[]company;
}
const char* media::getname()
{
    return name;
}
const char* media::getcompany()
{
    return company;
}
class audiomedia :public media
{
public:
    audiomedia(const char* n, const char* c, const char* s);
    ~audiomedia();
    const char* getsinger();
private:
    char* singer;
};
audiomedia::audiomedia(const char* n, const char* c, const char* s) :media(n, c)//调用基类的构造函数
{
    singer = new char[strlen(s) + 1];
    strcpy(singer, s);
}
audiomedia::~audiomedia()
{
    if (singer != NULL) delete[]singer;
}
const char* audiomedia::getsinger()
{
    return singer;
}
int main()
{
    media medium("slumdog millionaire", "celador films");
    audiomedia audio("the color of my love", "columbia", "celine dion");
    media* mptr;
    mptr = &medium;
    cout << "Accessing media object through meida*" << endl;
    cout << "name:" << mptr->getname() << endl;
    cout << "company:" << mptr->getcompany() << endl;
    mptr = &audio;
    cout << "Accessing auidomedia object through media*" << endl;
    cout << "name:" << mptr->getname() << endl;
    cout << "company:" << mptr->getcompany() << endl;
    cout << "singer:" << ((audiomedia*)mptr)->getsinger()<<endl;//强制类型转换
    return 0;
}
out:
Accessing media object through meida*
name : slumdog millionaire
company : celador films
Accessing auidomedia object through media*
name : the color of my love
company : columbia
singer : celine dion

②多态

Ⅰ虚函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
using namespace std;

class media
{
public:
    media(const char* n, const char* c);
    ~media();
    virtual void showinfo();
private:
    char* name;
    char* company;
};
media::media(const char* n, const char* c)
{
    name = new char[strlen(n) + 1];
    strcpy(name, n);
    company = new char[strlen(c) + 1];
    strcpy(company, c);
}
media::~media()
{
    if (name != NULL) delete[]name;
    if (company != NULL) delete[]company;
}
void media::showinfo()
{
    cout << "name:" << name << endl;
    cout << "company:" << company << endl;
}
class audiomedia :public media
{
public:
    audiomedia(const char* n, const char* c, const char* s);
    ~audiomedia();
    void showinfo();
private:
    char* singer;
};
audiomedia::audiomedia(const char* n, const char* c, const char* s) :media(n, c)//调用基类的构造函数
{
    singer = new char[strlen(s) + 1];
    strcpy(singer, s);
}
audiomedia::~audiomedia()
{
    if (singer != NULL) delete[]singer;
}
void audiomedia::showinfo()
{
    media::showinfo();//调用被重定义的函数
    cout << "singer:" << singer <<endl;
}
int main()
{
    media* mptr;
    media medium("slumdog millionaire", "celador films");
    audiomedia audio("the color of my love", "columbia", "celine dion");
    mptr = &medium;
    mptr->showinfo();//基类指针指向基类对象
    cout << endl;//基类指针调用成员函数,动态绑定
    mptr = &audio;//基类指针指向派生类对象
    mptr->showinfo();//基类指针调用成员函数,动态绑定
    return 0;
}
name:slumdog millionaire
company : celador films

name : the color of my love
company : columbia
singer : celine dion

Ⅱ抽象基类与纯虚函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#define PI 3.14
using namespace std;
//纯虚函数:没有函数体,初始化为0
//抽象类,包含纯虚函数不能实例化对象
class shape//抽象基类
{
public:
    virtual double area()const = 0;
    virtual void show()const = 0;
};
class circle :public shape
{
public:
    circle(double = 0.0, double = 0.0, double = 1.0);
    double area()const;
    void show()const;
private:
    double x, y;
    double r;
};
circle::circle(double a, double b, double c)
{
    x = a; y = b; r = c;
}
double circle::area()const
{
    return PI * r * r;
}
void circle::show()const
{
    cout << "I'm a circle:";
}
class rectangle :public shape
{
public:
    rectangle(double = 1.0, double = 1.0);
    double area()const;
    void show()const;
private:
    double length;
    double width;
};
rectangle::rectangle(double a, double b)
{
    length = a; width = b;
}
double rectangle::area()const
{
    return length * width;
}
void rectangle::show()const
{
    cout << "I'm a rectangle:";
}
void callarea(shape&obj)
{
    obj.show();
    cout << "area=" << obj.area() << endl;
}
int main()
{
    circle cir(0.0, 0.0, 2.5);
    rectangle rec(2.4, 5.3);
    callarea(cir);
    callarea(rec);
    return 0;
}
out:
I'm a circle:area=19.625
I'm a rectangle:area=12.72

Ⅲ虚析构函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <cstring>
#define PI 3.14
using namespace std;
class employee
{
public:
    employee()
    {
        cout << "Employee begin!" << endl;
    }
    virtual ~employee()
    {
        cout << "Employee end!" << endl;
    }
};
class programmer :public employee
{
public:
    programmer(char* str)
    {
        cout << "Programmer begin!" << endl;
        name = new char[strlen(str) + 1];
        strcpy(name, str);
    }
    ~programmer()
    {
        delete[]name;
        cout << "programmer end!" << endl;
    }
private:
    char* name;
};
class accountant :public employee
{
public:
    accountant(int n)
    {
        cout << "accountant begin!" << endl;
        age = n;
    }
    ~accountant()
    {
        cout << "accountant end!" << endl;
    }
private:
    int age;
};

int main()
{
    int no;
    employee* ptr[100], * tptr;//声明储存雇员信息的数组
    int Enum = 0;
    char name[100];
    int age;
    for (int i = 0; i < 100; i++)
    {
        ptr[i] = NULL;
    }
    cout << "Input employees' info:" << endl;
    cout << "1---Programmer" << endl
        << "2---Accoutant" << endl
        << "0--exit" << endl;
    cin >> no;
    while (no)
    {
        switch (no)
        {
        case 1:
            cout << "Input name:";
            cin >> name;
            tptr = new programmer(name);
            ptr[Enum++] = tptr;
            break;
        case 2:
            cout << "Input age:";
            cin >> age;
            tptr = new accountant(age);
            ptr[Enum++] = tptr;
            break;
        default:
            cout << "It's over" << endl;
        };
        cout << "Input another employee's info:" << endl;
        cout << "1---Programmer" << endl
            << "2---Accountant" << endl
            << "0---exit" << endl;
        cin >> no;
    }
    //撤销所有对象
    for (int i = 0; i < Enum; i++)
    {
        delete ptr[i];
    }
    return 0;
}
out:
Input employees' info:
1-- - Programmer
2-- - Accoutant
0--exit
1
Input name : swx
Employee begin!
Programmer begin!
Input another employee's info:
1-- - Programmer
2-- - Accountant
0-- - exit
2
Input age : 12
Employee begin!
accountant begin!
Input another employee's info:
1-- - Programmer
2-- - Accountant
0-- - exit
0
programmer end!
Employee end!
accountant end!
Employee end!

③STL

Ⅰ动态学生信息管理https://www.educoder.net/tasks/p4imnbvy/887783/ok8rac4vzhbx?coursesId=p4imnbvy

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

class Student {
public:
    string name;
    int score;

    Student(string n, int s) {
        name = n;
        score = s;
    }
};

vector<Student> studentTable;

void addOrUpdateRecord(string name, int score)
{
    bool found = false;
    for (int i = 0; i < studentTable.size(); i++) {
        if (studentTable[i].name == name) {
            studentTable[i].score = score;
            found = true;
            break;
        }
    }
    if (!found) {
        Student newStudent(name, score);
        studentTable.push_back(newStudent);
    }
}

void deleteRecord(string name) {
    for (int i = 0; i < studentTable.size(); i++) {
        if (studentTable[i].name == name) {
            studentTable.erase(studentTable.begin() + i);
            break;
        }
    }
}

void printTable() {
    if (studentTable.empty()) {
        cout << "[空]" << endl;
    }
    else {
        for (int i = 0; i < studentTable.size(); i++) {
            cout << studentTable[i].name << " " << studentTable[i].score << endl;
        }
    }
}

bool compareScore(Student s1, Student s2) {
    return s1.score > s2.score;
}

void sortTable() {
    sort(studentTable.begin(), studentTable.end(), compareScore);
}
int main()
{
    string input;
    while (getline(cin, input)) {
        if (input[0] == 'A') {
            char name[10];
            int score;
            sscanf(input.c_str(), "A %s %d", name, &score);
            addOrUpdateRecord(name, score);
        }
        else if (input[0] == 'R') {
            char name[10];
            sscanf(input.c_str(), "R %s", name);
            deleteRecord(name);
        }
        else if (input[0] == 'P') {
            printTable();
        }
        else if (input[0] == 'S') {
            sortTable();
        }
    }
}

Ⅱ还原键盘输入https://www.educoder.net/tasks/p4imnbvy/887783/yf2swgkio7ma?coursesId=p4imnbvy

#include <iostream>
#include <string>
#include <list>
using namespace std;

int main()
{
    //读取输入,解析并输出复原后的输出
    string input;
    string output;

    while (getline(cin, input)) {
        list<char> chars;
        auto it = chars.begin();

        for (char c : input) {
            if (c == '<') {
                if (it != chars.begin()) {
                    it--;
                }
            }
            else if (c == '>') {
                if (it != chars.end()) {
                    it++;
                }
            }
            else if (c == '[') {
                it = chars.begin();
            }
            else if (c == ']') {
                it = chars.end();
            }
            else {
                it = chars.insert(it, c);
                it++;
            }
        }

        for (char c : chars) {
            output += c;
        }
        cout << output << endl;
        output.clear();
    }

    return 0;
}