课程链接:https://www.bilibili.com/video/BV1et411b73Z
#include
using namespace std;int main() {cout << "Hello World" << endl;system("pause");return 0;
}
作用:在代码中加一些说明和解释,方便自己或其他程序员阅读代码
CPP的注释有两种格式:
// 描述信息
/* 描述信息 */
Note: 编译器在编译代码时,会忽略注释的内容
#include
using namespace std;/*main是一个程序的入口,每个程序都必须有这么一个函数,有且仅有一个
*/
int main() {// 在屏幕中输出Hello Worldcout << "Hello World" << endl;system("pause");return 0;
}
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名 = 初始值;
示例:
#include
using namespace std;int main() {// 变量创建的语法:数据类型 变量名 = 变量初始值int a = 10;cout << "a = " << a << endl; // a = 10system("pause");return 0;
}
作用:用于记录程序中不可更改的数据
C++定义常量的两种方式:
#define 常量名 常量值
const 数据类型 常量名 = 常量值
const
,修饰该变量为常量,不可修改const: 英['kɒnst] 美['kɑnst]
adj. 恒定的; 不变的;
n. 常数; 恒量;
示例:
#include
using namespace std;/*
常量的定义方式1. #define 宏常量 -> #define 常量名 常量值2. const修饰的变量 -> const 数据类型 常量名 = 常量值
*/#define Day 7int main() {cout << "一周总共有: " << Day << " 天" << endl; // 一周总共有: 7 天const int month = 12; // const修饰的变量也称为常量cout << "一年总共有: " << month << " 个月份" << endl; // 一年总共有: 12 个月份system("pause");return 0;
}
作用:关键字是C++中预先保留的单词(标识符)
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 |
Note:在给变量或常量起名时,不要使用CPP的关键字,否则会产生歧义。
示例:
#include
using namespace std;int main() {// 创建变量时变量名使用关键字int true = 10; // 不能使用关键字作为变量名,会报错!system("pause");return 0;
}
作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则:
建议:给标识符命名时,争取做到见名知意的效果,方便自己和他人阅读
#include using namespace std;/*1. 标识符不能是关键字2. 标识符只能由字母、数字、下划线组成3. 第一个字符必须为字母或下划线(不能以数字开头)4. 标识符中字母区分大小写
*/
int main() {// 1. 标识符不能是关键字// int int = 10; // 错误// 2. 标识符只能由字母、数字、下划线组成int abc = 10;int _abc = 20;int _123abc = 30;// 3. 第一个字符必须为字母或下划线(不能以数字开头)// int 123abc = 40; // 错误// 4. 标识符中字母区分大小写int aaa = 100;int AAA = 300;cout << aaa << endl; // 100cout << AAA << endl; // 300system("pause");return 0;
}
C++规定在创建一个变量或常量时,必须要指定出相应的数据类型,否则无法给变量分配内存。
数据类型存在的意义是给变量分配合适的内存空间。
作用:整型变量表示的是整数类型的数据。C++中能够表示整型的类型有以下几种方式,区别在于所占用的空间不同:
数据类型 | 占用空间 | 取值范围 |
---|---|---|
short (短整型) | 2字节 | (−215∼215−1)(-2^{15} \sim 2^{15} - 1)(−215∼215−1) ⇔\Leftrightarrow⇔ (−32,768∼32,767)(-32,768 \sim 32,767)(−32,768∼32,767) |
int (整型) | 4字节 | (−231∼231−1)(-2^{31} \sim 2^{31} - 1)(−231∼231−1) ⇔\Leftrightarrow⇔ (−2,147,483,648∼2,147,483,647)(-2,147,483,648 \sim 2,147,483,647)(−2,147,483,648∼2,147,483,647) |
long (长整型) | Windows为4字节,Linux为4字节(32位),8字节(64位) | (−231∼231−1)(-2^{31} \sim 2^{31} - 1)(−231∼231−1) ⇔\Leftrightarrow⇔ (−2,147,483,648∼2,147,483,647)(-2,147,483,648 \sim 2,147,483,647)(−2,147,483,648∼2,147,483,647) |
long long (长长整型) | 8字节 | (−263∼263−1)(-2^{63} \sim 2^{63} - 1)(−263∼263−1) ⇔\Leftrightarrow⇔ (−9,223,372,036,854,775,808∼9,223,372,036,854,775,807)(-9,223,372,036,854,775,808 \sim 9,223,372,036,854,775,807)(−9,223,372,036,854,775,808∼9,223,372,036,854,775,807) |
在日常开发中,
int
是最常用的。
#include
using namespace std;/*整型:1. 短整型 short2. 整型 int3. 长整型 long4. 长长整型 long long
*/
int main() {// 1. 短整型 short (−32,768 ~ 32,767)short num1 = 10;// 2. 整型 int (−2,147,483,648 ~ 2,147,483,647)int num2 = 10;// 3. 长整型 long (−2,147,483,648 ~ 2,147,483,647)long num3 = 10;// 4. 长长整型 long long ((−9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807))long long num4 = 10; cout << "num1: " << num1 << endl; // num1: 10cout << "num2: " << num2 << endl; // num2: 10cout << "num3: " << num3 << endl; // num3: 10cout << "num4: " << num4 << endl; // num4: 10cout << "-------------------" << endl;/*探讨越界的情况:当出现超过表示范围的数时,会自动轮到开头*/// 1. 短整型 short (−32768~32767)short ol_num1 = 32768;cout << "ol_num1: " << ol_num1 << endl; // ol_num1: -32768// 2. 整型 int (−2,147,483,648 ~ 2,147,483,647)int ol_num2 = 2147483648;cout << "ol_num2: " << ol_num2 << endl; // ol_num2: -2147483648// 3. 长整型 long (−2,147,483,648 ~ 2,147,483,647)long ol_num3 = 2147483648;cout << "ol_num3: " << ol_num3 << endl; // ol_num3: -2147483648// 4. 长长整型 long long ((−9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807))long long ol_num4 = 9223372036854775808;cout << "ol_num4: " << ol_num4 << endl; // ol_num4: -9223372036854775808system("pause");return 0;
}
作用:利用sizeof
关键字可以统计数据类型所占内存的大小。
语法:sizeof(数据类型 / 变量)
示例:
#include
using namespace std;int main() {/*使用sizeof求出数据类型/变量所占的内存大小*/short num1 = 10;cout << "short占用的内存空间为: " << sizeof(short) << endl; // short占用的内存空间为: 2cout << "num1变量对应的数据类型所占用的内存空间为: " << sizeof(num1) << endl; // num1变量对应的数据类型所占用的内存空间为: 2int num2 = 10;cout << "int占用的内存空间为: " << sizeof(int) << endl; // int占用的内存空间为: 4long num3 = 10;cout << "long占用的内存空间为: " << sizeof(long) << endl; // long占用的内存空间为: 4long long num4 = 10;cout << "long long占用的内存空间为: " << sizeof(long long) << endl; // long long占用的内存空间为: 8system("pause");return 0;
}
作用:用于表示小数。
浮点型变量分为两种:
float
double
两者的区别在于表示的有效数字范围不同。
数据类型 | 占用空间 | 有效数字范围 |
---|---|---|
float | 4字节 | 7位有效数字 |
double | 8字节 | 15~16位有效数字 |
有效数字包含小数点前面和后面的!
需要注意的是,在写float
类型时,数字后面加上一个f
,例如:
float num = 3.14f;
因为如果不加f
,那么编译器看到小数会默认它为double
,还需要将double
转为为float
,这样会多一步。
示例:
#include
using namespace std;int main() {// 1. 单精度 float// 2. 双精度 doublefloat f1 = 3.1415126f; // 一般会在后面写一个f// endl = end linecout << "f1: " << f1 << endl; // f1: 3.14151double d1 = 3.1415126;cout << "d1: " << d1 << endl; // d1: 3.14151// 统计float和double占用的内存空间cout << "float占用的内存空间: " << sizeof(float) << "字节" << endl; // float占用的内存空间: 4字节cout << "double占用的内存空间: " << sizeof(double) << "字节" << endl; // double占用的内存空间: 8字节// 科学计数法float f2 = 3e2f; // 3 * 10^2double d2 = 3e-2; // 3 * 10^-2cout << "f2: " << f2 << endl; // f2: 300cout << "d2: " << d2 << endl; // d2: 0.03system("pause");return 0;
}
默认情况下,CPP显示一个小数最多显示6位小数。
作用:字符型变量用于显示单个字符
语法:char ch = 'a';
注意:
字节字节,就是一个英文单词所占用的大小,所以对于
char
,在空间中就是占一个字节。
需要记忆的ASCII码值:
a
: 97A
: 65示例:
#include
using namespace std;int main() {// 1. 字符型变量的创建方式char ch = 'a';cout << "ch: " << ch << endl; // ch: a// 2. 字符型变量所占用内存大小cout << "char所占的内存大小: " << sizeof(char) << "字节" << endl; // char所占的内存大小: 1字节// 3. 字符型变量常见错误// char ch2 = "a"; // 不能用双引号创建字符// char ch3 = 'abcdef'; // 不能用单引号创建字符串// 4. 字符型变量对应的ASCII编码// (数据类型)变量: 将变量强转为指定的数据类型cout << (int)ch << endl; // 97cout << (int)'A' << endl; // 65system("pause");return 0;
}
ASCII值(十进制) | 控制字符 | 解释 | ASCII值(十进制) | 控制字符 | 解释 | ASCII值(十进制) | 控制字符 | 解释 | ASCII值(十进制) | 控制字符 | 解释 |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | NUT (null) | 空字符 | 32 | (space) | 空格 | 64 | @ | 电子邮件符号 | 96 | ` | 开单引号 |
1 | SOH (start of headline) | 标题开始 | 33 | ! | 叹号 | 65 | A | 大写字母A | 97 | a | 小写字母 |
2 | STX (start of text) | 正文开始 | 34 | " | 双引号 | 66 | B | 大写字母B | 98 | b | 小写字母b |
3 | ETX (end of text) | 正文结束 | 35 | # | 井号 | 67 | C | 大写字母C | 99 | c | 小写字母c |
4 | EOT (end of transmission) | 传输结束 | 36 | $ | 美元符号 | 68 | D | 大写字母D | 100 | d | 小写字母d |
5 | ENQ (enquiry) | 请求 | 37 | % | 百分号 | 69 | E | 大写字母E | 101 | e | 小写字母e |
6 | ACK (acknowledge) | 收到通知 | 38 | & | 和号 | 70 | F | 大写字母F | 102 | f | 小写字母f |
7 | BEL (bell) | 响铃 | 39 | ’ | 闭单引号 | 71 | G | 大写字母G | 103 | g | 小写字母g |
8 | BS (backspace) | 退格 | 40 | ( | 开括号 | 72 | H | 大写字母H | 104 | h | 小写字母h |
9 | HT (horizontal tab) | 水平制表符 | 41 | ) | 闭括号 | 73 | I | 大写字母I | 105 | i | 小写字母i |
10 | LF (NL line feed, new line) | 换行键 | 42 | * | 星号 | 74 | J | 大写字母J | 106 | j | 小写字母j |
11 | VT (vertical tab) | 垂直制表符 | 43 | + | 加号 | 75 | K | 大写字母K | 107 | k | 小写字母k |
12 | FF (NP form feed, new page) | 换页键 | 44 | , | 逗号 | 76 | L | 大写字母L | 108 | l | 小写字母l |
13 | CR (carriage return) | 回车键 | 45 | - | 减号/破折号 | 77 | M | 大写字母M | 109 | m | 小写字母m |
14 | SO (shift out) | 不用切换 | 46 | . | 句号/点 | 78 | N | 大写字母N | 110 | n | 小写字母n |
15 | SI (shift in) | 启用切换 | 47 | / | 斜杠 | 79 | O | 大写字母O | 111 | o | 小写字母o |
16 | DLE (data link escape) | 数据链路转义 | 48 | 0 | 数字0 | 80 | P | 大写字母P | 112 | p | 小写字母p |
17 | DC1 (device control 1) | 设备控制1 | 49 | 1 | 数字1 | 81 | Q | 大写字母Q | 113 | q | 小写字母q |
18 | DC2 (device control 2) | 设备控制2 | 50 | 2 | 数字2 | 82 | R | 大写字母R | 114 | r | 小写字母r |
19 | DC3 (device control 3) | 设备控制3 | 51 | 3 | 数字3 | 83 | S | 大写字母S | 115 | s | 小写字母s |
20 | DC4 (device control 4) | 设备控制4 | 52 | 4 | 数字4 | 84 | T | 大写字母T | 116 | t | 小写字母t |
21 | NAK (negative acknowledge) | 拒绝接收 | 53 | 5 | 数字5 | 85 | U | 大写字母U | 117 | u | 小写字母u |
22 | SYN (synchronous idle) | 同步空闲 | 54 | 6 | 数字6 | 86 | V | 大写字母V | 118 | v | 小写字母v |
23 | ETB (end of trans. block) | 结束传输块 | 55 | 7 | 数字7 | 87 | W | 大写字母W | 119 | w | 小写字母w |
24 | CAN (cancel) | 取消 | 56 | 8 | 数字8 | 88 | X | 大写字母X | 120 | x | 小写字母x |
25 | EM (end of medium) | 媒介结束 | 57 | 9 | 数字9 | 89 | Y | 大写字母Y | 121 | y | 小写字母y |
26 | SUB (substitute) | 代替 | 58 | : | 冒号 | 90 | Z | 大写字母Z | 122 | z | 小写字母z |
27 | ESC (escape) | 换码(溢出) | 59 | ; | 分号 | 91 | [ | 开方括号 | 123 | { | 开花括号 |
28 | FS (file separator) | 文件分隔符 | 60 | < | 小于 | 92 | \ | 反斜杠 | 124 | ` | ` |
29 | GS (group separator) | 分组符 | 61 | = | 等号 | 93 | ] | 闭方括号 | 125 | } | 闭花括号 |
30 | RS (record separator) | 记录分隔符 | 62 | > | 大于 | 94 | ^ | 脱字符 | 126 | ~ | 波浪号 |
31 | US (unit separator) | 单元分隔符 | 63 | ? | 问号 | 95 | _ | 下划线 | 127 | DEL (delete) | 删除 |
ASCII码大致由以下两部分组成:
0 ~ 31
分配给了控制字符,用于控制像打印机等一些外围设备。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 | |
\0 | 代表一个问号 | 000 | |
\ddd | 8进制转义字符, d范围0~7 | 3位8进制 | |
\xhh | 16进制转义字符, h范围0~9, a~f, A~F | 3位16进制 |
注意:
\r
表示将当前的光标移动到行首,但不会移动到下一行;\n
表示将光标移动到下一行,但不会移动到行首。单独一个\r
或\n
都不是一般意义上的回车,\r\n
放在一起才是。通常在写程序的时候只要一个\n
就可以了,这是因为编译器会自动将\n
替换成\r\n
。
示例:
#include
using namespace std;int main() {// 1. 换行符 \ncout << "hello wolrd";/*hello wolrd请按任意键继续. . .*/cout << "hello wolrd\n";/*hello wolrd请按任意键继续. . .*/// 2. 反斜杠 \\ cout << "\\" << endl; // \
// 3. 水平制表符 \t 可以整齐地输出数据cout << "aaa\thello world" << endl;/*aaa hello world请按任意键继续. . .*/cout << "a\thello world" << endl;cout << "ab\thello world" << endl;cout << "abc\thello world" << endl;cout << "abcd\thello world" << endl;/*a hello worldab hello worldabc hello worldabcd hello world请按任意键继续. . .*/// 4. 回车 \rcout << "abc\rdefg" << endl; // defg(回车会让光标回到行首,因此defg覆盖掉了abc)cout << "123\r\n"; // \r\n表示开始下一行并回到行首/*\r表示将当前的光标移动到行首,但不会移动到下一行;\n表示将光标移动到下一行,但不会移动到行首。单独一个\r或\n都不是一般意义上的回车,\r\n放在一起才是。通常在写程序的时候只要一个\n就可以了,这是因为编译器会自动将\n替换成\r\n。*/system("pause");return 0;
}
作用:用于表示一串字符。
两种风格:
char 变量名[] = "字符串值";
-> char str1[] = "Hello World";
string 变量名 = "字符串值";
注意:
#include
示例:
#include
using namespace std;
#include int main() {// 1. C风格字符串char str_c[] = "Hello World";cout << str_c << endl; // Hello World// 2. C++风格字符串(使用的时候需要引入string头文件)string str_cpp = "Hello World";cout << str_cpp << endl; // Hello World// 看一下两种字符串占空间的大小cout << "C大小: " << sizeof(str_c) << "字节" << endl; // C大小: 12字节cout << "C++大小: " << sizeof(string) << "字节" << endl; // C++大小: 40字节system("pause");return 0;
}
作用:布尔数据类型表示真或假的值
bool类型只有两个值:
true
: 真 (本质是1)false
: 假 (本质是0)bool类型占1个字节大小(因为本质上是数字1/0)
语法:bool 变量名 = true/false;
示例:
#include ,
using namespace std;int main() {// 1. 创建bool数据类型bool flag_1 = true;bool flag_2 = false;cout << flag_1 << endl; // 1cout << flag_2 << endl; // 0// 2. 查看bool数据类型占用空间大小cout << "bool数据类型占 " << sizeof(bool) << " 字节" << endl; // bool数据类型占 1 字节system("pause");return 0;
}
作用:用于从键盘获取数据
关键字:cin
语法:cin >> 变量
示例:
#include
#include
using namespace std;int main() {// 1. 整型int a = 0;cout << "请给整型变量a赋值: " << endl;cin >> a; // 请给整型变量a赋值:cout << "整型变量a = " << a << endl; // 整型变量a = 100// 2. 浮点型float f = 3.14f;cout << "请给浮点型变量f赋值: " << endl;cin >> f; // 请给浮点型变量f赋值:cout << "浮点型变量f = " << f << endl; // 浮点型变量f = 7.77// 3. 字符型char ch = 'a';cout << "请给字符型变量ch赋值: " << endl;cin >> ch; // 请给字符型变量ch赋值:cout << "字符型变量ch = " << ch << endl; // 字符型变量ch = b// 4. 字符串型string str = "None";cout << "请给字符串型变量str赋值: " << endl;cin >> str;cout << "字符串型变量str = " << str << endl; // 字符串型变量str = "Hello"// 5. boolbool flag = false;cout << "请给bool型变量flag赋值: " << endl;cin >> flag; // bool类型只要是非0的值都代表真cout << "bool型变量flag = " << flag << endl; // bool型变量bool = "1"/*请给整型变量a赋值:100整型变量a = 100请给浮点型变量f赋值:3.3浮点型变量f = 3.3请给字符型变量ch赋值:b字符型变量ch = b请给字符串型变量str赋值:Hello字符串型变量str = Hello请给bool型变量flag赋值:1bool型变量flag = 1*/system("pause");return 0;
}
作用:用于执行代码的运算。
本章主要讲以下几类运算符:
运算符类型 | 作用 |
---|---|
算术运算符 | 用于处理四则运算 |
赋值运算符 | 用于将表达式的值赋给变量 |
比较运算符 | 用于表达式的比较,并返回一个真值或假值 |
逻辑运算符 | 用于根据表达式的值返回真值或假值 |
作用:用于处理四则运算。
算术运算符包含以下符号:
运算符 | 术语 | 示例 | 结果 | 注意 |
---|---|---|---|---|
+ | 正号 | +3 | 3 | |
- | 负号 | -3 | -3 | |
+ | 加 | 10+5 | 15 | |
- | 减 | 10-5 | 5 | |
* | 乘 | 10*5 | 50 | |
/ | 除 | 10/5 | 2 | 除数不能是0 |
% | 取模(取余数) | 10%3 | 1 | 必须是两个整数, 除数不能是0 |
++ | 前置递增 | 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; |
取余操作的本质就是除法
#include
using namespace std;int main() {// 1. 加减乘除int a1 = 10;int b1 = 3;/*因为a和b都是int,因此两个整数做除法仍然是int*/cout << a1 + b1 << endl; // 13cout << a1 - b1 << endl; // 7cout << a1 * b1 << endl; // 30cout << a1 / b1 << endl; // 3int a2 = 10;int b2 = 20;cout << a2 / b2 << endl; // 0int a3 = 10;int b3 = 0;// cout << a3 / b3 << endl; // 0 // Integer division by zero。// 两个小数相除double d1 = 0.5;double d2 = 0.22;cout << d1 / d2 << endl; // 2.27273// 整数和小数相除int a4 = 2;double d3 = 3.14;cout << a4 / d3 << endl; // 0.636943// 两个不同数据类型的小数相除float f1 = 3.14f;float d4 = 7.11;cout << f1 / d4 << endl; // 0.441632// 2. 取模(取余)int aa1 = 10;int aa2 = 3;cout << aa1 % aa2 << endl; // 1cout << aa2 % aa1 << endl; // 3// 两个小数是不可以取余float ff1 = 3.14f;float ff2 = 1.01f;// cout << ff1 % ff2 << endl; // 表达式必须具有整数或未区分范围的枚举类型(取余操作必须是整数!)// 取余操作的除数不能是0,被除数可以是0且结果恒等于0int aaa1 = 0;int aaa2 = 3;cout << aaa1 % aaa2 << endl; // 0// cout << aaa2 % aaa1 << endl; // Integer division by zero// 3. 前置递增、后置递增、前置递减、后置递减// 3.1 前置递增: 先让变量+1,然后进行表达式运算int a = 10;++a; // 让变量+1cout << "a = " << a << endl; // 11// 3.2 后置递增: 先进行表达式运算,再让变量+1int b = 10;b++;cout << "b = " << b << endl; // 11// 前置和后置的区别a = 10;b = ++a * 10;cout << "a = " << a << endl; // a = 11cout << "b = " << b << endl; // b = 110a = 10;b = a++ * 10;cout << "a = " << a << endl; // a = 11cout << "b = " << b << endl; // b = 100// 3.3 前置递减a = 10;--a;cout << "a = " << a << endl; // 9// 3.4 后置递减b = 10;b--;cout << "b = " << b << endl; // 9// 前置和后置的区别a = 10;b = --a * 10;cout << "a = " << a << endl; // a = 9cout << "b = " << b << endl; // b = 90a = 10;b = a-- * 10;cout << "a = " << a << endl; // a = 9cout << "b = " << b << endl; // b = 100system("pause");return 0;
}
作用:用于将表达式的值赋给变量。
赋值运算符包括以下几个符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
= | 赋值 | a=2; b=3; | a=2; b=3; |
+= | 加等于 | a=0; a+=2; | a=2; |
-= | 减等于 | a=0; a-=2; | a=-2; |
*= | 乘等于 | a=2; a*=3; | a=6; |
/= | 除等于 | a=6; a/=3; | a=2; |
%= | 模等于 | a=6; a%=4; | a=2; |
#include
using namespace std;int main() {// =int a = 10;cout << "a = " << a << endl; // a = 10a = 20;cout << "a = " << a << endl; // a = 20// +=a = 10;a += 2; // a = a + 2cout << "a = " << a << endl; // a = 12// -=a = 10;a -= 2;cout << "a = " << a << endl; // a = 8// *=a = 10;a *= 2;cout << "a = " << a << endl; // a = 20// /=a = 10;a /= 2;cout << "a = " << a << endl; // a = 5// %=a = 10;a %= 2;cout << "a = " << a << endl; // a = 0system("pause");return 0;
}
作用:用于表达式的比较,并返回一个真值或假值。
比较运算符有以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
== | 相等于 | 4==3 | 0 |
!= | 不等于 | 4!=3 | 1 |
< | 小于 | 4<3 | 0 |
> | 大于 | 4>3 | 1 |
<= | 小于等于 | 4<=3 | 0 |
>= | 大于等于 | 4>=3 | 1 |
#include
using namespace std;int main() {int a = 10;int b = 20;// ==cout << (a == b) << endl; // 0// !=cout << (a != b) << endl; // 1// >cout << (a > b) << endl; // 0// =cout << (a >= b) << endl; // 0// <=cout << (a <= b) << endl; // 1system("pause");return 0;
}
作用:用于根据表达式的值返回真值或假值
逻辑运算符有以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
! | 非 | !a | 如果a为假,则!a为真;如果a为真,则!a为假 |
&& | 与 | a && b | 如果a和b都为真,则结果为真,否则为假 |
|| | 与 | a || b | 如果a或b有一个为真,则结果为真 |
#include
using namespace std;int main() {// 逻辑非 !int a = 10;cout << "!a: " << !a << endl; // !a: 0cout << "!!a: " << !!a << endl; // !!a: 1// 逻辑与 &&int b = 20;cout << "a && b: " << (a && b) << endl; // a && b: 1bool c = false;cout << "b && c: " << (b && c) << endl; // b && c: 0int d = 0;cout << "c && d: " << (c && d) << endl; // c && d: 0// 逻辑或 ||cout << "a || b: " << (a || b) << endl; // a || b: 1cout << "b || c: " << (b || c) << endl; // b || c: 1cout << "c || d: " << (c || d) << endl; // c || d: 0system("pause");return 0;
}
C/C++支持最基本的三种程序执行结构:顺序结构、选择结构、循环结构:
作用:执行满足条件的语句
if语句的三种形式:
if(条件){满足条件时执行的语句}
if(条件){满足条件时执行的语句}else{不满足条件时执行的语句}
if(条件){条件1满足时执行的语句}else if(条件2){条件2满足时执行的语句}... else{所有条件都不满足时执行的语句}
补充:嵌套if语句:在if语句中,可以嵌套使用if语句,达到更精确的条件判断。
示例:
#include
using namespace std;int main() {// 用户输入分数,如果分数大于600,视为考上一本大学,在屏幕上输出int score = 0;cout << "请输入分数: ";cin >> score;cout << "输入的分数为: " << score << "\r\n" << endl;// 1. 单行格式if语句:if(条件){满足条件时执行的语句}cout << "---------1. 单行格式if语句---------" << endl;if (score >= 600) {cout << "恭喜您考上了一本大学!" << endl;}// 2. 多行格式if语句:if(条件){满足条件时执行的语句}else{不满足条件时执行的语句}cout << "\r\n---------2. 多行格式if语句---------" << endl;if (score >= 600) {cout << "恭喜您考上了一本大学!" << endl;}else{cout << "很可惜,您没考上一本大学" << endl;}// 3. 多条件的if语句:if(条件){条件1满足时执行的语句}else if(条件2){条件2满足时执行的语句}... else{所有条件都不满足时执行的语句}cout << "\r\n---------3. 多条件的if语句---------" << endl;if (score >= 600) {cout << "恭喜您考上了一本大学!" << endl;}else if (score >= 450) {cout << "恭喜您考上了二本大学!" << endl;}else if (score >= 300) {cout << "恭喜您考上了三本大学!" << endl;}else if (score >= 200) {cout << "恭喜您考上了专科大学!" << endl;}else {cout << "很可惜,您的分数不足以考上大学" << endl;}// 补充:在一本分数中,如果大于700分,考入北大,大于650分,考入清华,大于600考入人大。cout << "\r\n---------补充---------" << endl;if (score >= 600) {cout << "恭喜您考上了一本大学!" << endl;if (score > 700) {cout << "您能考上北大!" << endl;}else if (score > 650) {cout << "您能考上清华!" << endl;}else {cout << "您能考上人大!" << endl;}}/*请输入分数: 620输入的分数为: 620---------1. 单行格式if语句---------恭喜您考上了一本大学!---------2. 多行格式if语句---------恭喜您考上了一本大学!---------3. 多条件的if语句---------恭喜您考上了一本大学!---------补充---------恭喜您考上了一本大学!您能考上人大!*/system("pause");return 0;
}
练习案例:有三只小猪ABC,请分别输入三只小猪的体重,并判断哪只小猪最重。
#include
using namespace std;int main() {// 1. 创建三只小猪的体重int a = 0;int b = 0;int c = 0;// 2. 用户输入三只小猪的重量cout << "请输入小猪A的体重: ";cin >> a;cout << "请输入小猪B的体重: ";cin >> b;cout << "请输入小猪C的体重: ";cin >> c;cout << endl;// 3. 显示三只小猪的体重cout << "小猪A的体重 = " << a << endl;cout << "小猪B的体重 = " << b << endl;cout << "小猪C的体重 = " << c << endl;cout << endl;// 4. 判断哪只最重if (a > b) {if (a > c) {cout << "小猪A最重!" << endl;}}else { // b > aif (b > c) {cout << "小猪B最重!" << endl;}else{cout << "小猪C最重!" << endl;}}/*请输入小猪A的体重: 10请输入小猪B的体重: 20请输入小猪C的体重: 30小猪A的体重 = 10小猪B的体重 = 20小猪C的体重 = 30小猪C最重!*/system("pause");return 0;
}
作用:通过三目运算符实现简单的判断
语法:表达式1 ? 表达式2 : 表达式3
解释:
表达式1
的值为真,执行表达式2
,并返回表达式2
的结果;表达式1
的值为假,执行表达式3
,并返回表达式3
的结果。Python中是
num = 值1 if 表达式1 else 值2
#include
using namespace std;int main() {// 创建三个变量 abc// 将a和b作比较,将变量大的值赋值给变量cint a = 10;int b = 20;int c = 0;c = a > b ? a : b;cout << "c = " << c << endl; // c = 20// 在C++中,三目运算符返回的是变量,可以继续赋值(a > b ? a : b) = 100;cout << "a = " << a << endl; // a = 10cout << "b = " << b << endl; // b = 100system("pause");return 0;
}
作用:执行多条件分支语句
语法:
switch (表达式) {
case 结果1: 执行语句;break;
case 结果2: 执行语句;break;...default: 执行语句;break;
}
注意:
switch
语句中表达式类型只能是整型或字符型case
里如果没有break
,那么程序会一直向下执行示例:
#include
using namespace std;// switch语句
int main() {/*给电影打分:10 ~ 9:经典8 ~ 7:非常好6 ~ 5:一般5以下:烂片*/// 1. 提出用户给电影打分int score = 0;cout << "请给电影打分: ";cin >> score;// 2. 根据用户输入的分数来提出最终结果cout << "\r\nswitch语句结果:" << endl;switch (score){case 10:cout << "您认为是经典电影" << endl;break;case 9:cout << "您认为是经典电影" << endl;break;case 8:cout << "您认为是一般电影" << endl;break;case 7:cout << "您认为是一般电影" << endl;break;case 6:cout << "您认为是一般电影" << endl;break;case 5:cout << "您认为是一般电影" << endl;break;default:cout << "您认为是烂片" << endl;break;}/*switch相对if的优缺点:优点:结构清晰,执行效率高缺点:判断时候只能是整数或字符型,不可以是一个区间*/cout << "\r\nif语句结果:" << endl;if (score >= 9) {cout << "您认为是经典电影" << endl;}else if (score >= 5) {cout << "您认为是一般电影" << endl;}else {cout << "您认为是烂片" << endl;}system("pause");return 0;
}
作用:满足循环条件,执行循环语句
语法:while (循环条件) {循环语句}
解释:只要循环条件的结果为真,就执行循环语句。
注意:在执行循环语句时,程序必须提供跳出循环的出否,否则出现死循环
#include
using namespace std;int main() {// 在屏幕中打印 0~9 这10个数字int num = 0;while (num < 10) {cout << num << endl;num += 1;}system("pause");return 0;
}
while循环练习案例:猜数字
案例描述:系统随机生成一个1到100之间的数字,玩家进行猜测,如果猜错,提示玩家数字过大或过小,如果猜对恭喜玩家胜利,并且退出游戏。
#include
using namespace std;
// 引入time头文件
#includeint main() {// 添加随机数种子,利用当前系统时间生成随机数,防止每次随机数都一样(随机本质上是伪随机)srand((unsigned int)time(NULL));// 1. 生成随机数int num = rand() % 100 + 1; // 生成0~99的随机数// 2. 让玩家进行猜测int val = 0; // 玩家输入的数据//限定猜测次数(5次)int times = 5;while (1) {cout << "猜个数: ";cin >> val;times -= 1;// 3. 判断玩家的猜测并给出提示if (times != 0) {if (val > num) {cout << "猜的大了" << endl;}else if (val < num) {cout << "猜的小了" << endl;}else // 猜对了 -> 退出游戏{cout << "猜对了!游戏结束..." << endl;break;}cout << "剩余次数" << times << "\n" << endl;}else{cout << "次数用尽,游戏失败..." << endl;break;}}system("pause");return 0;/*猜个数: 50猜的大了剩余次数4猜个数: 30猜的小了剩余次数3猜个数: 35猜对了!游戏结束...*/
}
作用:满足循环条件,执行循环语句
语法:do{循环语句} while(循环条件);
注意:与while
的区别在于do...while
会先执行一次循环语句,再判断循环条件
do...while
与while
循环的区别在于: do...while
会先执行一次循环语句,再判断循环条件。
#include
using namespace std;/*do...while和while的区别:do...while会先执行一次循环(不管条件是否满足)
*/
int main() {// 在屏幕中输出0~9这10个数字int num = 0;cout << "---------do while---------" << endl;do{cout << num << endl;num += 1;} while (num < 10);cout << "\r\n---------while---------" << endl;num = 0;while (num < 10) {cout << num << endl;num += 1;}system("pause");return 0;
}
练习案例:水仙花数
案例描述:水仙花数是指: 一个3位数,它的每个位上的数字的3次幂之和等于它本身
例如: 13+53+33=1531^3 + 5^3 + 3^3 = 15313+53+33=153
请利用do...while
语句,求出所有3位数中的水仙花数
#include
using namespace std;
#include // 引入数学头文件int main() {// 1. 将所有的三位数进行输出(100 ~ 999)int num = 100;int a = 0; // 个位int b = 0; // 十位int c = 0; // 百位int times = 1;// 2. 在所有三位数中找到水仙花数/*e.g. 153获取个位: 153 % 10 = 3 获取十位: 153 / 10 = 15; 15 % 10 = 5 获取百位: 153 / 100 = 1判断:个位**3 + 十位**3 + 百位**3 == 本身*/do{a = num % 10;b = num / 10 % 10;c = num / 100;if ((pow(a, 3) + pow(b, 3) + pow(c, 3)) == num) {cout << "水仙花数" << times << ": " << num << endl;times += 1;}num += 1;} while (num < 1000);/*水仙花数1: 153水仙花数2: 370水仙花数3: 371水仙花数4: 407*/system("pause");return 0;
}
作用: 满足循环条件,执行循环语句
语法: for(起始表达式; 条件表达式; 末尾循环体) {循环语句;}
示例:
#include
using namespace std;int main() {// 打印数字0~9for (int i = 0; i < 10; i++){cout << i << endl;}system("pause");return 0;
}
注意:
while
, do...while
, for
都是开发中常用的循环语句,for
循环结构比较清晰,比较常用。练习案例:敲桌子
案例描述:从1开始数的数字100,如果数字个位含有7,或者数字十位含有7,或者该数字是7的倍数,我们打印敲桌子,其余数字直接打印输出。
#include
using namespace std;int main() {// 1. 先输出1到100for (int i = 1; i <= 100; i++){/*2. 从这100个数字中找到特殊数字,改为"敲桌子"* 特殊数字* 7的倍数: num % 7 == 0* 个位有7: num % 10 == 7* 十位有7: num / 10 == 7*/if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7) {cout << "敲桌子" << endl;}else {cout << i << endl;}}system("pause");return 0;
}
作用: 在循环体中再嵌套一层循环,解决一些实际问题
例如我们想在屏幕中打印如下图片,就需要利用嵌套循环。
#include
using namespace std;int main() {for (int i = 0; i < 11; i++) // 行{for (int j = 0; j < 11; j++) // 列{cout << "* ";}cout << endl;}system("pause");return 0;
}
练习案例:乘法口诀表
案例描述:利角嵌套循环,实现九九乘法表
#include
using namespace std;int main() {/** 列数 * 行数 = 计算结构* * 条件: 列数 <= 当前行数*/for (int i = 1; i < 10; i++) // 行{for (int j = 1; j <= i; j++) // 列{cout << i << "*" << j << "=" << i * j << "\t";}cout << endl;}/*1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94*1=4 4*2=8 4*3=12 4*4=165*1=5 5*2=10 5*3=15 5*4=20 5*5=256*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=367*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=498*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=649*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81请按任意键继续. . .*/system("pause");return 0;
}
作用: 用于跳出选择结构或者循环结构
break使用的时机:
switch
条件语句中,作用是终止case
并跳出switch
示例1:
#include
using namespace std;// break的使用时机
int main() {// 1. 出现在switch语句中 cout << "------ 1. 出现在switch语句中 ------" << endl;cout << "请选择副本的难度" << endl;cout << "1. 普通" << endl;cout << "2. 中等" << endl;cout << "3. 困难" << endl;int select = 0; // 用户选择结果变量cout << "请选择(1 2 3): ";cin >> select; // 等待用户输入switch (select){case 1:cout << "您选择的是普通难度" << endl;break;case 2:cout << "您选择的是中等难度" << endl;break;case 3:cout << "您选择的是困难难度" << endl;break;default:cout << "您选择的选择有误!" << endl;break;}// 2. 出现在循环语句中cout << "\r\n------ 2. 出现在循环语句中 ------" << endl;for (int i = 0; i < 10; i++){cout << i << endl;// 如果i==5, 退出循环if (i == 5) {break;}}// 3. 出现在嵌套循环语句中cout << "\r\n------ 3. 出现在嵌套循环语句中 ------" << endl;for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){// 如果j == 5,退出循环if (j == 5) {break;}cout << "* ";}cout << endl;}system("pause");return 0;
}
作用: 在循环语句中,跳过本次循环,继续执行下一次循环。
#include
using namespace std;int main() {for (int i = 0; i <= 100; i += 1) {if (i % 10 == 0) {cout << endl;}// 如果是奇数则输出if (i % 2 == 1) {cout << i << "\t";}else{continue;}}/*1 3 5 7 911 13 15 17 1921 23 25 27 2931 33 35 37 3941 43 45 47 4951 53 55 57 5961 63 65 67 6971 73 75 77 7981 83 85 87 8991 93 95 97 99*/system("pause");return 0;
}
作用: 可以无条件跳转语句
跳转语法: goto 标记;
-> goto FLAG; // 跳到标记
标记语法: 标记:
-> FLAG: // 表明标记的位置
示例:
int main3() {goto FLAG; // 跳转到标记FLAG的位置FLAG: // 确认标记的位置return 0;
}
解释: 如果标记的名称存在,当程序执行到goto语句时,会跳转到标记的位置
注意:学习goto
语句只是为了明白这个语句的作用,我们写代码的时候不要用,跳来跳去的,麻烦且容易出bug.
#include
using namespace std;// goto语句
int main() {cout << "1. xxxxxxxx" << endl;cout << "2. xxxxxxxx" << endl;goto FLAG; // 跳转到标记FLAG的位置cout << "3. xxxxxxxx" << endl;cout << "4. xxxxxxxx" << endl;FLAG: // 确认标记的位置cout << "5. xxxxxxxx" << endl;/*1. xxxxxxxx2. xxxxxxxx5. xxxxxxxx请按任意键继续. . .*/system("pause");return 0;
}
所谓数组(array),就是一个集合,里面存放了相同类型的数据元素,数组有两个特点:
在Python中,list是列表不是数组;Python的list里面可以存放不一样的数据类型,但数组中一定要存放相同的数据类型
一维数组定义的三种方式:
数据类型 数组名 [数组长度];
数据类型 数组名[数组长度] = {值1, 值2, ...};
(如果在初始化数据时没有全部填写,则会用0来填补)数据类型 数组名[] = {值1, 值2, ...];
C++中没有built-in的方法求数组的长度
总结:
示例:
#include
using namespace std;// 一维数组的定义
int main() {// ----- 1. 数据类型 数组名 [数组长度]; -----cout << "----- 1. 数据类型 数组名 [数组长度]; -----" << endl;int arr1[5]; // 定义数组// 给数组中的元素赋值for (int i = 0; i < 5; i++){arr1[i] = (i + 1) * 10;}// 访问数组元素for (int i = 0; i < 5; i++) {cout << "arr1[" << i << "]: " << arr1[i] << endl;}// ----- 2. 数据类型 数组名[数组长度] = { 值1, 值2, ... }; ----- cout << "\r\n----- 2. 数据类型 数组名[数组长度] = {值1, 值2, ...}; ----- " << endl;int arr2[5] = { 10, 20, 30, 40, 50 };// 访问数组元素for (int i = 0; i < 5; i++) {cout << "arr2[" << i << "]: " << arr2[i] << endl;}// ----- 3. 数据类型 数组名[] = {值1, 值2, ...}; -----cout << "\r\n----- 3. 数据类型 数组名[] = {值1, 值2, ...}; -----" << endl;int arr3[] = { 90, 80, 60, 50, 40, 30, 20, 10, 0 };// 访问数组元素for (int i = 0; i < 9; i++){cout << "arr3[" << i << "]: " << arr3[i] << endl;}/*----- 1. 数据类型 数组名 [数组长度]; -----arr1[0]: 10arr1[1]: 20arr1[2]: 30arr1[3]: 40arr1[4]: 50----- 2. 数据类型 数组名[数组长度] = {值1, 值2, ...}; -----arr2[0]: 10arr2[1]: 20arr2[2]: 30arr2[3]: 40arr2[4]: 50----- 3. 数据类型 数组名[] = {值1, 值2, ...}; -----arr3[0]: 90arr3[1]: 80arr3[2]: 60arr3[3]: 50arr3[4]: 40arr3[5]: 30arr3[6]: 20arr3[7]: 10arr3[8]: 0*/system("pause");return 0;
}
一维数组名称的用途:
sizeof(数组名)
cout << arr << endl;
sizeof(arr[0])
sizeof(arr)
这样我们就可以得到数组中元素的个数,即数组的长度。
C++中没有built-in的方法求数组的长度
#include
using namespace std;int main() {// 1. 可以统计整个数组在内存中的长度: sizeof(数组名)int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };cout << "arr数组占用内存空间大小为: " << sizeof(arr) << "字节" << endl; // arr数组占用内存空间大小为: 40字节cout << "arr数组每个元素占用内存空间大小为: " << sizeof(arr[0]) << "字节" << endl; // arr数组每个元素占用内存空间大小为: 4字节cout << "arr数组的元素个数(数组长度)为: " << sizeof(arr) / sizeof(arr[0]) << endl; // arr数组的元素个数(数组长度)为: 10// 2. 可以获取数组在内存中的首地址: cout << arr << endl; cout << "arr数组的首地址为: " << arr << endl; // 000000B955D0F748cout << "arr数组的首地址(十进制)为: " << (int) arr << endl; // 1439758152cout << "arr数组的第一个元素的地址为: " << &arr[0] << endl; // 000000B955D0F748cout << "arr数组的第一个元素的地址(十进制)为: " << (int)&arr[0] << endl; // 1439758152cout << "arr数组的第二个元素的地址为: " << &arr[0] << endl; // 000000B955D0F748cout << "arr数组的第二个元素的地址(十进制)为: " << (int)&arr[0] << endl; // 1439758152/** 1. &是取址符* * 2. 可以看到,数组的首地址和数组第一个元素的地址是一样的!* * 3. 因为数组在内存空间中是连续的,因此第一个元素的地址和第二个元素的地址差4(int的大小是4字节!)*/// 数组名是常量,不可以进行赋值// arr = 100; // IDE报错: 表达式必须是可修改的左值system("pause");return 0;
}
练习案例1: 五只小猪称体重
案例描述: 在一个数组中记录了五只小猪的体重,如: int arr[5]= { 300, 350, 200, 400, 250 };
找出并打印最重的小猪体重。
#include
using namespace std;int main() {// 1. 创建5只小猪体重的数组int arr[5] = { 300, 350, 200, 400, 250 };// 2. 定义最大值int max_num = arr[0];int order = 0;// 3. 逻辑判断for (int i = 1; i < 5; i++){if (arr[i] > max_num) {max_num = arr[i];order = i;}}// 4. 打印最大值cout << "最大值为: " << max_num;cout << "。是第 " << order + 1 << " 只小猪" << endl; // 最大值为: 400。是第 4 只小猪system("pause");return 0;
}
练习案例2: 数组元素逆置
案例描述: 请声明一个5个元素的数组,并且将元素逆置.
(如原数组元素为: 1, 3, 2, 5, 4; 逆置后输出结果为: 4, 5, 2, 3, 1);
#include
using namespace std;int main() {// 1. 创建数组int arr[] = { 1, 3, 2, 5, 4 };// 2. 实现逆置/*2.1 记录起始下标的位置2.2 记录结束下标的位置2.3 起始下标和结束下标的元素互换2.4 起始位置++; 结束位置++2.5 循环执行2.1操作,直到起始位置 >= 结束位置*/int start = 0;int end = sizeof(arr) / sizeof(arr[0]) - 1;int tmp = 0;while (start < end) {// 元素互换tmp = arr[start];arr[start] = arr[end];arr[end] = tmp;// 更新下标start += 1;end -= 1;}// 3. 打印逆置后的数组cout << "数组元素逆置后: " << endl;for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){cout << arr[i] << ", "; // 4, 5, 2, 3, 1,}cout << endl;system("pause");return 0;
}
思路2:
#include
using namespace std;int main() {// 1. 创建数组int arr[] = { 1, 3, 2, 5, 4 };int length = sizeof(arr) / sizeof(arr[0]) - 1;// 2. 具体实现for (int i = 0; i <= length / 2; i++) // 注意只走一半{ int tmp = arr[i];arr[i] = arr[length - i];arr[length - i] = tmp;}// 3. 打印逆置后的数组cout << "数组元素逆置后: " << endl;for (int i = 0; i <= length; i++){cout << arr[i] << ", "; // 4, 5, 2, 3, 1,}cout << endl;system("pause");return 0;
}
作用: 最常用的排序算法,对数组内元素进行排序
示例: 将数组{ 4, 2, 8, 0, 5, 7, 1, 3, 9 }
进行升序排序
#include
using namespace std;int main() {int arr[] = { 4, 2, 8, 0, 5, 7, 1, 3, 9 };int n = sizeof(arr) / sizeof(arr[0]) - 1;// 排序前cout << "排序前: " << endl;for (int i = 0; i <= n; i++){cout << arr[i] << " "; // 4 2 8 0 5 7 1 3 9}cout << endl;/*外层: n - 1内层: n - i - 1*/for (int i = 0; i < n - 1; i++) // n - 1轮(外层){for (int j = 0; j < n - i - 1; j++) // 内层{if (arr[j] > arr[j + 1]) {int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}// 排序后cout << "排序后: " << endl;for (int i = 0; i <= n; i++){cout << arr[i] << " "; // 0 1 2 3 4 5 7 8 9}cout << endl;system("pause");return 0;
}
二维数组就是在一维数组上,多加了一个维度。
二维数组定义的四种方式:
数据类型 数组名[行数][列数];
数据类型 数组名[行数][列数] = { {数据1,数据2},{数据3,数据4 }};
数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};
数据类型 数组名[][列数] = {数据1,数据2,数据3,数据4};
建议: 以上4种定义方式,利用第二种更加直观,提高代码的可读性
在定义二维数组时,如果初始化了数据,可以省略行数
示例:
#include
using namespace std;int main() {// 1. 数据类型 数组名[行数][列数];int arr1[2][3];// 赋值for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++){arr1[i][j] = (i + 1) * (j + 1) * 10;}}// 查看cout << "------ 1. 数据类型 数组名[行数][列数]; ------" << endl;for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++){cout << arr1[i][j] << " ";}cout << endl;}// 2. 数据类型 数组名[行数][列数] = { {数据1,数据2},{数据3,数据4 }};int arr2[2][3] = { {10, 20, 30}, {40, 50, 60} };// 查看cout << "\r\n------ 2. 数据类型 数组名[行数][列数] = { {数据1,数据2},{数据3,数据4 }}; ------" << endl;for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++){cout << arr2[i][j] << " ";}cout << endl;}// 3. 数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};int arr3[2][3] = { 10, 20, 30, 40, 50, 60 };// 查看cout << "\r\n------ 3. 数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4}; ------" << endl;for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++){cout << arr2[i][j] << " ";}cout << endl;}// 4. 数据类型 数组名[][列数] = {数据1,数据2,数据3,数据4};int arr4[][3] = { 10, 20, 30, 40, 50, 60 };// 查看cout << "\r\n------ 4. 数据类型 数组名[][列数] = {数据1,数据2,数据3,数据4}; ------" << endl;for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++){cout << arr2[i][j] << " ";}cout << endl;}/*------ 1. 数据类型 数组名[行数][列数]; ------10 20 3020 40 60------ 2. 数据类型 数组名[行数][列数] = { {数据1,数据2},{数据3,数据4 }}; ------10 20 3040 50 60------ 3. 数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4}; ------10 20 3040 50 60------ 4. 数据类型 数组名[][列数] = {数据1,数据2,数据3,数据4}; ------10 20 3040 50 60*/system("pause");return 0;
}
#include
using namespace std;int main() {// 1. 查看二维数组所占内存空间int arr[2][3] = {{1, 2, 3},{4, 5, 6}};cout << "二维数组占用的内存空间为: " << sizeof(arr) << "字节" << endl; // 24字节cout << "二维数组第一行占用的内存空间为: " << sizeof(arr[0]) << "字节" << endl; // 12字节cout << "二维数组第一个元素占用的内存空间为: " << sizeof(arr[0][0]) << "字节" << endl; // 4字节// 统计出二维数组的行和列cout << "二维数组行数为: " << sizeof(arr) / sizeof(arr[0]) << endl; // 2cout << "二维数组列数为: " << sizeof(arr[0]) / sizeof(arr[0][0]) << endl; // 3// 2. 获取二维数组首地址cout << "二维数组的首地址为: " << arr << endl;cout << "二维数组第一行的首地址为: " << arr[0] << endl;cout << "二维数组第二行的首地址为: " << arr[1] << endl;cout << "二维数组第一个元素的地址为: " << &arr[0][0] << endl;cout << "二维数组第二个元素的地址为: " << &arr[0][1] << endl;/*第一行和第二行首地址差12(因为列=3)二维数组的首地址为: 000000438C4FF648二维数组第一行的首地址为: 000000438C4FF648二维数组第二行的首地址为: 000000438C4FF654二维数组第一个元素的地址为: 000000438C4FF648二维数组第二个元素的地址为: 000000438C4FF64C*/system("pause");return 0;
}
考试成绩统计:
案例描述: 有三名同学(张三,李四,王五),在一次考试中的成绩分别如下表,请分别输出三名同学的总成绩。
姓名 | 语文 | 数学 | 英语 |
---|---|---|---|
张三 | 100 | 100 | 100 |
李四 | 90 | 50 | 100 |
王五 | 60 | 70 | 80 |
#include
using namespace std;
#include// 二维数组案例 —— 考试成绩统计
int main() {// 1. 创建二维数组int scores[3][3] = {{100, 100, 100},{90, 50, 100},{60, 70, 80},};string names[3] = {"张三","李四","王五",};// 2. 统计每个人的总和分数for (int i = 0; i < 3; i++) // 行{int sum = 0; // 统计分数总和for (int j = 0; j < 3; j++) // 列{sum += scores[i][j];}// 打印每个人的总成绩cout << names[i] << "的总分为: " << sum << endl;}/*张三的总分为: 300李四的总分为: 240王五的总分为: 210*/system("pause");return 0;
}
作用: 将一段经常使用的代码封装起来,减少重复代码。
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。
函数的定义一般主要有5个步骤:
语法:
返回值类型 函数名 (形参1, 形参2, ...) {函数体语句;return表达式;
}
示例:
// 加法函数,实现两个整型相加并返回相加的结果
int add(int num1, int num2) {int sum = num1 + num2;return sum;
}
功能: 使用定义好的函数
语法: 函数名(参数1, 参数2, ...)
示例:
#include
using namespace std;// 加法函数,实现两个整型相加并返回相加的结果
int add(int num1, int num2) {int sum = num1 + num2;return sum;
}int main() {int a = 10;int b = 20;int res = add(a, b);cout << "两数之和为: " << res << endl; // 两数之和为: 30//system("pause"); // 按任意键继续的功能return 0;
}
#include
using namespace std;// 如果函数不需要返回值,声明的时候可以写void
void swap(int num1, int num2) {cout << "交换前: " << "num1: " << num1 << "\t num2: " << num2 << endl;int tmp = num1;num1 = num2;num2 = tmp;cout << "交换后: " << "num1: " << num1 << "\t num2: " << num2 << endl;
}int main() {int a = 10;int b = 20;swap(a, b);/*交换前: num1: 10 num2: 20交换后: num1: 20 num2: 10*///system("pause"); // 按任意键继续的功能return 0;
}
void: 中文翻译为“无类型”。常用在程序编写中对定义函数的参数类型、返回值、函数中指针类型进行声明。void的字面意思是“无类型”。
常见的函数样式有4种:
#include
using namespace std;// 1. 无参无返
void test_01() {cout << "1. 无参无返" << endl;
}// 2. 有参无返
void test_02(int a) {cout << "2. 有参无返: ";cout << a << endl;
}// 3. 无参有返
float test_03() {cout << "3. 无参有返" << endl;return 3.14f;
}// 4. 有参有返
double test_04(float a) {cout << "4. 有参有返" << endl;return a;
}int main() {// 1. 无参无返test_01(); // 1. 无参无返// 2. 有参无返test_02(10086); // 2. 有参无返 10086// 3. 无参有返float return_param_1 = test_03(); // 3. 无参有返cout << "return_param_1: " << return_param_1 << endl; // return_param_1: 3.14// 4. 有参有返double return_param_2 = test_04(6.17f); // 4. 有参有返cout << "return_param_2: " << return_param_2 << endl; // return_param_2: 6.17return 0;
}
作用: 告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
#include
using namespace std; // 让我们可以使用cout在屏幕输出// 提前告诉编译器函数的存在,可以利用函数的声明
// 函数的声明可以有多次,但函数的定义只能有一次!
int max(int a, int b);
int max(int a, int b);
int max(int a, int b);int main() {int a = 10;int b = 20;int max_num = max(a, b);cout << "max_num: " << max_num; // max_num: 20return 0;
}// 函数的定义只能有一次!
int max(int a, int b) {return a > b ? a : b;
}
作用: 让代码结构更加清晰
函数分文件编写一般有4个步骤:
.h
的头文件 -> swap.h
.cpp
的源文件 -> swap.cpp
示例:
.h
的头文件 -> swap.h
.cpp
的源文件 -> swap.cpp
#include
using namespace std;// 函数的声明
void swap(int num1, int num2);
#include "swap.h"// 函数的定义
void swap(int num1, int num2) {cout << "交换前: " << "num1: " << num1 << "\t num2: " << num2 << endl;int tmp = num1;num1 = num2;num2 = tmp;cout << "交换后: " << "num1: " << num1 << "\t num2: " << num2 << endl;
}
#include
using namespace std; // 让我们可以使用cout在屏幕输出
#include "swap.h"/*函数分文件编写一般有4个步骤:1. 创建后缀名为.h的头文件: swap.h2. 创建后缀名为.cpp的源文件: swap.cpp3. 在头文件中写函数的声明4. 在源文件中写函数的定义
*/int main() {int a = 10;int b = 20;swap(a, b);/*交换前: num1: 10 num2: 20交换后: num1: 20 num2: 10*/return 0;
}
指针的作用: 可以通过指针间接访问内存。
简单来说,指针就是一个地址
指针变量定义语法: 数据类型 *变量名;
示例:
#include
using namespace std;int main() {// 1. 定义指针: 数据类型 *指针变量名int a = 10;int* p;; // 这就定义了一个指针// 让指针*p记录变量a的地址p = &a;cout << "a的地址为: " << &a << endl; // 000000F62119F7C4cout << "指针p为: " << p << endl; // 000000F62119F7C4cout << "*p为: " << *p << endl; // 10// 2. 使用指针// 可以通过解引用的方式来找到指针指向的内存// 指针前加一个*代表解引用,即找到指针指向的内存中的数据*p = 1000;cout << "a = " << a << endl; // 1000cout << "*p = " << *p << endl; // 1000return 0;
}
提问:指针也是一种数据类型,那么这种数据类型占用多少内存空间?
回答:在32位操作系统下,指针都占用4个字节空间;在64位操作系统下,指针占用8个字节空间。
在IDE中可以修改系统环境的位数:
示例:
#include
using namespace std;int main() {int a = 10;int* p = &a;cout << "sizeof(int*) = " << sizeof(int*) << "字节" << endl; // 8字节cout << "sizeof(int*) = " << sizeof(p) << "字节" << endl; // 8字节cout << "sizeof(float*) = " << sizeof(float*) << "字节" << endl; // 8字节cout << "sizeof(double*) = " << sizeof(double*) << "字节" << endl; // 8字节cout << "sizeof(char*) = " << sizeof(char*) << "字节" << endl; // 8字节cout << "sizeof(long*) = " << sizeof(long*) << "字节" << endl; // 8字节cout << "sizeof(long long*) = " << sizeof(long long*) << "字节" << endl; // 8字节/* 32位操作系统sizeof(int*) = 4字节sizeof(float*) = 4字节sizeof(double*) = 4字节sizeof(char*) = 4字节sizeof(long*) = 4字节sizeof(long long*) = 4字节*//* 64位操作系统sizeof(int*) = 8字节sizeof(float*) = 8字节sizeof(double*) = 8字节sizeof(char*) = 8字节sizeof(long*) = 8字节sizeof(long long*) = 8字节*/return 0;
}
指针不知道指向哪里好,就指向空
0 ~ 255这块内存是系统占用的,我们不可以访问
#include
using namespace std;// 空指针
int main() {// 1. 空指针用于给指针变量进行初始化int* p = NULL;cout << "p: " << p << endl; // p: 0000000000000000// 2. 空指针是不可以进行访问的(0 ~ 255的内存编号是系统占用的,因此不可以访问)// *p = 100; // 引发了异常: 写入访问权限冲突。p 是 nullptr。return 0;
}
示例:
#include
using namespace std;// 野指针:在程序中尽量避免出现野指针
int main() {// 没有申请内存就直接让指针指向这个地址int* p = (int*)0x1100;cout << "p: " << p << endl; // p: 0000000000001100cout << "*p: " << *p << endl; // 引发了异常: 读取访问权限冲突。p 是 0x1100。// 因为我们之前没有申请0x1100这个地址,所以C++程序是没有权限去操作这块地址return 0;
}
总结:空指针和野指针都不是我们申请的空间,因此不要访问!
const修饰指针有三种情况:
const
修饰指针 -> 常量指针 -> const int* p = &a;
const
修饰常量 -> 指针常量 -> int* const p = &a;
const
即修饰指针,又修饰常量 -> const int* const p = &a;
记名称:常量=const, 指针=*,这样就好记了
对于常量指针,可以理解为const
限制的*
,所以*p
的操作就不可以了
对于指针常量,可以理解为const
限制的p
,所以p
的操作就不可以了
const
修饰谁,谁就是常量,常量是不可以修改的!
const
修饰指针 -> 常量指针 -> const int* p = &a;
特点:指针的指向可以修改,但指针指向的值不可以修改,即
int a = 10;
int b = 10;// 定义常量指针
const int* p = &a;// 判断
*p = 20; // 不可以,指针不可以修改指向的值
p = &b; // 可以,指针可以修改指向
const
修饰常量 -> 指针常量 -> int* const p = &a;
特点:指针的指向不可以改,指针指向的值可以修改。
int a = 10;
int b = 10;// 定义常量指针
int* const p = &a;// 判断
*p = 20; // 可以,指针可以修改指向的值
p = &b; // 不可以,指针不可以修改指向
const
即修饰指针,又修饰常量const
即修饰指针,又修饰常量 -> const int* const p = &a;
特点:指针的指向和指向的值都不可以改!
int a = 10;
int b = 10;// 定义常量指针
const int* const p = &a;// 判断
*p = 20; // 不可以,指针不可以修改指向的值
p = &b; // 不可以,指针不可以修改指向
示例:
#include
using namespace std;int main() {int a = 10;int b = 20;// 1. const修饰指针 -> 常量指针const int* p1 = &a;// *p1 = 20; // 报错:“p1” : 不能给常量赋值 指针p1 = &b; // 不报错// 2. const修饰常量 -> 指针常量int* const p2 = &a;*p2 = 20; // 不报错// p2 = &b; // 报错:“p2” : 不能给常量赋值// 3. const修饰指针和常量const int* const p3 = &a;// *p3 = 20; // 报错:表达式必须是可修改的左值// p3 = &b; // 报错:“p3” : 不能给常量赋值return 0;
}
技巧: 看
const
右侧紧跟着的是指针还是常量,是指针就是常量指针,是常量就是指针常量
作用:利用指针访问数组中元素
示例:
#include
using namespace std;int main() {// 利用指针访问数组中的元素int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };cout << "第一个元素为: " << arr[0] << endl; // 1int* p = arr; // 数组名就是数组第一个元素的地址(数组的首地址)cout << "利用指针访问第一个元素: " << *p << endl; // 1p += 1; // 让指针向后偏移4个字节cout << "利用指针访问第二个元素: " << *p << endl; // 1 // 2cout << "\r\n--------利用指针遍历数组--------" << endl;int* p2 = arr;for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){cout << *p2 << " "; // 1 2 3 4 5 6 7 8 9 10p2 += 1;}cout << endl;return 0;
}
作用:利用指针作函数参数,可以修改实参的值
#include
using namespace std;// 实现两个数字进行交互
void swap_01(int a, int b) {int tmp = a;a = b;b = tmp;cout << "----形参----" << endl;cout << "[swap_01] a = " << a << endl;cout << "[swap_01] b = " << b << endl;
}void swap_02(int* p1, int* p2) {int tmp = *p1;*p1 = *p2;*p2 = tmp;cout << "----形参----" << endl;cout << "[swap_02] a = " << *p1 << endl;cout << "[swap_02] b = " << *p2 << endl;
}int main() {// 1. 值传递: 不会修改实参int a = 10;int b = 20;swap_01(a, b);cout << "----实参----" << endl;cout << "a = " << a << endl;cout << "b = " << b << endl;/*----形参----[swap_01] a = 20[swap_01] b = 10----实参----a = 10b = 20*/// 2. 地址传递: 可以修改实参swap_02(&a, &b);cout << "----实参----" << endl;cout << "a = " << a << endl;cout << "b = " << b << endl;/*----形参----[swap_02] a = 20[swap_02] b = 10----实参----a = 20b = 10*/return 0;
}
总结:如果不想修改实参,就用值传递;如果想修改实参,就用地址传递
案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序。
例如数组: int arr[10] = { 4, 3, 6, 9, 1, 2, 10, 8, 7, 5 }
#include
using namespace std;void bubble_sort(int* arr, int n) {/** arr: 数组的首地址(因为要接收一个地址,所以数据类型是int*)* n: 数组的长度*/for (int i = 0; i < n - 1; i++){for (int j = 0; j < n - i - 1; j++){if (arr[j] > arr[j + 1]) {int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}void print_array(int* arr, int n) {/** arr: 数组的首地址(因为要接收一个地址,所以数据类型是int*)* n: 数组的长度*/for (int i = 0; i < n; i++){cout << arr[i] << " ";}cout << endl;
}int main8() {// 1. 创建数组int arr[10] = { 4, 3, 6, 9, 1, 2, 10, 8, 7, 5 };int len = sizeof(arr) / sizeof(arr[0]);// 2. 创建函数,实现冒泡排序bubble_sort(arr, len);// 3. 打印排序后的数组print_array(arr, len); // 1 2 3 4 5 6 7 8 9 10return 0;
}
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。
语法: struct 结构体名 { 结构体成员列表 };
通过结构体创建变量的方式有三种:
struct 结构体名 变量名;
struct 结构体名 变量名 = { 成员1值, 成员2值, ... };
注意:
struct
关键字可以省略总结:
struct
,不可省略struct
可以省略.
访问成员可以看到,C/C++中的结构体和Python中的class很像。
示例:
#include
using namespace std;
#include// 1. 创建学生数据类型:姓名,年龄,分数
struct Student
{// 成员列表string name;int age;int score;
};struct Student2
{// 成员列表string name;int age;int score;
}s3; // 在创建结构体的时候创建顺便创建变量int main() {// 2. 通过学生类型创建具体学生// 2.1 struct 结构体名 变量名;struct Student s1;s1.name = "张三";s1.age = 18;s1.score = 100;// cout << s1 << endl; // 没有与这些操作数匹配的cout << "姓名: " << s1.name << "\t年龄: " << s1.age << "\t分数: " << s1.score << endl; // 姓名: 张三 年龄: 18 分数: 100// 2.2 struct 结构体名 变量名 = { 成员1值, 成员2值, ... }; Student s2 = { "李四", 19, 80 }; // 在创建结构体变量时struct关键字可以省略cout << "姓名: " << s2.name << "\t年龄: " << s2.age << "\t分数: " << s2.score << endl; // 姓名: 李四 年龄: 19 分数: 80// 2.3 定义结构体时顺便创建变量s3.name = "王五";s3.age = 20;s3.score = 60;cout << "姓名: " << s3.name << "\t年龄: " << s3.age << "\t分数: " << s3.score << endl; // 姓名: 王五 年龄: 20 分数: 60return 0;
}
作用:将自定义的结构体放入到数组中以方便维护。
语法:struct 结构体名 数组名[元素个数] = { {}, {}, ... }
示例:
#include
using namespace std;
#include// 1. 定义结构体
struct Student
{string name;int age;int score;
};int main() {// 2. 创建结构体数组Student stuArray[] = {{"张三", 18, 100},{"李四", 20, 99},{"王五", 38, 80},};// 3. 给结构体数组中的元素赋值stuArray[2].name = "赵六";stuArray[2].age = 40;stuArray[2].score = 75;// 4. 遍历结构体数组for (int i = 0; i < 3; i++){cout << "姓名: " << stuArray[i].name << "\t年龄: " << stuArray[i].age << "\t分数: " << stuArray[i].score << endl;}/*姓名: 张三 年龄: 18 分数: 100姓名: 李四 年龄: 20 分数: 99姓名: 赵六 年龄: 40 分数: 75*/return 0;
}
作用:通过指针访问结构体中的成员
->
可以通过结构体指针访问结构体属性struct Student {string name;int age;int score;
}> 总结:结构体指针可以通过>操作符来访问结构体中的成员int main() {Student s1 = { "张三", 18, 100 };Student* p = &s1;// 利用 -> 访问结构体中的成员变量cout << p->name << endl;cout << p->age << endl;cout << p->score << endl;return 0;
}
示例:
#include
using namespace std;
#include// 1. 定义结构体
struct Student
{string name;int age;int score;
};int main() {// 2. 创建学生的结构体变量Student s = { "张三", 18, 100 };// 3. 通过指针指向结构体变量// int* p = &s; // "Student *" 类型的值不能用于初始化Student* p = &s; // 结构体就是我们自定义的数据类型,指针当然也要使用这种数据类型// 4. 通过指针访问结构体变量中的数据cout << "姓名: " << p->name << "\t年龄: " << p->age << "\t分数: " << p->score << endl;// 姓名: 张三 年龄: 18 分数: 100return 0;
}
作用:结构体中的成员可以是另一个结构体。
例子:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体。
示例:
#include
using namespace std;
#include// 1. 定义学生的结构体
struct Student
{string name;int age;int score;
};// 2. 定义老师的结构体
struct Teacher
{int id; // 教师编号string name;int age;Student stu; // 辅导的学生
};int main() {// 3. 创建老师Teacher t = { 10086, "王老师", 50, {"小王", 16, 60} };/*Teacher t;t.id = 10086;t.name = "王老师";t.age = 50;t.stu.name = "小王";t.stu.age = 16;t.stu.score = 60;*/cout << "老师姓名: " << t.name << "\t老师编号: " << t.id << "\t老师年龄: " << t.age << "\n辅导的学生的姓名: " << t.stu.name << "\t辅导的学生的年龄: " << t.stu.age << "\t辅导的学生的分数" << t.stu.score << endl;/*老师姓名: 王老师 老师编号: 10086 老师年龄: 50辅导的学生的姓名: 小王 辅导的学生的年龄: 16 辅导的学生的分数60*/return 0;
}
作用:将结构体作为参数向函数中传递
传递方式有两种:
总结:如果不想修改主函数中的数据,用值传递,反之用地址传递。
示例:
#include
using namespace std;
#include// 定义学生结构体
struct Student
{string name;int age;int score;
};// 打印学生信息的函数
// 1. 值传递
void print_student_1(Student stu) {cout << "---------子函数[print_student_1]中打印---------" << endl;stu.name = "[值传递修]改后的姓名";cout << "姓名: " << stu.name << "\t年龄: "<< stu.age << "\t分数: " << stu.score<< endl;
}// 2. 地址传递
void print_student_2(Student* p) {cout << "---------子函数[print_student_2]中打印---------" << endl;p->name = "[地址传递]修改后的姓名";cout << "姓名: " << p->name << "\t年龄: "<< p->age << "\t分数: " << p->score<< endl;
}int main() {Student stu;stu.name = "张三";stu.age = 20;stu.score = 80;// 将学生传入到一个函数中,打印学生身上所有的信息// 1. 值传递print_student_1(stu);cout << "---------main函数中打印---------" << endl;cout << "姓名: " << stu.name << "\t年龄: "<< stu.age << "\t分数: " << stu.score<< endl << endl << endl;// 2. 地址传递print_student_2(&stu);cout << "---------main函数中打印---------" << endl;cout << "姓名: " << stu.name << "\t年龄: "<< stu.age << "\t分数: " << stu.score<< endl;/*---------子函数[print_student_1]中打印---------姓名: [值传递修]改后的姓名 年龄: 20 分数: 80---------main函数中打印---------姓名: 张三 年龄: 20 分数: 80---------子函数[print_student_2]中打印---------姓名: [地址传递]修改后的姓名 年龄: 20 分数: 80---------main函数中打印---------姓名: [地址传递]修改后的姓名 年龄: 20 分数: 80*/return 0;
}
作用:用const
来防止误操作。
示例:
#include
using namespace std;
#includestruct Student
{string name;int age;int score;
};void print_stu_info_value_trans(Student stu) {/** 这种值传递的方式会有问题:* 值传递的形参会复制传入的值,因此会带来额外的性能开销。* 如果调用这个函数的次数很多,那么带来的性能开销就会变大!* * 要想减小开销,可以使用地址传递!*/stu.age += 1; // 让年龄增加一岁cout << "姓名: " << stu.name << "\t年龄: " << stu.age << "\t分数: " << stu.score << endl;
}void print_stu_info_pointer_trans(const Student* stu) {/** 值传递因为会复制实参,带来了大量的性能开销,而地址传递* 传入的是指针,一个指针的大小为4字节(32位系统下),因此* 复制指针带来的性能开销明显降低!* * 但是地址传递有一个问题:那就是改变形参会改变实参。* 为了解决这个问题,我们应该使用const关键字!* * 具体实现是给形参加一个const,即const Student+* stu。* const修饰的是*,因此指针指向地址的值是不允许改变的,* 这样stu->age += 1;这行语句写完后就IDE就会报错,告诉* 我们不要修改指针指向地址的值!*///stu->age += 1; // 表达式必须是可修改的左值cout << "姓名: " << stu->name << "\t年龄: "<< stu->age + 1 << "\t分数: " << stu->score<< endl;
}int main() {// 创建结构体变量Student stu = { "张三", 18, 90 };// 通过函数打印结构体变量的信息print_stu_info_value_trans(stu);cout << "-----调用print_stu_info_value_trans后-----" << endl;cout << "姓名: " << stu.name << "\t年龄: "<< stu.age << "\t分数: " << stu.score<< endl << endl << endl;print_stu_info_pointer_trans(&stu);cout << "-----调用print_stu_info_pointer_trans后-----" << endl;cout << "姓名: " << stu.name << "\t年龄: "<< stu.age << "\t分数: " << stu.score<< endl;/*姓名: 张三 年龄: 19 分数: 90-----调用print_stu_info_value_trans后-----姓名: 张三 年龄: 18 分数: 90姓名: 张三 年龄: 19 分数: 90-----调用print_stu_info_pointer_trans后-----姓名: 张三 年龄: 18 分数: 90*/return 0;
}
案例描述:学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:
示例:
#include
using namespace std;
#include
#include// 定义学生的结构体
struct Student
{string stu_name;int stu_score;
};// 定义老师的结构体
struct Teacher
{string teac_name;// 学生数组Student stu_array[5];
};// 给老师和学生赋值的函数
void allocate_space(Teacher teac_array[], int len) {string name_seed = "ABCDE";for (int i = 0; i < len; i++) // 外层:给老师赋值{teac_array[i].teac_name = "Teacher_";teac_array[i].teac_name += name_seed[i];for (int j = 0; j < 5; j++) // 内层:给学生赋值{teac_array[i].stu_array[j].stu_name = "Student_";teac_array[i].stu_array[j].stu_name += name_seed[j];int random = rand() % 61 + 40; // 40 ~ 100teac_array[i].stu_array[j].stu_score = random;}}
}void print_info(Teacher teac_array[], int len) {for (int i = 0; i < len; i++){cout << "老师姓名: " << teac_array[i].teac_name << endl;for (int j = 0; j < 5; j++){cout << "\t学生姓名: " << teac_array[i].stu_array[j].stu_name << "\t考试分数: " << teac_array[i].stu_array[j].stu_score << endl;}}
}int main() {// 加入随机数种子srand((unsigned int)time(NULL));// 1. 创建3名老师的数组Teacher teac_array[3];// 2. 通过函数给3名老师的信息赋值,并给老师带的学生赋值int len = sizeof(teac_array) / sizeof(teac_array[0]);allocate_space(teac_array, len);// 3. 打印所有老师及所带学生的信息print_info(teac_array, len);/*老师姓名: Teacher_A学生姓名: Student_A 考试分数: 78学生姓名: Student_B 考试分数: 40学生姓名: Student_C 考试分数: 86学生姓名: Student_D 考试分数: 61学生姓名: Student_E 考试分数: 42老师姓名: Teacher_B学生姓名: Student_A 考试分数: 87学生姓名: Student_B 考试分数: 61学生姓名: Student_C 考试分数: 100学生姓名: Student_D 考试分数: 68学生姓名: Student_E 考试分数: 48老师姓名: Teacher_C学生姓名: Student_A 考试分数: 88学生姓名: Student_B 考试分数: 83学生姓名: Student_C 考试分数: 53学生姓名: Student_D 考试分数: 79学生姓名: Student_E 考试分数: 90*/return 0;
}
案例描述:设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
五名英雄信息如下:
{"盖伦", 23, "男"},
{"卡特", 22, "女"},
{"赵信", 30, "男"},
{"嘉文四世", 25, "男"},
{"瑞文", 24, "女"},
{"亚索", 20, "男"},
{"卡莎", 26, "女"},
示例:
#include
using namespace std;
#include// 1. 设计英雄结构体
struct Hero
{string name;int age;string gender;
};void bubble_sort_for_hero(Hero hero_arr[], int n) {for (int i = 0; i < n - 1; i++){for (int j = 0; j < n - i - 1; j++){if (hero_arr[j].age > hero_arr[j + 1].age) {Hero tmp = hero_arr[j];hero_arr[j] = hero_arr[j + 1];hero_arr[j + 1] = tmp;}}}
}void print_hero(Hero hero_arr[], int n) {cout << "-------排序后的结果-------" << endl;for (int i = 0; i < n; i++){cout << "姓名: " << hero_arr[i].name << "\t年龄: "<< hero_arr[i].age << "\t性别: " << hero_arr[i].gender << endl;}
}int main() {// 2. 创建数组存放5名英雄Hero hero_arr[] = {{"盖伦", 23, "男"},{"卡特", 22, "女"},{"赵信", 30, "男"},{"嘉文四世", 25, "男"},{"瑞文", 24, "女"},{"亚索", 20, "男"},{"卡莎", 26, "女"},};int n = sizeof(hero_arr) / sizeof(hero_arr[0]);// 3. 对数组进行排序,按照年龄进行升序排序bubble_sort_for_hero(hero_arr, n);// 4. 将排序后的结果打印输出print_hero(hero_arr, n);/*-------排序后的结果-------姓名: 亚索 年龄: 20 性别: 男姓名: 卡特 年龄: 22 性别: 女姓名: 盖伦 年龄: 23 性别: 男姓名: 瑞文 年龄: 24 性别: 女姓名: 嘉文四世 年龄: 25 性别: 男姓名: 卡莎 年龄: 26 性别: 女姓名: 赵信 年龄: 30 性别: 男*/return 0;
}
通讯录是一个可以记录亲人、好友信息的工具。本教程主要利用C++来实现一个通讯录管理系统。系统中需要实现的功能如下:
功能描述:用户选择功能的界面
菜单界面效果如下图:
步骤:
void showMenu()
代码:
// 菜单界面
void show_menu() {cout << "*****************************" << endl;cout << "*****\t1. 添加联系人\t*****" << endl;cout << "*****\t2. 显示联系人\t*****" << endl;cout << "*****\t3. 删除联系人\t*****" << endl;cout << "*****\t4. 查找联系人\t*****" << endl;cout << "*****\t5. 修改联系人\t*****" << endl;cout << "*****\t6. 清空联系人\t*****" << endl;cout << "*****\t0. 退出通讯录\t*****" << endl;cout << "*****************************" << endl;
}
功能描述:退出通讯录系统
思路:根据用户不同的选择,进入不同的功能,可以选择switch
分支结构,将整个架构进行搭建。
当用户选择0时候,执行退出,选择其他先不做操作,也不会退出程序。
代码:
int main() {int select = 0; // 用户选择输入的变量while (true) // 大循环{show_menu();cout << "请选择功能: ";cin >> select;// 根据输入做出判断switch (select){case 1: // 1. 添加联系人break;case 2: // 2. 显示联系人break;case 3: // 3. 删除联系人break;case 4: // 4. 查找联系人break;case 5: // 5. 修改联系人break;case 6: // 6. 清空联系人break;case 0: // 0. 退出通讯录cout << "欢迎下次使用!" << endl;system("pause"); // 请按任意键继续return 0; // main函数的return -> 退出main函数break;default:cout << "您的输入无效!" << endl;break;}}system("pause");return 0; // 返回正常退出值
}
功能描述:实现添加联系人功能,联系人上限为1000人,联系人信息包括(姓名、性别、年龄、联系电话、家庭住址)
添加联系人实现步骤:
main
函数中创建通讯录联系人信息包括:姓名、性别、年龄、联系电话、家庭住址
设计如下:
// 设计联系人结构体
struct Person
{string p_name;int p_gender; // 1: 男; 2: 女int p_age;string p_phone;string p_address;
};
设计时候可以在通讯录结构体中,维护一个容量为1000的存放联系人的数组,并记录当前通讯录中联系人数量
设计如下:
// 设计通讯录结构体
struct AddressBooks
{// 通信录中保存的联系人数组Person person_arr[MAX];// 初始化通讯录中当前人员个数(最后一个联系人的索引)int p_last_idx;
};
main
函数中创建通讯录添加联系人函数封装好后,在main函数中创建一个通讯录变量,这个就是我们需要一直维护的通讯录。
int main() {// 创建通讯录结构体变量AddressBooks abs;// 初始化通讯录中当前人员个数(最后一个联系人的索引)abs.p_last_idx = 0;}
思路:添加联系人前先判断通讯录是否已满,如果满了就不再添加,未满情况将新联系人信息逐个加入到通讯录。
添加联系人代码:
// 1. 添加联系人
void add_person(AddressBooks* abs) {// 判断通讯录是否满了if (abs->p_last_idx == MAX) {cout << "通讯录已满,无法添加!" << endl;return; // 这里的return表明当前函数结束}else {// 添加具体联系人// 姓名string name;cout << "请输入姓名: ";cin >> name;abs->person_arr[abs->p_last_idx].p_name = name;// 性别int gender = 0;cout << "请输入性别(1为男性, 2为女性): ";while (true){cin >> gender;if (gender == 1 || gender == 2) {abs->person_arr[abs->p_last_idx].p_gender = gender;break; // 停止无限循环}else {cout << "您的输入有误,请重新输入: ";}}// 年龄int age = 0;cout << "请输入年龄: ";while (true){cin >> age;if (age <= 0 || age >= 150){cout << "您的输入有误,请重新输入: ";}else{abs->person_arr[abs->p_last_idx].p_age = age;break; // 停止无限循环}}// 电话cout << "请输入联系电话(移动号码或固定号码): ";string phone;while (true){cin >> phone;if (phone.length() != 11 && phone.length() != 7){cout << "您输入的联系方式有误,请重新输入: ";}else{abs->person_arr[abs->p_last_idx].p_phone = phone;break; // 停止无限循环}}// 住址cout << "请输入家庭住址: ";string address;cin >> address;abs->person_arr[abs->p_last_idx].p_address = address;// 添加成功后,让最后一个联系的索引+1cout << "联系人[" << name << "]添加成功!" << endl;abs->p_last_idx += 1;// 添加清屏操作system("pause"); // 请按任意键继续system("cls"); // 清屏操作: cls = clear screen}
}
测试效果如图:
功能描述:显示通讯录中已有的联系人信息
显示联系人实现步骤:
思路:判断如果当前通讯录中没有人员,就提示记录为空,人数大于0,显示通讯录中信息。
显示联系人代码:
// 2. 显示所有联系人
void show_person(AddressBooks* abs) {// 判断通讯录中人数是否为0if (abs->p_last_idx == 0){cout << "通讯录为空,请添加联系人" << endl;}else{for (int i = 0; i < abs->p_last_idx; i++){ cout << "[" << i + 1 << "]: " << abs->person_arr[i].p_name << endl;cout << "\t性别: " << (abs->person_arr[i].p_gender == 1 ? "男" : "女") << endl;cout << "\t年龄: " << abs->person_arr[i].p_age << endl;cout << "\t电话: " << abs->person_arr[i].p_phone << endl;cout << "\t住址: " << abs->person_arr[i].p_address << endl;cout << "-------------------------------" << endl;}}system("pause");system("cls");
}
功能描述:按照姓名进行删除指定联系人
删除联系人实现步骤:
设计思路:删除联系人前,我们需要先判断用户输入的联系人是否存在。
因此我们可以把检测联系人是否存在封装成一个函数中:
// 检测联系人是否存在,如果存在则返回对应索引,不存在返回-1
int is_exist(AddressBooks* abs, string name) {/** abs: 通讯录地址* name: 要删除人的名字*/for (int i = 0; i < abs->p_last_idx; i++){if (abs->person_arr[i].p_name == name) // 找到了,返回对应的idx{return i;}}// 走完了for循环还是没有找到return -1;
}
根据用户输入的联系人判断该通讯录中是否有此人查找到进行删除,并提示删除成功
查不到提示查无此人。
// 删除指定的联系人
void del_person(AddressBooks* abs) {cout << "请输入您要删除的联系人: ";string delete_name;cin >> delete_name;int res = is_exist(abs, delete_name);if (res != -1){for (int i = res; i < abs->p_last_idx; i++){// 数据前移abs->person_arr[i] = abs->person_arr[i + 1];}// 更新通讯录最后一个人员的索引abs->p_last_idx -= 1;cout << "删除成功..." << endl;}else{cout << "查无此人!" << endl;}system("pause");system("cls");
}
功能描述:按照姓名查看指定联系人信息
查找联系人实现步骤:
实现思路:判断用户指定的联系人是否存在,如果存在显示信息,不存在则提示查无此人。
查找联系人代码:
// 4. 查找指定联系人信息
void find_person(AddressBooks* abs) {cout << "请输入您要查找的联系人: ";string find_name;cin >> find_name;// 判断指定联系人是否存在int res = is_exist(abs, find_name);if (res != -1){cout << "[" << res + 1 << "]: " << abs->person_arr[res].p_name << endl;cout << "\t性别: " << (abs->person_arr[res].p_gender == 1 ? "男" : "女") << endl;cout << "\t年龄: " << abs->person_arr[res].p_age << endl;cout << "\t电话: " << abs->person_arr[res].p_phone << endl;cout << "\t住址: " << abs->person_arr[res].p_address << endl;cout << "-------------------------------" << endl;}else{cout << "查无此人!" << endl;}system("pause");system("cls");
}
功能描述:按照姓名重新修改指定联系人
修改联系人实现步骤
实现思路:查找用户输入的联系人,如果查找成功进行修改操作,查找失败提示查无此人。
修改联系人代码:
// 5. 修改指定联系人信息
void modify_person(AddressBooks* abs) {cout << "请输入您要修改的联系人: ";string name;cin >> name;int res = is_exist(abs, name);if (res != -1){// 姓名string name;cout << "请输入姓名(不修改输入0): ";cin >> name;if (name != "0"){abs->person_arr[res].p_name = name;}// 性别string gender;while (true){cout << "请输入性别(不修改输入0): ";cin >> gender;if (gender != "0"){if (gender == "1"){abs->person_arr[res].p_gender = 1;break;}else if (gender == "2"){abs->person_arr[res].p_gender = 2;break;}else{cout << "您输入的性别有误(请输入1或2)" << endl;}}else{break;}}// 年龄int age;while (true){cout << "请输入年龄(不修改输入0): ";cin >> age;if (age == 0){break;}else{if (age <= 0 || age >= 150){cout << "您的输入有误,请重新输入" << endl;}else{abs->person_arr[res].p_age = age;break;}}}// 电话cout << "请输入电话(不修改输入0): ";string phone;while (true){ cin >> phone;if (phone == "0"){break;}if (phone.length() != 11 && phone.length() != 7){cout << "您输入的联系方式有误,请重新输入(移动号码或固定号码): " << endl;}else{abs->person_arr[res].p_phone = phone;break; }}// 地址cout << "请输入地址(不修改输入0): ";string address;cin >> address;if (address != "0"){abs->person_arr[res].p_address = address;}cout << "修改成功!" << endl;}else{cout << "查无此人!" << endl;}system("pause");system("cls");
}
功能描述:清空通讯录中所有信息清空联系人
实现步骤:
实现思路:将通讯录所有联系人信息清除掉,只要将通讯录记录的联系人数量置为0,做逻辑清空即可。
清空联系人代码:
// 6. 清空所有联系人
void clear_all_persons(AddressBooks* abs) {abs->p_last_idx = 0;cout << "通讯录已清空..." << endl;system("pause");system("cls");
}
#include // 屏幕中输入输出都需要这个头文件
using namespace std; // 使用标准的命名空间
#include
#define MAX 1000 // 定义一个宏常量// 设计联系人结构体
struct Person
{string p_name;int p_gender; // 1: 男; 2: 女int p_age;string p_phone;string p_address;
};// 设计通讯录结构体
struct AddressBooks
{// 通信录中保存的联系人数组Person person_arr[MAX];// 初始化通讯录中当前人员个数(最后一个联系人的索引)int p_last_idx;
};// 1. 添加联系人
void add_person(AddressBooks* abs) {// 判断通讯录是否满了if (abs->p_last_idx == MAX) {cout << "通讯录已满,无法添加!" << endl;return; // 这里的return表明当前函数结束}else {// 添加具体联系人// 姓名string name;cout << "请输入姓名: ";cin >> name;abs->person_arr[abs->p_last_idx].p_name = name;// 性别int gender = 0;cout << "请输入性别(1为男性, 2为女性): ";while (true){cin >> gender;if (gender == 1 || gender == 2) {abs->person_arr[abs->p_last_idx].p_gender = gender;break; // 停止无限循环}else {cout << "您的输入有误,请重新输入: ";}}// 年龄int age = 0;cout << "请输入年龄: ";while (true){cin >> age;if (age <= 0 || age >= 150){cout << "您的输入有误,请重新输入: ";}else{abs->person_arr[abs->p_last_idx].p_age = age;break; // 停止无限循环}}// 电话cout << "请输入联系电话(移动号码或固定号码): ";string phone;while (true){cin >> phone;if (phone.length() != 11 && phone.length() != 7){cout << "您输入的联系方式有误,请重新输入: ";}else{abs->person_arr[abs->p_last_idx].p_phone = phone;break; // 停止无限循环}}// 住址cout << "请输入家庭住址: ";string address;cin >> address;abs->person_arr[abs->p_last_idx].p_address = address;// 添加成功后,让最后一个联系的索引+1cout << "联系人[" << name << "]添加成功!" << endl;abs->p_last_idx += 1;// 添加清屏操作system("pause"); // 请按任意键继续system("cls"); // 清屏操作: cls = clear screen}
}// 2. 显示所有联系人
void show_person(AddressBooks* abs) {// 判断通讯录中人数是否为0if (abs->p_last_idx == 0){cout << "通讯录为空,请添加联系人" << endl;}else{for (int i = 0; i < abs->p_last_idx; i++){ cout << "[" << i + 1 << "]: " << abs->person_arr[i].p_name << endl;cout << "\t性别: " << (abs->person_arr[i].p_gender == 1 ? "男" : "女") << endl;cout << "\t年龄: " << abs->person_arr[i].p_age << endl;cout << "\t电话: " << abs->person_arr[i].p_phone << endl;cout << "\t住址: " << abs->person_arr[i].p_address << endl;cout << "-------------------------------" << endl;}}system("pause");system("cls");
}// 检测联系人是否存在,如果存在则返回对应索引,不存在返回-1
int is_exist(AddressBooks* abs, string name) {/** abs: 通讯录地址* name: 要删除人的名字*/for (int i = 0; i < abs->p_last_idx; i++){if (abs->person_arr[i].p_name == name) // 找到了,返回对应的idx{return i;}}// 走完了for循环还是没有找到return -1;
}// 删除指定的联系人
void del_person(AddressBooks* abs) {cout << "请输入您要删除的联系人: ";string delete_name;cin >> delete_name;int res = is_exist(abs, delete_name);if (res != -1){for (int i = res; i < abs->p_last_idx; i++){// 数据前移abs->person_arr[i] = abs->person_arr[i + 1];}// 更新通讯录最后一个人员的索引abs->p_last_idx -= 1;cout << "删除成功..." << endl;}else{cout << "查无此人!" << endl;}system("pause");system("cls");
}// 4. 查找指定联系人信息
void find_person(AddressBooks* abs) {cout << "请输入您要查找的联系人: ";string find_name;cin >> find_name;// 判断指定联系人是否存在int res = is_exist(abs, find_name);if (res != -1){cout << "[" << res + 1 << "]: " << abs->person_arr[res].p_name << endl;cout << "\t性别: " << (abs->person_arr[res].p_gender == 1 ? "男" : "女") << endl;cout << "\t年龄: " << abs->person_arr[res].p_age << endl;cout << "\t电话: " << abs->person_arr[res].p_phone << endl;cout << "\t住址: " << abs->person_arr[res].p_address << endl;cout << "-------------------------------" << endl;}else{cout << "查无此人!" << endl;}system("pause");system("cls");
}// 5. 修改指定联系人信息
void modify_person(AddressBooks* abs) {cout << "请输入您要修改的联系人: ";string name;cin >> name;int res = is_exist(abs, name);if (res != -1){// 姓名string name;cout << "请输入姓名(不修改输入0): ";cin >> name;if (name != "0"){abs->person_arr[res].p_name = name;}// 性别string gender;while (true){cout << "请输入性别(不修改输入0): ";cin >> gender;if (gender != "0"){if (gender == "1"){abs->person_arr[res].p_gender = 1;break;}else if (gender == "2"){abs->person_arr[res].p_gender = 2;break;}else{cout << "您输入的性别有误(请输入1或2)" << endl;}}else{break;}}// 年龄int age;while (true){cout << "请输入年龄(不修改输入0): ";cin >> age;if (age == 0){break;}else{if (age <= 0 || age >= 150){cout << "您的输入有误,请重新输入" << endl;}else{abs->person_arr[res].p_age = age;break;}}}// 电话cout << "请输入电话(不修改输入0): ";string phone;while (true){ cin >> phone;if (phone == "0"){break;}if (phone.length() != 11 && phone.length() != 7){cout << "您输入的联系方式有误,请重新输入(移动号码或固定号码): " << endl;}else{abs->person_arr[res].p_phone = phone;break; }}// 地址cout << "请输入地址(不修改输入0): ";string address;cin >> address;if (address != "0"){abs->person_arr[res].p_address = address;}cout << "修改成功!" << endl;}else{cout << "查无此人!" << endl;}system("pause");system("cls");
}// 6. 清空联系人
void clear_all_persons(AddressBooks* abs) {cout << "[二次确认]确定要清空通讯录吗?(Y/N): ";string confirmation;while (true){cin >> confirmation;if (confirmation == "Y"){// 将最后一个联系人的索引置为0,做逻辑清空操作abs->p_last_idx = 0;cout << "通讯录已清空..." << endl;break;}else if (confirmation == "N"){cout << "操作取消" << endl;break;}else{cout << "请输入Y/N: ";}}system("pause");system("cls");
}// 菜单界面
void show_menu() {cout << "*****************************" << endl;cout << "*****\t1. 添加联系人\t*****" << endl;cout << "*****\t2. 显示联系人\t*****" << endl;cout << "*****\t3. 删除联系人\t*****" << endl;cout << "*****\t4. 查找联系人\t*****" << endl;cout << "*****\t5. 修改联系人\t*****" << endl;cout << "*****\t6. 清空联系人\t*****" << endl;cout << "*****\t0. 退出通讯录\t*****" << endl;cout << "*****************************" << endl;
}int main() {// 创建通讯录结构体变量AddressBooks abs;// 初始化通讯录中当前人员个数(最后一个联系人的索引)abs.p_last_idx = 0;int select = 0; // 用户选择输入的变量while (true) // 大循环{show_menu();cout << "请选择功能: ";cin >> select;// 根据输入做出判断switch (select){case 1: // 1. 添加联系人add_person(&abs); // 用地址传递,以修改实参break;case 2: // 2. 显示联系人show_person(&abs);break;case 3: // 3. 删除联系人del_person(&abs);break;case 4: // 4. 查找联系人find_person(&abs);break;case 5: // 5. 修改联系人modify_person(&abs);break;case 6: // 6. 清空联系人clear_all_persons(&abs);break;case 0: // 0. 退出通讯录cout << "欢迎下次使用!" << endl;system("pause"); // 请按任意键继续return 0; // main函数的return -> 退出main函数break;default:cout << "您的输入无效!" << endl;break;}}system("pause");return 0; // 返回正常退出值
}