相关内容来自B站黑马程序员:C++教程从0到1入门编程
C++起步知识
注释
和Java一样,C++的注释分为单行注释和多行注释
单行注释://
多行注释:/* */
例如:
入口函数
在C++中,入口函数为main函数,每个程序有且仅有一个入口函数,对应Java中的public static void main
1 2 3 4 5 6 7 8 9
| #include <iostream>
using namespace std;
int main() { cout << "Hello World" << endl; return 0; }
|
变量
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量 = 值;
1 2 3 4 5 6 7 8 9 10 11
| #include <iostream>
using namespace std;
int main() { int a = 10;
cout << "a = " << a << endl; return 0; }
|
变量命名规则:
- 字母、数字和下划线:变量名可以包含字母(A-Z, a-z)、数字(0-9)和下划线(_)。
- 以字母或下划线开头:变量名必须以字母或下划线开头,不能单独使用数字开头。
- 区分大小写:C++是区分大小写的语言,因此
variable和Variable会被视为两个不同的标识符。
- 避免使用保留关键字:避免使用C++的保留关键字作为变量名。例如,
int, class, if, for等是C++的关键字,不能用作变量名。
| asm |
do |
if |
return |
typedef |
| auto |
double |
inline |
short |
typeid |
| bool |
dynamic_cast |
int |
signed |
typename |
| break |
else |
long |
sizeof |
union |
| case |
enum |
mutable |
static |
unsigned |
| catch |
explicit |
namespace |
static_cast |
using |
| char |
export |
new |
struct |
virtual |
| class |
extern |
operator |
switch |
void |
| const |
false |
private |
template |
volatile |
| const_cast |
float |
protected |
this |
wchar_t |
| continue |
for |
public |
throw |
while |
| default |
friend |
register |
true |
|
| delete |
goto |
reinterpret_cast |
try |
|
常量
作用:用于记录程序中不可更改的数据
定义方式:
#define宏常量:#define 常量名 常量值
- 通常在文件上方定义,表示一个常量,常量名一般都是以全部大写命名
const修饰的变量:const 数据类型 常量名 = 常量值
- 通常在变量定义前加关键字
const,修饰该变量为常量,不可修改
- 命名规则与变量一样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <iostream> #define PI 3.141
using namespace std;
int main() { cout << "PI = " << PI << endl; const int minutesInOneHour = 60; cout << "一小时有:" << minutesInOneHour << "分钟" << endl; return 0; }
|
数据类型
C++规定在创建一个变量或常量时,必须要指定相应的数据类型,否则无法给变量分配内存
整型
整型也称整数类型,C++有以下几种整型类型:
| 数据类型 |
占用空间 |
取值范围 |
| short(短整型) |
2字节 |
(-2^15 ~ 2^15-1) |
| int(整型) |
4字节 |
(-2^31 ~ 2^31-1) |
| long(长整形) |
Windows为4字节,Linux为4字节(32位),8字节(64位) |
(-2^31 ~ 2^31-1) |
| long long(长长整形) |
8字节 |
(-2^63 ~ 2^63-1) |
sizeof关键字
作用:利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof(数据类型/变量)
1 2 3 4 5 6 7 8 9 10
| #include <iostream>
using namespace std;
int main() { char h = 'h'; cout << sizeof(int) << endl; cout << sizeof(h) << endl; return 0; }
|
浮点型
作用:表示小数
浮点型分为两种:
- 单精度float
- 双精度double
| 数据类型 |
占用空间 |
有效数字范围 |
| float |
4字节 |
7位有效数字 |
| double |
8字节 |
15~16位有效数字 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
using namespace std;
int main() { float a = 3.1415f; double b = 1.01;
float c = 1.0000001f;
cout << a << endl; cout << b << endl; cout << c << endl;
float f1 = 3e2; float f2 = 3e-2;
return 0; }
|
精度丢失问题:
- 十进制 0.1 的二进制是无限循环小数:
0.1(十进制) = 0.00011001100110011...(二进制),就像十进制的 1/3 = 0.3333…。
案例:
1
| float count = 0.1 + 0.2;
|
字符型
作用:字符型变量用于显示单个字符
语法:char ch = 'a';
注意:在显示字符变量时,用单引号将字符括起来,而不是双引号
注意:单引号内只能有一个字符,不能是字符串
- C和C++中字符型变量只占用1个字节
- 字符型变量并不是把字符本身放到内存中存储,而是将字符对应的ASCII编码放入到存储单元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream>
using namespace std;
int main() { char c1 = 'h'; cout << c1 << endl; cout << sizeof(c1) << endl;
char c4 = 'a'; cout << (int)c4 << endl;
return 0; }
|
ASCII表:
| ASCII值 |
控制字符 |
ASCII值 |
字符 |
ASCII值 |
字符 |
ASCII值 |
字符 |
| 0 |
NUT |
32 |
(space) |
64 |
@ |
96 |
、 |
| 1 |
SOH |
33 |
! |
65 |
A |
97 |
a |
| 2 |
STX |
34 |
“ |
66 |
B |
98 |
b |
| 3 |
ETX |
35 |
# |
67 |
C |
99 |
c |
| 4 |
EOT |
36 |
$ |
68 |
D |
100 |
d |
| 5 |
ENQ |
37 |
% |
69 |
E |
101 |
e |
| 6 |
ACK |
38 |
& |
70 |
F |
102 |
f |
| 7 |
BEL |
39 |
, |
71 |
G |
103 |
g |
| 8 |
BS |
40 |
( |
72 |
H |
104 |
h |
| 9 |
HT |
41 |
) |
73 |
I |
105 |
i |
| 10 |
LF |
42 |
* |
74 |
J |
106 |
j |
| 11 |
VT |
43 |
+ |
75 |
K |
107 |
k |
| 12 |
FF |
44 |
, |
76 |
L |
108 |
l |
| 13 |
CR |
45 |
- |
77 |
M |
109 |
m |
| 14 |
SO |
46 |
. |
78 |
N |
110 |
n |
| 15 |
SI |
47 |
/ |
79 |
O |
111 |
o |
| 16 |
DLE |
48 |
0 |
80 |
P |
112 |
p |
| 17 |
DCI |
49 |
1 |
81 |
Q |
113 |
q |
| 18 |
DC2 |
50 |
2 |
82 |
R |
114 |
r |
| 19 |
DC3 |
51 |
3 |
83 |
S |
115 |
s |
| 20 |
DC4 |
52 |
4 |
84 |
T |
116 |
t |
| 21 |
NAK |
53 |
5 |
85 |
U |
117 |
u |
| 22 |
SYN |
54 |
6 |
86 |
V |
118 |
v |
| 23 |
TB |
55 |
7 |
87 |
W |
119 |
w |
| 24 |
CAN |
56 |
8 |
88 |
X |
120 |
x |
| 25 |
EM |
57 |
9 |
89 |
Y |
121 |
y |
| 26 |
SUB |
58 |
: |
90 |
Z |
122 |
z |
| 27 |
ESC |
59 |
; |
91 |
[ |
123 |
{ |
| 28 |
FS |
60 |
< |
92 |
/ |
124 |
| |
| 29 |
GS |
61 |
= |
93 |
] |
125 |
} |
| 30 |
RS |
62 |
> |
94 |
^ |
126 |
` |
| 31 |
US |
63 |
? |
95 |
_ |
127 |
DEL |
ASCII 码大致由以下两部分组成:
- ASCII 非打印控制字符: ASCII 表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备。
- ASCII 打印字符:数字 32-126 分配给了能在键盘上找到的字符,当查看或打印文档时就会出现。
转义字符
作用:用于表示一些不能显示出来的ASCII字符
常用转移字符有:\n \\ \t
| 转义字符 |
含义 |
ASCII码值(十进制) |
| \a |
警报 |
007 |
| \b |
退格(BS) ,将当前位置移到前一列 |
008 |
| \f |
换页(FF),将当前位置移到下页开头 |
012 |
| \n |
换行(LF) ,将当前位置移到下一行开头 |
010 |
| \r |
回车(CR) ,将当前位置移到本行开头 |
013 |
| \t |
水平制表(HT) (跳到下一个TAB位置) |
009 |
| \v |
垂直制表(VT) |
011 |
| \\ |
代表一个反斜线字符”" |
092 |
| ' |
代表一个单引号(撇号)字符 |
039 |
| " |
代表一个双引号字符 |
034 |
| ? |
代表一个问号 |
063 |
| \0 |
数字0 |
000 |
| \ddd |
8进制转义字符,d范围0~7 |
3位8进制 |
| \xhh |
16进制转义字符,h范围09,af,A~F |
3位16进制 |
1 2 3 4 5 6 7 8 9 10 11 12
| #include <iostream>
using namespace std;
int main() { cout << "Hello World" << endl; cout << "\t Hello World" << endl; cout << "\n Hello World" << endl; cout << "\\ Hello World" << endl;
return 0; }
|
字符串型
作用:用于表示一串字符
两种风格:
C风格字符串:char 变量名[] = "字符串值";
C++风格字符串:string 变量名 = "字符串值";
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream>
using namespace std;
int main() { string s1 = "Hello World"; char s2[] = "Hello World";
cout << s1 << endl; cout << s2 << endl;
cout << sizeof(s1) << endl; cout << sizeof(s2) << endl;
return 0; }
|
注意:字符串一定要用双引号括起来
注意:虽然string和char数组都可以表示字符串,但是所占的内存大小并不一样
| 类型 |
string类对象(s1) |
char[]数组(s2) |
| 内存布局 |
类实例,含指针、容量、大小等元数据 |
连续字符序列,结尾可能含\0 |
| sizeof结果 |
固定元数据大小(与字符串无关) |
整个数组的字节数(包含所有元素) |
布尔类型
作用:布尔类型表示值的真或假
布尔类型只有两种值:
true:表示值为真,本质是1
false:表示值为假,本质是0
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream>
using namespace std;
int main() { bool flag_1 = true; bool flag_2 = false;
cout << flag_1 << endl; cout << flag_2 << endl; cout << sizeof(flag_1) << endl; return 0; }
|
数据输入
作用:通过键盘输入数据
语法:cin >> 变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream>
using namespace std;
int main() { int number = 0;
cout << "请输入数据:" << endl; cin >> number;
cout << "您输入的是数字:" << number << endl;
return 0; }
|
数据类型之间的转换
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
| #include <iostream> #include <string> #include <typeinfo>
using namespace std;
int main() { string s1 = "123"; int n1 = stoi(s1); n1++; cout << n1 << endl;
int n2 = 11; string s2 = to_string(n2) + to_string(n2); cout << s2 << endl;
float f1 = 3.11f; int n3 = (int)f1; cout << n3 << endl;
int n4 = 10; float f2 = (float)n4; f2 += 0.1; cout << f2 << endl;
float f3 = 0.5f; string s3 = to_string(f3) + to_string(f3); cout << s3 << endl;
string s4 = "0.345"; float f4 = stof(s4); f4 += 0.1; cout << f4 << endl;
return 0; }
|
运算符
作用:用于执行代码的运算
| 运算符类型 |
作用 |
| 算术运算符 |
用于处理四则运算 |
| 赋值运算符 |
用于将表达式的值赋给变量 |
| 比较运算符 |
用于表达式的比较,并返回一个真值或假值 |
| 逻辑运算符 |
用于根据表达式的值返回真值或假值 |
算数运算符
| 运算符 |
术语 |
示例 |
结果 |
| + |
正号 |
+3 |
3 |
| - |
负号 |
-3 |
-3 |
| + |
加 |
10 + 5 |
15 |
| - |
减 |
10 - 5 |
5 |
| * |
乘 |
10 * 5 |
50 |
| / |
除 |
10 / 5 |
2 |
| % |
取模(取余) |
10 % 3 |
1 |
| ++ |
前置递增 |
a=2; b=++a; |
a=3; b=3; |
| ++ |
后置递增 |
a=2; b=a++; |
a=3; b=2; |
| – |
前置递减 |
a=2; b=–a; |
a=1; b=1; |
| – |
后置递减 |
a=2; b=a–; |
a=1; b=2; |
注意:整数与整数相除,结果一定是整数,如果除不尽则向下取整,如10 / 3 = 3
注意:整数与浮点数进行加减乘除,结果一定是浮点数
注意:小数不能做取模运算
赋值运算符
作用:用于将表达式的值赋给变量
| 运算符 |
术语 |
示例 |
结果 |
| = |
赋值 |
a=2; b=3; |
a=2; b=3; |
| += |
加等于 |
a=0; a+=2; |
a=2; |
| -= |
减等于 |
a=5; a-=3; |
a=2; |
| *= |
乘等于 |
a=2; a*=2; |
a=4; |
| /= |
除等于 |
a=4; a/=2; |
a=2; |
| %= |
模等于 |
a=3; a%2; |
a=1; |
比较运算符
作用:用于表达式的比较,并返回一个真值或假值
| 运算符 |
术语 |
示例 |
结果 |
| == |
相等于 |
4 == 3 |
0 |
| != |
不等于 |
4 != 3 |
1 |
| < |
小于 |
4 < 3 |
0 |
| > |
大于 |
4 > 3 |
1 |
| <= |
小于等于 |
4 <= 3 |
0 |
| >= |
大于等于 |
4 >= 1 |
1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream>
using namespace std;
int main() { int num_01 = 10; int num_02 = 20;
cout << (num_01 < num_02) << endl; cout << (num_01 > num_02) << endl; cout << (num_01 == num_02) << endl; cout << (num_01 <= num_02) << endl; cout << (num_01 >= num_02) << endl;
return 0; }
|
逻辑运算符
作用:用于根据表达式的值返回真值或假值
| 运算符 |
术语 |
示例 |
结果 |
| ! |
非 |
!a |
如果a为假,则!a为真; 如果a为真,则!a为假。 |
| && |
与 |
a && b |
如果a和b都为真,则结果为真,否则为假。 |
| || |
或 |
a || b |
如果a和b有一个为真,则结果为真,二者都为假时,结果为假。 |
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 num_01 = 10; int num_02 = 20; int num_03 = 30;
cout << !(num_01 < num_02) << endl; cout << !(num_01 > num_02) << endl;
cout << (num_01 < num_02 && num_02 < num_03) << endl; cout << (num_01 < num_02 && num_02 > num_03) << endl;
cout << (num_01 > num_02 || num_02 > num_03) << endl; cout << (num_01 < num_02 || num_02 < num_03) << endl;
return 0; }
|
程序流程结构
C/C++支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构
- 顺序结构:程序按顺序执行,不发生跳转
- 选择结构:依据条件是否满足,有选择的执行相应功能
- 循环结构:依据条件是否满足,循环多次执行某段代码
选择结构
if语句
作用:执行满足条件的语句
if语句的三种形式:
- 单行格式
if语句
- 多行格式
if语句
- 多条件的
if语句
- 单行格式
if语句:if (条件) {条件满足执行的语句}

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
| #include <iostream>
using namespace std;
int main() { int num = 0; cout << "请输入一个数字:" << endl; cin >> num; if (num < 10) { cout << "你输入的数字比10小" << endl; }
if (num >= 10 && num <= 20) { cout << "你输入的数字在10 ~ 20之间" << endl; }
if (num > 20) { cout << "你输入的数字比20大" << endl; }
return 0; }
|
- 多行格式
if语句:if (条件) {条件满足执行的语句} else { 条件不满足执行的语句 };

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <iostream>
using namespace std;
int main() { int num = 0; cout << "请输入一个数字:" << endl; cin >> num; if (num < 10) { cout << "你输入的数字比10小" << endl; } else { cout << "你输入的数字比10大" << endl; }
return 0; }
|
- 多条件
if语句:if (条件1) {条件1满足执行的语句} else if (条件2) {条件2满足执行的语句} ... else {都不满足执行的语句}
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
| #include <iostream>
using namespace std;
int main() { int num = 0; cout << "请输入一个数字:" << endl; cin >> num;
if (num < 10) { cout << "你输入的数字比10小" << endl; } else if (num < 20) { cout << "你输入的数字比10大比20小" << endl; } else if (num < 30) { cout << "你输入的数字比20大比30小" << endl; } else { cout << "你输入的数字大于等于30" << endl; } return 0; }
|
if语句嵌套
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
| #include <iostream> using namespace std;
int main() { int age; double height;
cout << "请输入年龄: "; cin >> age; cout << "请输入身高(cm): "; cin >> height;
if (age >= 18) { if (height >= 160.0) { cout << "符合条件,允许乘坐过山车!" << endl; } else { cout << "年龄达标,但身高不足160cm,不可乘坐" << endl; } } else { cout << "年龄未满18岁,禁止乘坐" << endl; }
return 0; }
|
三目运算符
作用:通过三目运算符实现简单的判断
语法:表达式1 ? 表达式2 : 表达式2;
解释:
如果表达式1的值为真,执行表达式2,并返回表达式2的结果
如果表达式2的值为假,执行表达式3,并返回表达式3的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <iostream>
using namespace std;
int main() { int a = 10; int b = 20; int c = 0;
a < b ? cout << "a小于b" << endl : cout << "a大于b" << endl;
c = a > b ? a : b; cout << "c的值为:" << c << endl;
return 0; }
|
switch语句
作用:执行多条件分支语句
语法:
1 2 3 4 5 6 7
| switch(表达式) { case 结果1: 执行语句1;break; case 结果2: 执行语句2;break; ... default:执行结果;break; }
|
示例:
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;
int main() { int a = 0;
cout << "请输入一个数:" << endl; cin >> a;
switch (a) { case 1: cout << "值为1" << endl; break; case 2: cout << "值为2" << endl; break; default: cout << "值不为1也不为2" << endl; break; }
return 0; }
|
如果不写break,switch会继续向下寻找符合条件的case并执行语句,这也称为case穿透:
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
| #include <iostream>
using namespace std;
int main() { int a = 0;
cout << "请输入一个数:" << endl; cin >> a;
switch (a) { case 0:; case 1:; case 2:; case 3:; case 4: cout << "值在0到4之间"; break; case 5:; case 6:; case 7:; case 8:; case 9: cout << "值在5到9之间"; break; default: cout << "值大于等于10"; break; }
return 0; }
|
循环结构
while循环语句
作用:满足循环条件,执行循环语句
语法:while(循环条件) {循环语句}
解释:只要循环条件的结果为真,就执行循环语句

示例:
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
| #include <iostream>
using namespace std;
int main() { int i = 0; while (i < 10) { cout << "我今年" << i << "岁了" << endl; i++; }
i = 0;
while (i < 100) { if (i == 18) { cout << "我成年啦" << endl; break; } else { cout << "我今年" << i << "岁了" << endl; i++; } }
i = 0;
while (i < 100) { if (i > 30 && i < 50) { i++; cout << "我要开始认真工作了" << endl; continue; } cout << "我今年" << i << "岁了" << endl; i++; }
return 0; }
|
注意:一定要注意避免死循环,如while (1),如果循环体中没有中断循环的代码,程序会一直运行直到内存资源消耗殆尽
do…while循环语句
作用:满足循环条件,执行循环语句
语法:do {循环语句} while {循环条件};
解释:在循环前先执行一次操作再判断循环条件
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <iostream>
using namespace std;
int main() { int password; do { cout << "请输入密码(必须>0):"; cin >> password; } while (password <= 0);
return 0; }
|
练习案例——水仙花数
水仙花数是指一个三位数,它的每个位上的数字的3次幂之和等于它本身
例如:1^3 + 5^3 + 3^3 = 153
利用do…while求出三位数中所有的水仙花数
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;
int main() { int num = 100;
do { int ge = num % 100 % 10; int shi = num / 10 % 10; int bai = num / 100;
if (pow(ge, 3) + pow(shi, 3) + pow(bai, 3) == num) { cout << num << "是水仙花数" << endl; num++; continue; }
num++;
} while (num < 1000);
return 0; }
|
for循环语句
作用:满足循环条件,执行循环语句
语法:for(起始表达式;条件表达式;末尾循环体) {循环语句;}
1 2 3 4 5 6 7
| int main() { for (int i = 0;i < 10; i++) { cout << i << endl; } return 0; }
|
嵌套循环
作用:在循环体中再嵌套一层循环
示例:
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
| #include <iostream>
using namespace std;
int main() {
for (int i = 1; i < 10; i++) { for (int j = 1; j <= i; j++) { cout << j << "x" << i << "=" << i * j << " "; }
cout << " " << endl; }
return 0; }
|
goto语句
作用:可以无条件跳转到语句
语法:goto 标记;
解释:如果标记的名称存在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <iostream>
using namespace std;
int main() {
cout << "1" << endl; goto Flag; cout << "2" << endl; cout << "3" << endl; cout << "4" << endl; Flag: cout << "5" << endl; cout << "6" << endl; cout << "7" << endl; cout << "8" << endl;
return 0; }
|
注意:由于goto代码会打乱代码的执行顺序,导致代码可读性变差,所以尽量避免使用
数组
数组就是一个集合,里面存放了相同类型的数据元素
特点1:数组中的每个数据元素都是相同的数据类型
特点2:数组是由连续的内存位置组成的
静态初始化
方式1(静态显式初始化):
语法:数据类型 数组名[数组长度] = {值1,值2,...,不能超过数组最大长度} ;
1 2 3 4
| int arr_01[5] = {1,2,3,4,5}; int arr_02[5] = {1,2,3}; int arr_03[5] = {1,2,3,4,5,6}; int arr_04[5]{1,2,3}
|
方式2(零初始化):
当前不考虑局部作用域
语法:数据类型 数组名[数组长度];
1 2 3 4 5 6 7 8
| int arr_01[5]; int arr[5]{}; arr_01[0] = 1; arr_01[1] = 2; arr_01[2] = 3; arr_01[3] = 4; arr_01[4] = 5; arr_01[5] = 6;
|
方式3(推导式静态显式初始化):
语法:数据类型 数组名[] = {1,2,3,4,...,没有长度限制}
1 2 3
| int arr_01[] = {1,2,3,4,5}; int arr_02[] = {1,2}; int arr_03[] = {1,2,3,4,5,6,7,8,9,10,11,...}
|
获取数组长度
C++17以前没有Python中len(数组名)或Java中数组名.length()来快速获取数组长度,需要进行单独的计算
计算公式:sizeof(数组名) / sizeof(数组数据类型)
解释:sizeof(数组名)表示数组中所有元素在内存中所占的大小,sizeof(数组数据类型)表示数组的数据类型所占内存空间大小
例如:
1 2 3 4 5
| int arr[] = {1,2,3,4,5,6,7,8,9};
int len_01 = sizeof(arr) / sizeof(int);
int len_02 = sizeof(arr) / sizeof(arr[0]);
|
C++17之后可以使用size()快速获取数组长度:
1 2 3 4 5 6 7 8 9 10
| #include <iostream> using namespace std;
int main() {
int arr[]{ 5,2,3,6,9,7,8,1,4 }; cout << size(arr) << endl;
return 0; }
|
冒泡排序
作用:最常用的排序算法,对数组内元素进行排序
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个
- 对每一个相邻元素做同样的工作,执行完毕后,找到第一个最大值
- 重复以上的步骤,每次比较次数-1,直到不需要比较
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
| #include <iostream>
using namespace std;
void coutArr(int arr[],int length) { for (int i = 0; i < length; i++) { cout << arr[i]; } }
int main() {
int arr[]{ 5,2,3,6,9,7,8,1,4 };
int length = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < length - 1; i++) { for (int j = 0; j < length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } }
coutArr(arr, length);
return 0; }
|
二维数组
二维数组定义的四种方式:
数据类型 数组名[行数][列数];
数据类型 数组名[行数][列数] = {{值1,值2}, {值3,值4}};
数据类型 数组名[行数][列数] = {数据1, 数据2, 数据3, 数据4};
数据类型 数组名[][列数] = {数据1,数据2,数据3,数据4};
推荐使用第二种方式,更加直观,提升代码可读性
示例:
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
| #include <iostream>
using namespace std;
int main() { int arr[2][3] = { {1,2,3}, {4,5,6} };
int row = sizeof(arr) / sizeof(arr[0]); int col = sizeof(arr[0]) / sizeof(arr[0][0]); cout << "col列:" << col << endl; cout << "row行:" << row << endl;
for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { cout << "第" << i + 1 << "行" << "第" << j + 1<< "列的数字是" << arr[i][j] << endl; } }
return 0; }
|
案例
将下表内容输出的控制台中:
|
语文 |
数学 |
英语 |
| 张三 |
100 |
100 |
100 |
| 李四 |
90 |
50 |
100 |
| 王五 |
60 |
70 |
80 |
答案:
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
| #include <iostream>
using namespace std;
int main() { int score[3][3] = { {100,100,100}, {90,50,100}, {60,70,80} };
string name[] = {"张三","李四","王五"};
int row = sizeof(score) / sizeof(score[0]); int col = sizeof(score[0]) / sizeof(score[0][0]);
cout << " 语文 数学 英语" << endl;
for (int i = 0; i < row; i++) { cout << name[i] << " "; for (int j = 0; j < col; j++) { cout << score[i][j] << " "; } cout << endl; }
return 0; }
|
函数
作用:将一段经常使用的代码封装起来,减少重复代码
函数的定义
- 返回值类型
- 函数名
- 参数列表
- 函数体语句
- return 表达式
语法:
1 2 3 4 5
| 返回值类型 函数名 (参数列表) { 函数体语句; return 表达式; }
|
基本使用案例:
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;
void saySomeThing(string strs) { cout << strs << endl; };
int sum(int num1, int num2) { return num1 + num2; }
int main() {
saySomeThing("Hello World"); saySomeThing("你好!!");
int count = sum(1, 2); cout << sum(5, 6) << endl;
return 0; }
|
注意:函数必须在main之前声明,否则运行时会检测不到函数而引起报错
1 2 3 4 5
| int main() { func(); }
void func() {...};
|
但是以下写法是可以的:
1 2 3 4 5 6 7 8 9
| void func();
int main() { func(); }
void func() { cout << "Hello World" << endl; }
|
函数的调用
以上代码已经包含了函数的调用,简单来说,调用一个函数只需要函数名(函数参数)即可
如:sum(1,2)、sayHello()、checkMission()
函数的值传递
函数定义时,括号里的参数表示形参,函数调用时,括号里的参数表示实参
值的传递流程就是:调用函数 => 修改/添加实参 => 对应位置上的形参被替换为实参 => 执行函数体内容
所以,只要实参和形参的类型相同,形参名是什么都无所谓,只要每个形参之间不重名即可
函数的常见形式
常见的函数样式有4种:
- 无参无返
- 有参无返
- 无参有返
- 有参有反
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
| #include <iostream>
using namespace std;
void test_01() { cout << "无参无返" << endl; }
void test_02(int nums[]) { for (int i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) { cout << nums[i] << " "; } }
bool test_03() { return true; }
string test_04(string s1,string s2,string s3) { return s1 + s2 + s3; }
int main() {
cout << "无参无返调用结果:"; test_01(); cout << "有参无返调用结果:"; int arr[]{ 1,2,3,4,5 }; test_02(arr); cout << endl; cout << "无参有返调用结果:"; bool b1 = test_03(); cout << b1 << endl; cout << "有参有返调用结果:"; string s1 = test_04("你好", "世界", "Hello World"); cout << s1 << endl;
return 0; }
|
函数的声明
作用:告诉编译器函数名称以及如何调用函数。函数的实际主体可以单独定义
1 2 3 4 5 6 7 8 9 10 11 12 13
| int max(int a,int b); int max(int a,int b);
int max(int a,int b) { return a > b ? a : b; }
int main() { cout << max(1,2) << endl; }
|
函数的重载
虽然正常情况下函数定义只能定义一次,但实际上只要形参数量不重复就可以多次定义,当实参数对应到了函数的形参数就调用哪个函数
1 2 3 4 5 6 7 8 9 10 11 12
| int max(int a,int b) { return a > b ? a : b; }
int max(int a,int b,int c) { return max(max(a,b),c); }
int main() { max(1,2); max(1,2,3); }
|
函数的分文件编写
作用:让代码结构更加清晰
函数分文件编写一般有4个步骤
- 创建后缀名为.h的头文件
- 创建后缀名为.cpp的源文件
- 在头文件中写函数的声明
- 在源文件中写函数的定义
示例:
1 2 3 4 5 6
| #include<iostream> using namespace std;
void swap(int a, int b);
|
1 2 3 4 5 6 7 8 9 10 11 12
| #include "swap.h"
void swap(int a, int b) { int temp = a; a = b; b = temp;
cout << "a = " << a << endl; cout << "b = " << b << endl; }
|
1 2 3 4 5 6 7 8 9 10 11 12
| #include "swap.h" int main() {
int a = 100; int b = 200; swap(a, b);
system("pause");
return 0; }
|
指针
指针的作用:可以通过指针间接访问内存
- 内存编号是从0开始记录,一般用十六进制数字表示
- 可以利用指针变量保存地址
指针变量的定义和使用
指针变量定义语法:数据类型 * 变量名
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
| #include <iostream>
using namespace std;
int main() { int a = 10; int* p; p = &a; cout << "a的内存地址为:" << &a << endl; cout << "指针p的值为:" << p << endl; cout << "指针p指向内存地址的具体值为:" << *p << endl;
*p = 255; cout << "*p修改a的值后,a当前的值为:" << a << endl;
return 0; }
|
&表示取值符号
*指针名 = 值表示对指针所指的变量的值进行修改
1 2 3
| int a = 10; int* p = &a; *p = 255;
|
指针所占内存空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <iostream>
using namespace std;
int main() { int a = 10; int* p = &a; cout << sizeof(p) << endl; cout << sizeof(char*) << endl; cout << sizeof(float*) << endl; cout << sizeof(double*) << endl;
return 0; }
|
| 系统架构 |
地址总线宽度 |
指针大小 |
寻址空间 |
| 32位 |
32位 |
4字节 |
4GB(2^32) |
| 64位 |
64位 |
8字节 |
16EB(2^64) |
- 64位系统:指针统一占用 8字节(无论指向何种数据类型)。
- 32位系统:指针统一占用 4字节。
- 原理:指针存储的是内存地址,其大小由 系统寻址能力 决定(64位系统地址总线为64位,需8字节存储)
空指针和野指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
示例:
1 2 3 4 5 6 7 8 9 10 11
| #include <iostream>
using namespace std;
int main() { int* p= NULL; cout << p << endl; cout << *p << endl;
return 0; }
|
野指针:指针变量指向非法的内存空间
示例:
1 2 3 4 5 6 7 8 9 10
| #include <iostream>
using namespace std;
int main() { int* p = (int *)0x1100; cout << *p << endl;
return 0; }
|
const修饰指针
const修饰指针有三种情况:
- const修饰指针
- 称为:常量指针
- 语法:
const int * p = a;
- 特点:指针的指向可以修改,但是指针指向的值不可以该。如
p = &b是可以的,但是*p = 20是错误的
- const修饰常量
- 称为:指针常量
- 语法:
int * const p = a;
- 特点:与常量指针正好相反。
p = &b是错误的,*p = 20是可以的
- const即修饰指针,又修饰常量
- 无特定名称
- 语法:
const int * const p = a;
- 特点:指针的指向、指针指向的值都不可以修改。
*p = 20、p = &b都是错误的
记忆技巧:
- const在
*之前,表示对*进行了限制,当操作*时就是错误的,如*p = 20
- const在
*之后,表示对指针变量进行了限制,当操作指针变量时就是错误的,如p = &b
| 类型 |
术语 |
特性总结 |
const int *p |
指向常量的指针 |
值不可改,地址可改 |
int *const p |
指针常量 |
地址不可改,值可改 |
const 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
| #include <iostream>
using namespace std;
int main() { int a = 10; int b = 20;
const int* p1 = &a; *p1 = 20; p1 = &b;
int* const p2 = &a; *p2 = 20; p2 = &b;
const int* const p3 = &a; *p3 = 20; p3 = &b;
return 0; }
|
指针和数组
作用:利用指针访问数组中元素
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <iostream>
using namespace std;
int main() { int arr[]{ 1,2,3,4,5,6,7,8,9,10 }; int* p = arr;
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { cout << "数组中索引为" << i << "的值是:" << *p << endl; cout << "数组中索引为" << i << "的值的地址是:" << p << endl; p++; }
return 0; }
|
关于p++的详细说明:
| 机制 |
说明 |
| 类型依赖步长 |
指针加减运算根据指向类型自动调整步长(int→4字节,double→8字节) |
| 编译器隐式转换 |
p+1实际执行 p + 1*sizeof(int) |
指针和函数
作用:利用指针作函数参数,可以修改实参的值
示例:
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 45
| #include <iostream>
using namespace std;
void swap_01(int a, int b) { int tmp = a; a = b; b = tmp; }
void swap_02(int* p1, int* p2) { int tmp = *p1; *p1 = *p2; *p2 = tmp; }
void swap_03(int* p1, int* p2) { int* tmp = p1; p1 = p2; p2 = tmp; }
int main() { int a = 10; int b = 20;
swap_01(a, b); cout << "a的值为:" << a << endl; cout << "b的值为:" << b << endl;
swap_02(&a, &b); cout << "a的值为:" << a << endl; cout << "b的值为:" << b << endl;
swap_03(&a, &b); cout << "a的值为:" << a << endl; cout << "b的值为:" << b << endl;
return 0; }
|
指针、函数、数组
案例:利用冒泡排序,编写一个函数对数组进行从小到大的排序
示例:
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
| #include <iostream>
using namespace std;
void coutArr(int arr[],int length) { for (int i = 0; i < length; i++) { cout << arr[i]; } }
void BubbleSort(int arr[], int length) { for (int i = 0; i < length - 1; i++) { for (int j = 0; j < length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } }
int main() {
int arr[]{ 5,2,3,6,9,7,8,1,4 };
int length = sizeof(arr) / sizeof(arr[0]);
BubbleSort(arr, length);
coutArr(arr, length);
return 0; }
|
结构体
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
结构体定义和使用
语法:struct 结构体名 { 结构体成员列表 };
通过结构体创建变量的方式有三种:
struct 结构体名 变量名
struct 结构体名 变量名 = {成员值1, 成员值2...}
- 定义结构体时顺便创建变量
示例:
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 45
| #include <iostream>
using namespace std;
struct Student { string name; int age; int score; string gender; };
int main() { struct Student s1 = { "zhangsan",5,200,"男" };
cout << "学生叫做:" << s1.name << ";学生年龄为:" << s1.age << ";学生的成绩为:" << s1.score << ";学生的性别是:" << s1.gender << endl;
struct Student s2; s2.name = "李四"; s2.age = 8; s2.gender = "男"; s2.score = 180; cout << "学生叫做:" << s2.name << ";学生年龄为:" << s2.age << ";学生的成绩为:" << s2.score << ";学生的性别是:" << s2.gender << endl;
return 0; }
|
注意1:当定义结构体时,struct关键字是不可以被省略的
注意2:创建结构体变量时,如struct Student s1可以省略struct=>Student s1
访问结构体变量的成员时,可以用操作符"."访问成员
结构体数组
作用:将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名[元素个数] = {{},{},...{}}
示例:
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
| #include <iostream> #include <string>
using namespace std;
struct Student { string name; int age; int score; string gender; };
int main() { Student stuArry[] = { {"张三",18,172,"男"}, {"李四",18,178,"女"}, {"王五",17,180,"女"}, {"赵六",17,180,"男"}, };
cout << sizeof(stuArry) / sizeof(stuArry[0]) << endl; cout << size(stuArry) << endl;
for (int i = 0; i < size(stuArry); i++) { stuArry[i].name = stuArry[i].name + to_string(i); cout << "姓名:" << stuArry[i].name << " "; cout << "年龄:" << stuArry[i].age << " "; cout << "分数:" << stuArry[i].score << " "; cout << "性别:" << stuArry[i].gender << " " << endl; }
return 0; }
|
结构体指针
作用:通过指针访问结构体中的成员
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <iostream>
using namespace std;
struct Subject { string name; string level; int point; bool isOpened; };
int main() { Subject s1 = { "英语","高",5,true };
Subject* p = &s1;
cout << p->name << endl;
return 0; }
|
结构体嵌套结构体
当结构体内存在另一个结构体,就称之为结构体嵌套结构体
示例:
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 45 46 47 48
| #include <iostream>
using namespace std;
struct Teacher { string name; int age; string gender; };
struct Student { string name; int age;
struct Subject { string name; string level; int point; bool isOpened; } subject;
struct Teacher teacher; };
int main() { Student s1; s1.age = 18; s1.name = "张三"; s1.subject.level = "中等"; s1.subject.name = "体育"; s1.subject.point = 3; s1.subject.isOpened = false;
s1.teacher = { "老王",42,"男" };
cout << s1.name << "今年" << s1.age << "岁了," << "他/她的班主任是" << s1.teacher.name << ",他/她是一名" << (s1.teacher.age > 35 ? "有经验的" : "年轻的") << s1.teacher.gender << "老师。" << s1.name << "同学喜欢" << s1.subject.name << "这门课,难度属于" << s1.subject.level << "水平,可以获得" << s1.subject.point << "点学分,这门课现在" << (s1.subject.isOpened ? "已经停止开放了" : "已经开放了") << endl;
return 0; }
|
结构体做函数参数
作用:将结构体作为参数向函数中传递
传递方式有两种:
- 值传递
- 地址传递
示例:
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #include <iostream> #include <string> #include <typeinfo>
using namespace std;
struct Student { int id; string name; int age; string province; };
void coutStudent(Student s) { cout << "姓名:" << s.name << " "; cout << "年龄:" << s.age << " "; cout << "学号:" << s.id << " "; cout << "所在省份:" << s.province << endl;
s.name += "值传递"; s.age += 100; s.id += 100000; s.province += "值传递"; }
void coutStudent(Student* s) { cout << "姓名:" << s -> name << " "; cout << "年龄:" << s -> age << " "; cout << "学号:" << s -> id << " "; cout << "所在省份:" << s -> province << endl;
s->name = (s->name) + "地址传递"; s->age = (s->age) + 100; s->id = (s->id) + 100000; s->province = (s->province) + "地址传递"; }
int main() { Student s1 = { 10001,"张三",14,"江苏" };
cout << endl; coutStudent(s1); cout << endl; cout << "值传递函数执行后的结果为:"; cout << "姓名:" << s1.name << " "; cout << "年龄:" << s1.age << " "; cout << "学号:" << s1.id << " "; cout << "所在省份:" << s1.province << endl;
Student* p1 = &s1; cout << endl; coutStudent(p1); cout << endl; cout << "值传递函数执行后的结果为:"; cout << "姓名:" << s1.name << " "; cout << "年龄:" << s1.age << " "; cout << "学号:" << s1.id << " "; cout << "所在省份:" << s1.province << endl;
return 0; }
|
结构体中const使用场景
作用:用const来防止误操作
示例:
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
| #include <iostream> #include <string> #include <typeinfo>
using namespace std;
struct Student { int id; string name; int age; string province; };
void coutStudent(const Student* s) {
cout << "姓名:" << s -> name << " "; cout << "年龄:" << s -> age << " "; cout << "学号:" << s -> id << " "; cout << "所在省份:" << s -> province << endl; }
int main() { Student s1 = { 10001,"张三",14,"江苏" };
Student* p1 = &s1; coutStudent(p1); cout << "值传递函数执行后的结果为:"; cout << "年龄:" << s1.age << " ";
return 0; }
|
结构体案例练习
案例1:
共有两个结构体,分别是学生和老师,老师结构体中有姓名和学生数组(结构体嵌套,一共三个老师,每个老师共5名学生);
学生结构体中有姓名和分数;利用函数将老师和对应的学生进行赋值;最后将所有结构体打印出来:
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include <iostream> #include <string> #include <typeinfo>
using namespace std;
struct Student { string name; int score; };
struct Teacher { string name; Student student[5]; };
void createTeacher(Teacher* t,string tname,Student s[]) { t->name = tname; for (int i = 0; i < size(t->student); i++) { t->student[i] = s[i]; } }
void createStudent(Student* s,string name,int score) { s->name = name; s->score = score; }
int main() { Teacher t[3]; for (int i = 0; i < size(t); i++) { string name; cout << "请输入第" << i + 1 << "个老师的姓名:"; cin >> name; cout << endl; Student s[5]; for (int j = 0; j < size(s); j++) { string stuName; int score; cout << "请输入该老师带领的第" << j + 1 << "个学生的信息:" << endl; cout << "学生姓名:"; cin >> stuName; cout << endl; cout << "学生分数:"; cin >> score; Student* p = &s[j]; createStudent(p, stuName, score); } Teacher* p = &t[i]; createTeacher(p, name, s); }
for (int i = 0; i < size(t); i++) { cout << "第" << i+1 <<"名老师是:" << t[i].name << "老师" << endl;
for (int j = 0; j < size(t[i].student); j++) { cout << "他的第" << j + 1 << "名学生叫:" << t[i].student[j].name << ",他得分是:" << t[i].student[j].score << endl; } }
return 0; }
|
案例2:
设计一个人物的结构体,结构体成员有:姓名、年龄、性别;创建结构体数组,数组中存放5名人物
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果
五名人物的信息如下:
1 2 3 4 5
| {"刘备",23,"男"}, {"关羽",22,"男"}, {"张飞",20,"男"}, {"赵云",21,"男"}, {"貂蝉",19,"女"}
|
示例:
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 <string> #include <typeinfo>
using namespace std;
struct Person { string name; int age; string gender; };
int main() { Person p[] = { {"刘备",23,"男"}, {"关羽",22,"男"}, {"张飞",20,"男"}, {"赵云",21,"男"}, {"貂蝉",19,"女"} };
for (int i = 0; i < size(p) - 1; i++) { for (int j = 0; j < size(p) - 1 - i; j++) { if (p[j].age > p[j + 1].age) { Person tmp = p[j]; p[j] = p[j + 1]; p[j + 1] = tmp; } } }
for (int i = 0; i < size(p); i++) { cout << "第" << i + 1 << "位人物是:" << p[i].name << ",年龄是:" << p[i].age << ",性别是:" << p[i].gender << endl; }
return 0; }
|