Contents

C++程序设计

第一课

C语法回顾

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
基本类型:int char float double
输入输出:scanf printf
基本语句:for,while,switch case,if else ...
数组:int arr[ ]
字符串:char str[ ]
指针:int *p
内存分配:malloc和free
函数:function
结构体:struct
文件操作:FILE

C++对C的扩展

命名空间

作用域:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
变量都有其作用域
全局变量:(全局)
局部变量:(函数内部或{ }内)

相同作用域中,同名变量只可定义一次
不同作用域中,同名变量可重复定义,
只有新定义的起作用。

实际上,不同作用域的同名变量所占有
的内存空间是不同的。

引入原因:

1
2
3
4
5
在大中型项目开发过程中,经常会用到多家公司提供的类库,或者协作开发的多个小组之间,可能会使用同名的函数或者全局变量,从而造成冲突。

命名空间,是为了解决这种命名冲突而引入的一种机制。
C语言中没有该机制
C++语言中引入了该机制

基本语法:

1
2
3
4
5
6
7
8
namespace 空间名字 {
变量;
函数; ......
} (注意,此处没有分号)

基本用法:空间名字::变量名/函数名
命名空间分割了全局命名空间(::)
每个命名空间都是一个作用域

使用用法:

1
2
3
4
5
1. 空间名字::变量名/函数名
2. using 空间名字::变量名/函数名;
3. using namespace 空间名字;
2种用法每次只能引入一个成员;
3种用法会打开该空间中所有的成员(变量/函数等),谨慎使用

嵌套、不连续:

1
2
3
4
5
6
命名空间支持嵌套
命名空间可以是不连
续的,同名空间自动合并。

不要把 #include 放在
命名空间内部

实际应用:

1
2
3
4
起别名(方便书写)
namespace TV=myTelev....;

平时常用的命名空间成员的using声明写在一个头文件中,方便使用。(如:usingstd::cout;)

输入输出

cin和cout :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
C++(头文件 #include <iostream>)
cin 标准输入
cout 标准输出
cerr 标准错误输出
C(头文件#include<stdio.h>)
键盘 scanf
屏幕 printf
屏幕 fprintf(stderr,...)

cin和cout是C++的标准输入流和标准输出流。
在头文件<iostream>中定义。
需要使用命名空间std
std::cin std::cout std::endl (推荐用法)
或者 using std::cin; using std::cout; using std::endl;
或者 using namespace std; (为了演示方便,使用该方法)

格式化:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

int main() {
	int a = 12345;
	double f = 123.4567;
	//默认输出整数
	printf("a=%d===\n", a);
	//占8格,右对齐
	printf("a=%8d===\n", a);
	//占8格,左对齐
	printf("a=%-8d===\n", a);
	//默认输出浮点数,小数显示6位
	printf("f=%f===\n", f);
	//占10格,小数显示2位,右对齐
	printf("f=%10.2f===\n", f);
	//占10格,小数显示2位,左对齐
	printf("f=%-10.2f===\n", f);

	return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
	int a = 12345;
	double f = 123.4567;
	//默认输出整数
	cout << "a=" << a << "===" << endl;
	//占8格,右对齐
	cout << "a=" << setw(8) << a << "===" << endl;
	//占8格,左对齐
	cout << "a=" << setw(8) << setiosflags(ios::left)
		<< a << "===" << endl;
	//默认输出浮点数,有效位数显示6位
	cout << "f=" << f << "===" << endl;
	//占10格,小数显示2位,右对齐
	cout << "f=" << setw(10) << setprecision(2)
		<< setiosflags(ios::fixed) << setiosflags(ios::right)
		<< f << "===" << endl;
	
	return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <iomanip>
using namespace std;
struct mytime {
	int h;
	int m;
	int s;
};
int main() {
	mytime t1 = { 7,9,8 };
	cout << "time: " << t1.h
		<< ":" << t1.m
		<< ":" << t1.s
		<< endl;
	cout << "time: " << setfill('0')
		<< setw(2) << t1.h << ":"
		<< setw(2) << t1.m << ":"
		<< setw(2) << t1.s << endl;
	return 0;
}

字符串:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>
#include <string.h>
int main() {
	char str[10] = { 0 };
	fgets(str, sizeof(str), stdin);
	if (str[strlen(str) - 1] == '\n')
		str[strlen(str) - 1] = '\0';
	printf("%s\n", str);
	return 0;
}
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
int main() {
	char str[10] = { 0 };
	cin.getline(str, sizeof(str));
	cout << str << endl;
	return 0;
}

数据类型

基本内置类型:

1
2
3
4
5
6
7
bool类型是C++新增的。
bool类型的取值是true(真),false(假)
常用的数据类型:
unsigned int
short, unsigned short
long, unsigned long
long long, unsigned long long

基本类型转换

unsigned注意

声明、列表初始化

指针和引用

1
2
3
4
5
6
7
指针实际上是地址,指针变量用来存放指针(地址)。
指针变量也是一种变量,同样要占用一定的存储空间。
指针的存储空间存放的是一个地址。

引用是给变量或对象起一个别名。
定义时必须初始化,一旦绑定,终身不变。
引用并不占用存储空间。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
int main() {
	int i = 10, j = 20;
	int *pi = &i; //pi是指向i的指针
	cout << *pi << " " << i << endl; //*pi 相当于 i
	*pi = 100;
	cout << *pi << " " << i << endl; //通过指针改变值
	pi = &j; //pi指针指向其他对象了
	cout << *pi << " " << j << endl;

	//空指针:
	//NULL 在c中的定义是 ((void*)0)
	//NULL 在c++中定义是 0
	//nullptr 在c++中用来表示空指针
	int *p = nullptr;
	if (p)
		cout << "p is true" << endl;
	else
		cout << "p is false" << endl;
	return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <iostream>
using namespace std;
int main() {
	int i = 100;
	int &ref_i = i;	//ok
	//int &ref_i2;	//错误(引用必须被初始化)

	//注意书写方式:
	int *a1 = nullptr, a2 = 0;
	//上面一行:a1是指针,a2是int变量
	int &r1 = a2, r2 = a2;
	//上面一行:r1是a2的引用,r2是int变量
	return 0;
}

引用的本质:

1
2
3
从下面的代码,可以猜测,引用好像就是个指针。
通过汇编代码的分析,可以推测引用实际上是通过指针来实现的。
引用是指针的一种包装:类似 int * const p 这样的格式的一种包装。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;

struct Stu {
	int age;
	char sex;
	char name[20];
};
struct A {
	int &data;
};
struct B {
	char &data;
};
struct C {
	Stu &data;
};

int main() {
	cout << sizeof(A) << endl; //4
	cout << sizeof(B) << endl; //4
	cout << sizeof(C) << endl; //4
	return 0;
}

const限定符

1
2
3
4
5
6
7
8
9
C++增强了对类型的限制。
const限定符在C++编程中会经常用到。
const int i = 10;
//编译时初始化
const int i = get_size(); //运行时初始化
int j = 20; const int i = j; //用来初始化的值是否常量无关紧要
默认情况下:const对象仅在文件内有效
假如要在多个文件中生效,const变量不管是声明还是定义,都加上
extern关键字

struct和class

1
2
3
4
结构体是一种自定义数据类型。
标准C中的结构体是不允许包含成员函数
C语言结构体中可通过函数指针的方式加函数
C++中的结构体对此进行了扩展

字符串

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <string>

using namespace std;
int main() {
	//std::string
	std::string str1("abc"); //初始化
	string str2 = "bcd";	 //初始化
	str2 = "defg";			 //可以直接赋值
	str2 = str1;			 //可以直接赋值

	const char *pstr = str2.c_str(); //转c风格字符串
	str2[0] = 'X';		//可以直接下标访问操作
	str2.at(1) = 'Y';	//可以 at 访问操作
	cout <<"str2=" << str2 << endl; //XYc

	//求字符串长度
	cout << str2.size() << endl;
	cout << str2.length() << endl;
	//strlen(str1); 错误
	cout << strlen(str2.c_str()) << endl; //正确
	//字符串连接
	str2 = str2 + str1 + "!!";
	cout << "str2=" << str2 << endl; //XYcabc!!
	//字符串比较 (str1: abc)
	cout << str2.compare(str1) << endl; //-1
	cout << (str2 < str1) << endl;	    //1
	//字符串查找
	cout << str2.find(str1) << endl;	//3
	//字符串提取
	string str3 = str2.substr(3, 3);
	cout << str3 << endl;				//abc

	return 0;
}

vector

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
	//std::vector的结构
	std::vector<int> vec11; // [ 1, 3, 9 ...]
	vector<string> vec22;   // [ "abc", "play", "C++" ]
	vector<vector<int>> vec33; // [ [1,3,9..],[2,3,4..], ... ]
	vector<vector<string>> vec44; // [ ["hello","C",..],["C++","abc",..],... ]

	//vector的初始化
	vector<int> vec1 = { 1,2,3 };
	vector<int> vec2{ 1,2,3 };  //列表初始化
	vector<int> vec3 = vec1;    //vec1拷贝给 vec3
	vector<int> vec4(10);		//初始化10个元素,每个元素都是0
	vector<int> vec5(10, -1);	//初始化10个元素,每个元素都是-1
	vector<string> vec6(10, "hi"); //初始化10个元素,每个元素都是 "hi"

	//判断是否为空
	cout << vec1.empty() << endl; //0
	//元素个数
	cout << vec1.size() << endl;  //3
	//添加元素在最后面
	vec1.push_back(100);
	cout << vec1[vec1.size() - 1] << endl; //100
	//弹出元素在最后面
	vec1.pop_back();
	cout << vec1[vec1.size() - 1] << endl; //3
	//直接下标访问元素
	cout << vec1[1] << endl; //2
	vec1[1] = 10;
	cout << vec1[1] << endl; //10
	// vector<string> vec6(10, "hi")
	vec6[0][1] = 'X';
	cout << vec6[0] << endl; //hX

	//遍历(类似遍历数组)
	for (int i = 0; i < vec1.size(); i++) 
		cout << vec1[i] << " "; // 1 10 3
	cout << endl;

	return 0;
}

auto类型说明符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;

int main() {
	//1.auto 变量必须在定义时初始化,类似于const
	auto i1 = 0; auto i2 = i1;
	//auto i3; //错误,必须初始化
	//2.如果初始化表达式是引用,则去除引用语义
	int a1 = 10;
	int &a2 = a1; // a2是引用
	auto a3 = a2; // a3是int类型,而不是引用
	auto &a4 = a1; // a4是 引用
	//3.去除顶层const
	const int b1 = 100;
	auto b2 = b1; // b2 是 int
	const auto b3 = b1; // b3是 const int
	//4.带上底层const
	auto &b4 = b1; // b4 是 const int 的引用
	//5.初始化表达式为数组时,推导类型为指针
	int arr[3] = { 1,2,3 };
	auto parr = arr; //parr 是 int * 类型
	cout << typeid(parr).name() << endl;
	//6.表达式为数组且auto带上&,推导类型为数组
	auto &rarr = arr; //rarr 是 int [3]
	cout << typeid(rarr).name() << endl;
	//7.函数参数类型不能是 auto
	//func(auto arg); //错误
	//8.auto并不是一个真正的类型,编译时确定
	//sizeof(auto); 错误
	return 0;
}

第二课