01.C++基础语法
C++ 入门
C++ IDE
- CodeBlocks 轻量级
Clion
- Visual Code:Mac 版停止开发了
- Xcode
- VSCode:[[Visual Studio Code配置C++环境]]
- 在线:C++ Shell:cpp.sh
变量常量
变量
语法:数据类型 变量名 = 初始值;
1
int a = 10;
常量
C++ 定义常量两种方式
#define
宏常量:#define 常量名 常量值
- 通常在文件上方定义,表示一个常量
const
修饰的变量const 数据类型 常量名 = 常量值
- 通常在变量定义前加关键字 const,修饰该变量为常量,不可修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1、宏常量
#define day 7
int main() {
cout << "一周里总共有 " << day << " 天" << endl;
//day = 8; //报错,宏常量不可以修改
//2、const修饰变量
const int month = 12;
cout << "一年里总共有 " << month << " 个月份" << endl;
//month = 24; //报错,常量是不可以修改的
system("pause");
return 0;
}
运算符
见:[[C++运算符]]
C++ 关键字
见:[[C++关键字]]
C++ 语句
选择结构
if 语句
if
if else
if else else 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
int main() {
int score = 0;
cout << "请输入考试分数:" << endl;
cin >> score;
if (score > 600)
{
cout << "我考上了一本大学" << endl;
}
else if (score > 500)
{
cout << "我考上了二本大学" << endl;
}
else if (score > 400)
{
cout << "我考上了三本大学" << endl;
}
else
{
cout << "我未考上本科" << endl;
}
system("pause");
return 0;
}
三目运算符
作用: 通过三目运算符实现简单的判断
语法:表达式1 ? 表达式2 :表达式3
,和 Java 一样
解释:
- 如果表达式 1 的值为真,执行表达式 2,并返回表达式 2 的结果;
- 如果表达式 1 的值为假,执行表达式 3,并返回表达式 3 的结果。
格式:
1
2
条件表达式 ? 表达式1 : 表达式2;
// 语义:如果“条件表达式”为true,则整个表达式的值就是表达式1,忽略表达式2;如果“条件表达式”为false,则整个表达式的值就是表达式2,等价于if/else语句。
switch 语句
1
2
3
4
5
6
7
switch(表达式)
{
case 结果1:执行语句;break;
case 结果2:执行语句;break;
// ...
default:执行语句;break;
}
循环语句
基本循环语句
for
while
1
2
3
4
5
6
7
8
9
10
11
12
13
int main() {
int num = 0;
while (num < 10)
{
cout << "num = " << num << endl;
num++;
}
system("pause");
return 0;
}
do while
1
2
3
4
5
6
7
8
9
10
11
12
13
int main() {
int num = 0;
while (num < 10)
{
cout << "num = " << num << endl;
num++;
}
system("pause");
return 0;
}
与 while
循环区别在于,do…while
先执行一次循环语句,再判断循环条件
范围 for 循环(C++ 11)range-based for loop
定义: 范围 for 循环,是 C++11 的一个语法糖。特点:
- 它有两个参数,一个是自己创建的变量,另一个是一个容器。
- 范围 for 循环可以将一个容器 (第二个参数) 里的元素依次传第一个参数,并在该循环体中依次对每一个元素做操作。
- 如果你不想影响容器中的参数,请pass by value,否则请pass by reference。
语法:
1
2
3
for (declaration : expression) {
// 循环体
}
declaration
:用于循环遍历的局部变量的声明。expression
:一个序列表达式,比如一个数组、向量或其他任何带有begin()
和end()
成员函数的容器。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// by value
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int num : numbers) { // 每次迭代,变量 num 将被初始化为 numbers 容器中的下一个元素的副本。
std::cout << num << std::endl;
}
return 0;
}
// by reference
for (int &num : numbers) {
num *= 2; // 将每个元素乘以2
}
跳转语句
break
作用: 用于跳出==选择结构==或者==循环结构==
break 使用的时机:
- 出现在 switch 条件语句中,作用是终止 case 并跳出 switch
- 出现在循环语句中,作用是跳出当前的循环语句
- 出现在嵌套循环中,跳出最近的内层循环语句
示例 1:在 switch 语句中使用 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
25
26
27
28
int main() {
//1、在switch 语句中使用break
cout << "请选择您挑战副本的难度:" << endl;
cout << "1、普通" << endl;
cout << "2、中等" << endl;
cout << "3、困难" << endl;
int num = 0;
cin >> num;
switch (num)
{
case 1:
cout << "您选择的是普通难度" << endl;
break;
case 2:
cout << "您选择的是中等难度" << endl;
break;
case 3:
cout << "您选择的是困难难度" << endl;
break;
}
system("pause");
return 0;
}
示例 2:在循环语句中用 break
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main() {
//2、在循环语句中用break
for (int i = 0; i < 10; i++)
{
if (i == 5)
{
break; //跳出循环语句
}
cout << i << endl;
}
system("pause");
return 0;
}
示例 3:在嵌套循环语句中使用 break,退出内层循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main() {
//在嵌套循环语句中使用break,退出内层循环
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (j == 5)
{
break;
}
cout << "*" << " ";
}
cout << endl;
}
system("pause");
return 0;
}
continue
作用: 在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main() {
for (int i = 0; i < 100; i++)
{
if (i % 2 == 0)
{
continue;
}
cout << i << endl;
}
system("pause");
return 0;
}
goto
作用: 可以无条件跳转语句
语法: goto 标记;
解释: 如果标记的名称存在,执行到 goto 语句时,会跳转到标记的位置
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() {
cout << "1" << endl;
goto FLAG;
cout << "2" << endl;
cout << "3" << endl;
cout << "4" << endl;
FLAG:
cout << "5" << endl;
system("pause");
return 0;
}
注意:在程序中不建议使用 goto 语句,以免造成程序流程混乱
C++ 数据类型
C++ 规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存。
- 有符号,最高一位是符号位
short
、int
、long
、long int
、float
、double
、bool
- 无符号位,都是正数
这些类型前面加上 unsigned
整型 int
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) |
布尔类型 bool
作用: 布尔数据类型代表真或假的值
bool 类型只有两个值:
true
— 真(本质是 1)false
— 假(本质是 0)
bool 类型占 1 个字节大小
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
int main() {
bool flag = true;
cout << flag << endl; // 1
flag = false;
cout << flag << endl; // 0
cout << "size of bool = " << sizeof(bool) << endl; //1
system("pause");
return 0;
}
浮点型 float/double
作用:用于表示小数
浮点型变量分为两种:
- 单精度
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
21
22
int main() {
float f1 = 3.14f;
double d1 = 3.14;
cout << f1 << endl;
cout << d1<< endl;
cout << "float sizeof = " << sizeof(f1) << endl;
cout << "double sizeof = " << sizeof(d1) << endl;
//科学计数法
float f2 = 3e2; // 3 * 10 ^ 2
cout << "f2 = " << f2 << endl;
float f3 = 3e-2; // 3 * 0.1 ^ 2
cout << "f3 = " << f3 << endl;
system("pause");
return 0;
}
字符型 char
作用: 字符型变量用于显示单个字符
语法: char ch = 'a';
- C 和 C++ 中字符型变量只占用 1 个字节。
- 字符型变量并不是把字符本身放到内存中存储,而是将对应的
ASCII编码
放入到存储单元
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main() {
char ch = 'a';
cout << ch << endl;
cout << sizeof(char) << endl;
//ch = "abcde"; //错误,不可以用双引号
//ch = 'abcde'; //错误,单引号内只能引用一个字符
cout << (int)ch << endl; //查看字符a对应的ASCII码
ch = 97; //可以直接用ASCII给字符型变量赋值
cout << ch << endl;
system("pause");
return 0;
}
ASCII 码
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 范围 0 | 3 位 16 进制 |
示例:
1
2
3
4
5
6
7
int main() {
cout << "\\" << endl;
cout << "\tHello" << endl;
cout << "\n" << endl;
system("pause");
return 0;
}
字符串
见: [[04.C++字符串]]
sizeof 关键字
作用: 利用 sizeof
关键字可以统计数据类型所占内存大小
语法: sizeof(数据类型 或 变量)
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main() {
cout << "short 类型所占内存空间为: " << sizeof(short) << endl;
cout << "int 类型所占内存空间为: " << sizeof(int) << endl;
cout << "long 类型所占内存空间为: " << sizeof(long) << endl;
cout << "long long 类型所占内存空间为: " << sizeof(long long) << endl;
system("pause");
return 0;
}
C++ 的 auto 关键字(C++ 11)
auto
关键字在 C++ 中是一个类型说明符,用于让编译器自动推断变量的类型。它最早在 C++11 标准中引入,旨在简化代码,使之更加易读,并使得代码维护过程中,更新类型声明变得更加容易。- 当你在声明变量时使用
auto
关键字,你不需要显式指定变量的类型,编译器会根据变量的初始化表达式来自动推断变量的类型。 - 在使用
auto
关键字时,必须立即初始化变量,因为编译器需要初始化表达式来推断类型。
以下是几个 auto 关键字的用例:
1
2
3
4
5
6
auto x = 42; // x 被推断为 int
auto y = 3.14; // y 被推断为 double
auto z = x; // z 被推断为 int
std::vector<int> vec = {1, 2, 3, 4};
auto it = vec.begin(); // it 的类型是 std::vector<int>::iterator
auto 使用建议:如果不是下面两种应用场景,请尽量不要使用 auto,能不用,就不用。
- 在使用
iterator
的时候
1
2
3
4
5
6
7
8
9
10
11
12
std::vector<std::string> strings;
strings.push_back("Apple");
strings.push_back("Orange");
for (std::vector<std::string>::iterator it = strings.begin(); // 不使用auto
it != strings.end(); it++)
{
std::cout << *it << std::endl;
}
for (auto it = strings.begin(); it != strings.end(); it++) // 使用auto后简化代码
{
std::cout << *it << std::endl;
}
- 当类型名过长的时候可以使用
auto
: 如lambda
,长的指针类型
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>
#include <string>
#include <vector>
#include <unordered_map>
class Device{};
class DeviceManager
{
private:
std::unordered_map<std::string, std::vector<Device *>> m_Devices;
public:
const std::unordered_map<std::string, std::vector<Device *>> &GetDevices() const
{
return m_Devices;
}
};
int main()
{
DeviceManager dm;
const std::unordered_map<std::string, std::vector<Device *>> &devices = dm.GetDevices();//不使用auto
const auto& devices = dm.GetDevices(); //使用auto
std::cin.get();
}
除此之外类型名过长的时候也可以使用 using
或 typedef
方法:
1
2
3
4
using DeviceMap = std::unordered_map<std::string, std::vector<Device*>>;
typedef std::unordered_map<std::string, std::vector<Device*>> DeviceMap;
const DeviceMap& devices = dm.GetDevices();
C++ 类型双关 type punning
- 将同一块内存的东西通过不同 type 的指针给取出来
示例:把一个 int 型的内存,换成 double 去解释,当然这样做很糟糕,因为添加了四字节不属于原本自己的内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
int main()
{
int a = 50;
double value = *(double*)&a;
std::cout << value << std::endl;
std::cin.get();
}
// 可以用引用,这样就可以避免拷贝成一个新的变量:(只是演示,这样做很糟糕)
#include <iostream>
int main()
{
int a = 50;
double& value = *(double*)&a;
std::cout << value << std::endl;
std::cin.get();
}
示例 2:把一个结构体转换成数组进行操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
struct Entity
{
int x, y;
};
int main()
{
Entity e = {5, 8};
int *position = (int *)&e; // 1
std::cout << position[0] << ", " << position[1] << std::endl;
int y = *(int *)((char *)&e + 4); // 2
std::cout << y << std::endl;
}
解释:
上面的 struct 有 2 int 的字段 x 和 y,
(int *)&e
:取e
地址,强转换为int*
指针,struct 中的字段按它们在定义中的顺序依次排列在内存中,因此 x 会首先被分配空间,紧接着是 y,所以int*
指针代表的就是 struct Entity 在内存中的起始位置,由于是 2 个 int 值,所以指针position[0]
和position[1]
分别访问的是 x 和 y。e
地址转换成char*
指针,加 4 表示定位到到了 y 的位置,然后转换为int*
指针,最后取指针操作,就能把 y 的值取出来了
C++ 函数
见:[[02.C++函数]]