# C++ 初识
# 第一个 C++ 程序
编写一个 C++ 程序分 4 个步骤
- 创建项目
- 创建文件
- 编写代码
- 运行程序
示例:
// 引入输入输出流库,用于使用 cout 和 endl 等标准输入输出功能 | |
#include <iostream> | |
// 使用标准命名空间 std,避免每次调用标准库函数时都要写 std:: | |
using namespace std; | |
// 主函数,程序的入口点 | |
int main() | |
{ | |
// 使用 cout 输出 "Hello World!" 到控制台 | |
//cout 是标准输出流对象,用于将数据输出到控制台 | |
// << 是流插入运算符,用于将右侧的内容插入到左侧的流中 | |
// "Hello World!" 是要输出的字符串 | |
//endl 是换行符,表示结束当前行并刷新输出缓冲区 | |
cout << "Hello World!" << endl; | |
// 返回 0,表示程序正常结束 | |
// 在 main 函数中,返回 0 通常表示程序执行成功 | |
return 0; | |
} |
# 注释
作用:在代码中加入一些说明和解释,方便自己或他人阅读代码
两种格式
- 单行注释:
// 描述信息
- 通常放在一行代码的上方,或者一条语句的末尾,对该行代码说明
- 多行注释:
/* 描述信息 */
- 通常放在一段代码的上方,,对该段代码做整体说明
# 变量
作用:给一段指定的内存空间起名,方便操作这段内存
语法: 数据类型 变量名 = 初始值;
示例:
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
// 变量的定义 | |
// 语法: 数据类型 变量名 = 初始值; | |
int month = 12; | |
cout << "一年有" << month << "月" << endl; | |
return 0; | |
} |
# 常量
作用:用于记录程序中不可更改的数据
C++ 定义常量两种方式
- #define 宏常量:
#define 常量名 常量值
- 通常在文件上方定义,表示一个常量
- **const ** 修饰的变量:
const 数据类型 常量名 = 常量值
- 通常在变量定义前加关键字 const,修饰该变量为常量,不可修改
示例:
#include <iostream> | |
using namespace std; | |
// 常量定义的方式 | |
// 1.#define 宏常量 | |
// 2.const 修饰的变量 | |
// 宏常量 | |
#define DAY 7 | |
// DAY = 14; DAY 是常量,一旦修改就会保错 | |
int main() | |
{ | |
const int MONTH = 12; | |
// MONTH = 14; const 修饰的也是常量 | |
cout << "一周有" << DAY << "天" << endl; | |
cout << "一年有" << MONTH << "月" << endl; | |
return 0; | |
} |
# 关键字
作用:关键字是 C++ 中预留的单词(标识符)
- 在定义变量或常量时,不能使用关键字
C++ 关键字如下:
asm | else | new | this |
---|---|---|---|
auto | enum | operator | throw |
bool | explicit | private | true |
break | export | protected | try |
case | extern | public | typedef |
catch | false | register | typeid |
char | float | reinterpret_cast | typename |
class | for | return | union |
const | friend | short | unsigned |
const_cast | goto | signed | using |
continue | if | sizeof | virtual |
default | inline | static | void |
delete | int | static_cast | volatile |
do | long | struct | wchar_t |
double | mutable | switch | while |
dynamic_cast | namespace | template |
# 标识符命名规则
作用:C++ 规定给标识符(变量,常量)命名时,有一套自己的规则
- 标识符不能是关键字
- 标识符只能由字母,数字,下划线组成
- 第一个字符必须为字母或下划线
- 标识符中字母区分大小写
建议:给变量起名时,做到见名知意
# 数据类型
C++ 规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存
# 整型
作用:整型变量表示的是整数类型的数据
C++ 中能够表示整型的类型有以下几种方式,区别在所占内存空间不同
数据类型 | 占用空间(Byte) | 取值范围 |
---|---|---|
short | 2 | (-215~215-1) |
int | 4 | (-231~231-1) |
long | Windows 4 Linux 4 ,8 | (-231~231-1) |
long long | 8 | (-263~263-1) |
示例:
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
// 8002 | |
// 1000 0000 0000 0010 补码 | |
// 1111 1111 1111 1101 反码 | |
// 1111 1111 1111 1110 原码 -32766 | |
// 整型 | |
// 1. 短整型 (-32768~32767) | |
short num1 = 0xffff; | |
// 2. 整型 | |
int num2 = 32768; | |
// 1. 长整型 | |
long num3 = 10; | |
// 1. 长长整型 | |
long long num4 = 10; | |
cout << "num1 = " << num1 << endl; | |
cout << "num2 = " << num2 << endl; | |
cout << "num3 = " << num3 << endl; | |
cout << "num4 = " << num4 << endl; | |
return 0; | |
} |
# sizeof 关键字
作用:利用 sizeof 关键字可以获取数据类型所占内存的大小
语法: sizeof(数据类型/变量);
示例:
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
cout << "short 类型所占内存空间为:" << sizeof(short) << "字节" << endl; | |
cout << "int 类型所占内存空间为:" << sizeof(int) << "字节" << endl; | |
cout << "long 类型所占内存空间为:" << sizeof(long) << "字节" << endl; | |
cout << "long long 类型所占内存空间为:" << sizeof(long long) << "字节" << endl; | |
return 0; | |
} |
# 浮点型
作用:用于表示小数
浮点型分两种:
- 单精度 float
- 双精度 double
两者的区别在于所占内存空间不同,表示的有效数字范围不同。
数据类型 | 占用空间 | 有效数字范围 |
---|---|---|
float | 4 Byte | 7 位有效数字 |
double | 8 Byte | 15~16 位有效数字 |
示例:
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
// 浮点数默认只显示 6 位有效数字 | |
// 1. 单精度 float | |
float f1 = 3.1415926f; | |
cout << "f1 = " << f1 << endl; | |
// 2. 双精度 double | |
double d1 = 3.1415926; | |
cout << "d1 = " << d1 << endl; | |
// 统计 float 和 double 占用内存空间 | |
cout << "float 占用内存空间为:" << sizeof(float) << "字节" << endl; // 4Byte | |
cout << "double 占用内存空间为:" << sizeof(double) << "字节" << endl; // 8Byte | |
// 科学计数法 | |
//e 后面为正数 3*10^2 | |
float f2 = 3e2; | |
//e 后面为负数 3*0.1^2 | |
float f3 = 3e-2; | |
cout << "f2 = " << f2 << endl; | |
cout << "f3 = " << f3 << endl; | |
return 0; | |
} |
# 字符型
作用:字符型变量用于显示单个字符
语法: char ch = 'a';
注意 1:在显示字符型变量时,用单引号将字符包起来,不要用双引号
注意 2:单引号内只能有一个字符,不可以是字符串
- C 和 C++ 中字符型变量只占用 1 字节
- 字符型变量并不是把字符本身放到内存中存储,而是是将对应的 ASCII 编码值放入存储单元
示例:
#include <iostream> | |
using namespace std; | |
int main() { | |
// 1. 字符型变量创建方式 | |
char ch1 = 'a'; | |
// 2. 字符型变量所占内存大小 | |
cout << "char 所占内存大小:" << sizeof(char) << "字节" << endl; | |
// 3. 字符型变量常见错误 | |
//char ch2 = "b"; 创建字符型变量时候,要用单引号 | |
//char ch2 = 'abcef'; 创建字符型的变量时候,单引号内只能有一个字符 | |
// 4. 字符型变量对应 ASCII 编码 | |
cout << "a对应的ASCII码值:" << (int)ch1 << endl; | |
char ch = 98; | |
cout << "ch = " << ch << endl; | |
return 0; | |
} |
ASCII 码大致由以下两部分组成:
- ASCII 非打印字符:ASCII 表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备
- ASCII 打印字符:数字 32-126 分配给了能在键盘上找到的字符,当查看或打印文档时就会出现
# 转义字符
作用:用于表示一些不能显示出来的 ASCII 字符
常用的转义字符有: \n \\ \t
转义字符对照表
转义字符 | 意义 | ASCLL 码值 (十进制) |
---|---|---|
\a | 响铃 (BEL) | 007 |
\b | 退格 (BS) ,将当前位置移到前一列 | 008 |
\f | 换页 (FF),将当前位置移到下页开头 | 012 |
\n | 换行 (LF) ,将当前位置移到下一行开头 | 010 |
\r | 回车 (CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表 (HT) (跳到下一个 TAB 位置) | 009 |
\v | 垂直制表 (VT) | 011 |
' | 代表一个单引号 | 039 |
" | 代表一个双引号字符 | 034 |
\ | 代表一个反斜线字符 ''' | 092 |
? | 代表一个问号 | 063 |
\0 | 空字符 (NUL) | 000 |
\ddd | 1 到 3 位八进制数所代表的任意字符 | 三位八进制 |
\xhh | 十六进制所代表的任意字符 | 十六进制 |
# 字符串型
作用:表示一串字符
两种风格
- C 风格字符串:
char 变量名[] = "字符串值";
示例:
#include <iostream> | |
using namespace std; | |
int main() { | |
char ch[] = "你好!"; | |
cout << ch << endl; | |
return 0; | |
} |
注意:C 风格的字符串要双引号括起来
- C++ 风格字符串:
string 变量名 = "字符串值";
示例:
#include <iostream> | |
#include <string> | |
using namespace std; | |
int main() { | |
// C++ 语言风格字符串 | |
// 包含一个头文件 #include <string> | |
string ch1 = "你好!"; | |
cout << ch1 << endl; | |
return 0; | |
} |
注意:C++ 风格的字符串,需要引入头文件
# 布尔类型 bool
作用:布尔数据类型代表真或假的值
bool 类型只有两个值:
- true --- 真(本质是 1)
- false --- 假(本质是 0)
bool 类型占一个字节大小
示例:
#include <iostream> | |
using namespace std; | |
int main() { | |
bool flag = true; | |
cout << "true = " << flag << endl; // 1 | |
flag = false; | |
cout << "false = " << flag << endl; // 0 | |
//bool 所占内存空间 | |
cout << "bool类型所占空间:" << sizeof(bool) << endl; | |
return 0; | |
} |
# 数据的输入
作用:用于从键盘的输入获取数据
关键字:cin
语法: cin >> 变量
示例:
#include <iostream> | |
#include <string> | |
using namespace std; | |
int main() { | |
// 整型 | |
int a = 0; | |
cout << "请输入一个整型:"; | |
cin >> a; | |
cout << "a = " << a << endl; | |
// 浮点型 | |
double d = 0.0; | |
cout << "请输入一个浮点型:"; | |
cin >> d; | |
cout << "d = " << d << endl; | |
// 字符型 | |
char ch = ' '; | |
cout << "请输入一个字符型:"; | |
cin >> ch; | |
cout << "ch = " << ch << endl; | |
// 字符串型 | |
string str = ""; | |
cout << "请输入一个字符串型:"; | |
cin >> str; | |
cout << "str = " << str << endl; | |
// 布尔类型 | |
bool flag = false; | |
cout << "请输入一个布尔类型:"; | |
cin >> flag; //bool 类型 只要是非 0 都为真 | |
cout << "flag = " << flag << endl; | |
return 0; | |
} |
注意:在 C++ 中,
std::cin
对于布尔类型(bool
)的输入处理方式是基于整数的。具体来说:
- 如果你输入
0
,std::cin
会将其解释为false
。- 如果你输入任何非零整数(例如
1
、2
、-1
等),std::cin
会将其解释为true
。- 如果你输入字符串(例如
"true"
或"false"
),std::cin
无法直接将其转换为布尔值,会导致输入失败,并将flag
保持为默认值(在你的代码中是false
)。因此,当你输入
"true"
时,std::cin
无法将其解析为布尔值,输入操作失败,flag
的值仍然是false
,所以输出结果为0
。
# 运算符
# 算术运算符
作用:用于处理四则运算
算术运算符包括以下符号:
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
-- | 自减运算符,整数值减少 1 | A-- 将得到 9 |
示例:
四则运算
#include <iostream> | |
using namespace std; | |
int main() { | |
int n1 = 10; | |
int n2 = 20; | |
double d = 0.5; | |
cout << "加:" << (n1 + n2) << endl; | |
cout << "减:" << (n1 - n2) << endl; | |
cout << "乘:" << (n1 * n2) << endl; | |
// 两数相除,除数不可以为 0 | |
// 两个整数相除结果依然是整数 | |
cout << "整数除:" << (n1 / n2) << endl; | |
cout << "小数除:" << (n2 / d) << endl; | |
// 两个小数可以相除 | |
double d2 = 0.25; | |
cout << "小数除:" << (d2 / d) << endl; | |
return 0; | |
} |
取模运算
#include <iostream> | |
using namespace std; | |
int main() { | |
// 取模运算本质就是求余数 | |
int n1 = 10; | |
int n2 = 3; | |
cout << "取模运算:" << (n1 % n2) << endl; | |
// 两个数相除,除数不能为 0,所以也不能做取模运算 | |
//cout << 10 % 0 << endl; | |
// C++ 规定:两个小数是不可以做取模运算的 | |
double d1 = 3.14; | |
double d2 = 2.718; | |
//cout << d1 % d2 << endl; | |
return 0; | |
} |
# 取模运算的公式
取模运算的公式可以表示为:a % b = a - (a /b) * b
其中:
a
是被除数(dividend),b
是除数(divisor),a / b
是整数除法(结果向下取整)。# 取模运算的规则
- 结果的符号与被除数相同:
- 如果
a
是正数,结果为正。- 如果
a
是负数,结果为负。- 除数不能为零:
- 如果
b
为 0,会导致运行时错误(除零错误)。- 适用于整数类型:
- 取模运算只能用于整数类型(如
int
、long
等),不能用于浮点数类型(如float
、double
)。
递增
#include <iostream> | |
using namespace std; | |
int main() { | |
int a = 5; | |
// 前缀递增 | |
int b = ++a; //a 先加 1 变成 6,然后赋值给 b | |
cout << "a = " << a << ", b = " << b << endl; // 输出 a = 6, b = 6 | |
// 后缀递增 | |
int c = a++; // 先将 a 的当前值(6)赋值给 c,然后 a 加 1 变成 7 | |
cout << "a = " << a << ", c = " << c << endl; // 输出 a = 7, c = 6 | |
return 0; | |
} |
递减
#include <iostream> | |
using namespace std; | |
int main() { | |
int a = 5; | |
// 前缀递减 | |
int b = --a; //a 先减 1 变成 4,然后赋值给 b | |
cout << "a = " << a << ", b = " << b << endl; // 输出 a = 4, b = 4 | |
// 后缀递减 | |
int c = a--; // 先将 a 的当前值(4)赋值给 c,然后 a 减 1 变成 3 | |
cout << "a = " << a << ", c = " << c << endl; // 输出 a = 3, c = 4 | |
return 0; | |
} |
# 赋值运算符
作用:用于将表达式的值赋给变量
赋值运算符:
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或赋值运算符 | C |= 2 等同于 C = C | 2 |
示例:
#include <iostream> | |
using namespace std; | |
int main() { | |
// 1. 基本赋值运算符 (`=`) | |
int a = 5; // 将 5 赋值给变量 a | |
int b = a; // 将 a 的值(5)赋值给变量 b | |
cout << "基本赋值运算符: a = " << a << ", b = " << b << endl; // 输出 a = 5, b = 5 | |
// 2. 复合赋值运算符 | |
// (1) `+=`(加后赋值) | |
a += 3; // 等价于 a = a + 3 | |
cout << "加后赋值: a = " << a << endl; // 输出 a = 8 | |
// (2) `-=`(减后赋值) | |
a -= 2; // 等价于 a = a - 2 | |
cout << "减后赋值: a = " << a << endl; // 输出 a = 6 | |
// (3) `*=`(乘后赋值) | |
a *= 4; // 等价于 a = a * 4 | |
cout << "乘后赋值: a = " << a << endl; // 输出 a = 24 | |
// (4) `/=`(除后赋值) | |
a /= 3; // 等价于 a = a / 3 | |
cout << "除后赋值: a = " << a << endl; // 输出 a = 8 | |
// (5) `%=`(取模后赋值) | |
a %= 5; // 等价于 a = a % 5 | |
cout << "取模后赋值: a = " << a << endl; // 输出 a = 3 | |
// 3. 多重赋值 | |
int x, y, z; | |
x = y = z = 10; // 将 10 赋值给 z,然后将 z 的值赋值给 y,最后将 y 的值赋值给 x | |
cout << "多重赋值: x = " << x << ", y = " << y << ", z = " << z << endl; // 输出 x = 10, y = 10, z = 10 | |
// 4. 赋值运算符的返回值 | |
int c = (a = b); // 先将 b 的值(5)赋值给 a,然后将 a 的值(5)赋值给 c | |
cout << "赋值运算符的返回值: a = " << a << ", b = " << b << ", c = " << c << endl; // 输出 a = 5, b = 5, c = 5 | |
// 5. 赋值运算符的优先级 | |
int d = 5; | |
int e = 10; | |
int f = d + (e = 3); // 先将 3 赋值给 e,然后计算 d + e | |
cout << "赋值运算符的优先级: d = " << d << ", e = " << e << ", f = " << f << endl; // 输出 d = 5, e = 3, f = 8 | |
// 6. 赋值运算符与指针 | |
int value = 10; | |
int* p1 = &value; //p1 指向 value | |
int* p2 = p1; //p2 也指向 value | |
cout << "赋值运算符与指针: value = " << value << ", *p1 = " << *p1 << ", *p2 = " << *p2 << endl; // 输出 value = 10, *p1 = 10, *p2 = 10 | |
return 0; | |
} |
# 总结
- 基本赋值运算符:
=
用于将右侧的值赋给左侧的变量。- 复合赋值运算符:
+=
、-=
、*=
、/=
和%=
等结合了算术运算和赋值运算。- 多重赋值:可以连续使用赋值运算符。
- 赋值运算符的返回值:返回被赋值的变量本身。
- 优先级:赋值运算符的优先级较低,需要注意运算顺序。
# 比较(关系)运算符
作用:用于表达式的比较,并返回一个真或假值
比较运算符:
假设变量 A 的值为 10,变量 B 的值为 20,则:
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 不为真。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A> B) 不为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A>= B) 不为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
示例:
#include <iostream> | |
using namespace std; | |
int main() { | |
// 比较运算符 | |
// == | |
int a = 1; | |
int b = 2; | |
cout<< (a==b) <<endl; // 0 | |
// > | |
cout << (a > b) << endl; // 0 | |
// < | |
cout << (a < b) << endl; // 1 | |
// <= | |
cout << (a <= b) << endl; // 1 | |
// >= | |
cout << (a >= b) << endl; // 0 | |
// != | |
cout << (a != b) << endl; // 1 | |
return 0; | |
} |
# 逻辑运算符
作用:
逻辑运算符:
假设变量 A 的值为 1,变量 B 的值为 0,则:
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都 true,则条件为 true。 | (A && B) 为 false。 |
|| | 称为逻辑或运算符。如果两个操作数有一个为 true,则条件为 true。 | (A && B) 为 true。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态,如果条件为 true 则逻辑非运算符将使其为 false。 | !(A && B) 为 true。 |
# 程序流程结构
C/C++ 支持最基本的三种程序运行结构:顺序结构,选择结构,循环结构
- 顺序结构
- 选择结构
- 循环结构
# 选择结构
# if 语句
作用:执行满足条件的语句
if 语句的三种形式
- 单行格式 if 语句:
if(条件) {条件满足执行的语句}
- 多行格式 if 语句:
if(条件) {条件满足执行的语句} else {条件不满足执行的语句}
- 多条件的 if 语句:
if(条件1) {条件1满足执行的语句} else if(条件2) {条件2满足执行的语句} ... else {都不满足执行的语句}
嵌套 if 语句:在 if 语句中,可以嵌套使用 if 语句
练习案例:三只小猪称体重
有三只小猪 ABC,请分别输入三只小猪的体重,并且判断那只小猪最重?
#include <iostream> | |
using namespace std; | |
int main() { | |
// 定义三个变量存储三只小猪的体重 | |
int a, b, c; | |
// 变量初始化 | |
a = b = c = 0; | |
cout << "请输入小猪A的体重:"; | |
cin >> a; | |
cout << "请输入小猪B的体重:"; | |
cin >> b; | |
cout << "请输入小猪C的体重:"; | |
cin >> c; | |
// 先判断 A 和 B 谁重 | |
// A 重 | |
if (a > b) { | |
// 比较 A 和 C | |
if (a > c) { | |
cout << "A最重"; | |
} | |
else { | |
cout << "C最重"; | |
} | |
} | |
// B 重 | |
else { | |
// 比较 B 和 C | |
if (b > c) { | |
cout << "B最重"; | |
} | |
else { | |
cout << "C最重"; | |
} | |
} | |
return 0; | |
} |
# 三目运算符
作用:通过三目运算符实现简单的判断
语法: 表达式1 ? 表达式2 : 表达式3
解释:
- 如果表达式 1 的值为真,执行表达式 2,并返回表达式 2 的结果
- 如果表达式 1 的值为假,执行表达式 3,并返回表达式 3 的结果
示例:
#include <iostream> | |
using namespace std; | |
int main() { | |
// 三目运算符 | |
// 创建 3 个变量 a b c | |
// 将 a 和 b 做比较,将变量大的值赋给 c | |
int a = 10; | |
int b = 20; | |
int c = 0; | |
c = (a > b ? a : b); // 20 | |
cout << "c = " << c << endl; | |
// C++ 中三目运算符返回的是变量,可以继续赋值 | |
(a > b ? a : b) = 100; | |
cout << "a = " << a << endl; // 10 | |
cout << "b = " << b << endl; // 100 | |
return 0; | |
} |
# switch 语句
作用:执行多条件分支语句(比 if 语句效率高)
语法:
switch(表达式){ | |
case 常量1: //case 当表达式的值等于常量 1 的时候 | |
语句块1; | |
break; //break 退出 终止 switch | |
case 常量2: | |
语句块2; | |
break; | |
………… | |
case 常量n: | |
语句块n; | |
break; | |
default: | |
default 语句块; | |
break; | |
} |
示例:
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
char c = ' '; | |
cout << "请输入一个字符[a-g]:"; | |
cin >> c; | |
// switch | |
// 表达式:任何有值都可以看成一个表达式 | |
switch (c) | |
{ | |
case 'a': | |
cout << "今天星期一" << endl; | |
break; | |
case 'b': | |
cout << "今天星期二" << endl; | |
break; | |
case 'c': | |
cout << "今天星期三" << endl; | |
break; | |
case 'd': | |
cout << "今天星期四" << endl; | |
break; | |
case 'e': | |
cout << "今天星期五" << endl; | |
break; | |
case 'f': | |
cout << "今天星期六" << endl; | |
break; | |
case 'g': | |
cout << "今天星期天" << endl; | |
break; | |
default: | |
cout << "你输入的有误!" << endl; | |
break; | |
} | |
return 0; | |
} |
# switch 细节
- switch 语句中的 expression 是一个常量表达式,必须是一个整型(char,short,int,long 等)或枚举类型
- case 子句中的值必须是常量,而不能是变量
- default 子句是可选的,当没有匹配的 case 时,执行 default
- break 语句用来在执行完一个 case 分支后使程序跳出 switch 语句块
- 如果没有写 break,会执行下一个 case 语句块,直到遇到 break 或者执行到 switch 结尾,这个现象称为穿透
# switch 和 if 的比较
- 如果判断的具体数量不多,而且符合整型,枚举类型。虽然两个语句都可以使用,建议使用 switch 语句
- 其他情况 **: 对区间判断 **,对结果为真假的判断,使用 if ,if 的使用范围更广
# 循环结构
# while 循环语句
作用:满足循环条件,执行循环语句
语法: while(循环条件) {循环语句;}
解释:只要循环条件为真,就执行循环语句
# 猜数字游戏
#include <iostream> | |
//time 系统时间 头文件包含 | |
#include <ctime> | |
using namespace std; | |
int main() { | |
// 添加随机种子 利用当前系统时间生成随机数,防止每次随机都一样 | |
srand((unsigned int)time(NULL)); | |
// 1. 系统生成随机数 | |
int num = rand() % 100 + 1; //rand ()%100 生成 0 ~ 99 的随机数 | |
// 2. 玩家进行猜测 | |
int value = 0; | |
int number = 1; | |
while (number < 6) { | |
cout << "请输入猜测的数字:"; | |
cin >> value; | |
// 3. 判断玩家的猜测 | |
// 猜对 退出游戏 | |
if (num == value) { | |
cout << "你猜对了,就是" << value << endl; | |
cout << "游戏结束!" << endl; | |
break; | |
} | |
// 猜错 提示猜的结果 过大还是过小 重新返回第 2 步 | |
else if (value > num) { | |
if (number >= 5) { | |
cout << "你猜的数字大了!你已经猜了5次,游戏结束,你失败了!" << endl; | |
} | |
else { | |
cout << "你猜的数字大了!还剩" << (5 - number) << "次机会!" << endl; | |
} | |
} | |
else { | |
if(number >= 5){ | |
cout << "你猜的数字小了!你已经猜了5次,游戏结束,你失败了!" << endl; | |
} | |
else { | |
cout << "你猜的数字小了!还剩" << (5 - number) << "次机会!" << endl; | |
} | |
} | |
++number; | |
} | |
return 0; | |
} |
# do...while 循环语句
作用: 满足循环条件,执行循环语句
语法: do{ 循环语句 } while(循环条件);
注意: 与 while 的区别在于 do...while 会先执行一次循环语句,再判断循环条件
示例:
int main() { | |
int num = 0; | |
do | |
{ | |
cout << num << endl; | |
num++; | |
} while (num < 10); | |
system("pause"); | |
return 0; | |
} |
总结:与 while 循环区别在于,do...while 先执行一次循环语句,再判断循环条件
# for 循环语句
作用: 满足循环条件,执行循环语句
语法: for(起始表达式;条件表达式;末尾循环体) { 循环语句; }
示例:
int main() { | |
for (int i = 0; i < 10; i++) | |
{ | |
cout << i << endl; | |
} | |
system("pause"); | |
return 0; | |
} |
注意:for 循环中的表达式,要用分号进行分隔
总结:while , do...while, for 都是开发中常用的循环语句,for 循环结构比较清晰,比较常用
# 嵌套循环
介绍
- 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for,while,do..while 均可以作为外层循环和内层循环(建议一般使用两层,最多不要超过 3 层)
- 实质上,** 嵌套循环就是把内层循环当成外层循环的循环体。** 当只有内层循环的循环条件为 false 时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次循环
- 设外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n=mn 次
# 跳转语句
# break 语句
作用: 用于跳出选择结构或者循环结构
break 使用的时机:
- 出现在 switch 条件语句中,作用是终止 case 并跳出 switch
- 出现在循环语句中,作用是跳出当前的循环语句
- 出现在嵌套循环中,跳出最近的内层循环语句
示例 1:
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:
int main() { | |
//2、在循环语句中用 break | |
for (int i = 0; i < 10; i++) | |
{ | |
if (i == 5) | |
{ | |
break; // 跳出循环语句 | |
} | |
cout << i << endl; | |
} | |
system("pause"); | |
return 0; | |
} |
示例 3:
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 语句
作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
示例:
int main() { | |
for (int i = 0; i < 100; i++) | |
{ | |
if (i % 2 == 0) | |
{ | |
continue; | |
} | |
cout << i << endl; | |
} | |
system("pause"); | |
return 0; | |
} |
注意:continue 并没有使整个循环终止,而 break 会跳出循环
# goto 语句
作用:可以无条件跳转语句
语法: goto 标记;
解释:如果标记的名称存在,执行到 goto 语句时,会跳转到标记的位置
示例:
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 语句,以免造成程序流程混乱
# 数组
# 概述
所谓数组,就是一个集合,里面存放了相同类型的数据元素
特点 1: 数组中的每个数据元素都是相同的数据类型
特点 2: 数组是由连续的内存位置组成的
# 一维数组
# 一维数组定义方式
一维数组定义的三种方式:
数据类型 数组名[ 数组长度 ];
数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};
数据类型 数组名[ ] = { 值1,值2 ...};
示例:
int main() { | |
// 定义方式 1 | |
// 数据类型 数组名 [元素个数]; | |
int score[10]; | |
// 利用下标赋值 | |
score[0] = 100; | |
score[1] = 99; | |
score[2] = 85; | |
// 利用下标输出 | |
cout << score[0] << endl; | |
cout << score[1] << endl; | |
cout << score[2] << endl; | |
// 第二种定义方式 | |
// 数据类型 数组名 [元素个数] = {值 1,值 2 ,值 3 ...}; | |
// 如果 {} 内不足 10 个数据,剩余数据用 0 补全 | |
int score2[10] = { 100, 90,80,70,60,50,40,30,20,10 }; | |
// 逐个输出 | |
//cout << score2[0] << endl; | |
//cout << score2[1] << endl; | |
// 一个一个输出太麻烦,因此可以利用循环进行输出 | |
for (int i = 0; i < 10; i++) | |
{ | |
cout << score2[i] << endl; | |
} | |
// 定义方式 3 | |
// 数据类型 数组名 [] = {值 1,值 2 ,值 3 ...}; | |
int score3[] = { 100,90,80,70,60,50,40,30,20,10 }; | |
for (int i = 0; i < 10; i++) | |
{ | |
cout << score3[i] << endl; | |
} | |
system("pause"); | |
return 0; | |
} |
总结 1:数组名的命名规范与变量名命名规范一致,不要和变量重名
总结 2:数组中下标是从 0 开始索引
# 一维数组数组名
一维数组名称的用途:
- 可以统计整个数组在内存中的长度
- 可以获取数组在内存中的首地址
示例:
int main() { | |
// 数组名用途 | |
//1、可以获取整个数组占用内存空间大小 | |
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; | |
cout << "整个数组所占内存空间为: " << sizeof(arr) << endl; | |
cout << "每个元素所占内存空间为: " << sizeof(arr[0]) << endl; | |
cout << "数组的元素个数为: " << sizeof(arr) / sizeof(arr[0]) << endl; | |
//2、可以通过数组名获取到数组首地址 | |
cout << "数组首地址为: " << (int)arr << endl; | |
cout << "数组中第一个元素地址为: " << (int)&arr[0] << endl; | |
cout << "数组中第二个元素地址为: " << (int)&arr[1] << endl; | |
//arr = 100; 错误,数组名是常量,因此不可以赋值 | |
system("pause"); | |
return 0; | |
} |
注意:数组名是常量,不可以赋值
总结 1:直接打印数组名,可以查看数组所占内存的首地址
总结 2:对数组名进行 sizeof,可以获取整个数组占内存空间的大小
练习案例: 数组元素逆置
案例描述: 请声明一个 5 个元素的数组,并且将元素逆置.
(如原数组元素为:1,3,2,5,4; 逆置后输出结果为:4,5,2,3,1);
#include <iostream> | |
using namespace std; | |
int main() { | |
int arr[] = { 1,3,2,5,4 }; | |
int length = sizeof(arr) / sizeof(int); | |
int start = 0; | |
int end = length - 1; | |
int temp = 0; | |
cout << "交换前的顺序:"; | |
for (int i = 0; i < length;i++) { | |
cout << arr[i] << " "; | |
} | |
for (int i = 0; i < length;i++) { | |
//start < end 执行互换 | |
if (start < end){ | |
// 实现元素互换 | |
temp = arr[start]; | |
arr[start] = arr[end]; | |
arr[end] = temp; | |
// 下标更新 | |
start++; | |
end--; | |
} | |
} | |
cout << "\n交换后的顺序:"; | |
for (int i = 0; i < length;i++) { | |
cout << arr[i] << " "; | |
} | |
return 0; | |
} |
# 冒泡排序
作用: 最常用的排序算法,对数组内元素进行排序
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
- 重复以上的步骤,每次比较次数 - 1,直到不需要比较
示例: 将数组 {4,2,8,0,5,7,1,3,9} 进行升序排序
int main() { | |
int arr[9] = { 4,2,8,0,5,7,1,3,9 }; | |
for (int i = 0; i < 9 - 1; i++) | |
{ | |
for (int j = 0; j < 9 - 1 - i; j++) | |
{ | |
if (arr[j] > arr[j + 1]) | |
{ | |
int temp = arr[j]; | |
arr[j] = arr[j + 1]; | |
arr[j + 1] = temp; | |
} | |
} | |
} | |
for (int i = 0; i < 9; i++) | |
{ | |
cout << arr[i] << endl; | |
} | |
system("pause"); | |
return 0; | |
} |
# 二维数组
二维数组就是在一维数组上,多加一个维度。
# 二维数组定义方式
二维数组定义的四种方式:
数据类型 数组名[ 行数 ][ 列数 ];
数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2 } ,{数据3,数据4 } };
数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};
数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4};
建议:以上 4 种定义方式,利用第二种更加直观,提高代码的可读性
示例:
int main() { | |
// 方式 1 | |
// 数组类型 数组名 [行数][列数] | |
int arr[2][3]; | |
arr[0][0] = 1; | |
arr[0][1] = 2; | |
arr[0][2] = 3; | |
arr[1][0] = 4; | |
arr[1][1] = 5; | |
arr[1][2] = 6; | |
for (int i = 0; i < 2; i++) | |
{ | |
for (int j = 0; j < 3; j++) | |
{ | |
cout << arr[i][j] << " "; | |
} | |
cout << endl; | |
} | |
// 方式 2 | |
// 数据类型 数组名 [行数][列数] = { {数据 1,数据 2 } ,{数据 3,数据 4 } }; | |
int arr2[2][3] = | |
{ | |
{1,2,3}, | |
{4,5,6} | |
}; | |
// 方式 3 | |
// 数据类型 数组名 [行数][列数] = { 数据 1,数据 2 , 数据 3,数据 4 }; | |
int arr3[2][3] = { 1,2,3,4,5,6 }; | |
// 方式 4 | |
// 数据类型 数组名 [][列数] = { 数据 1,数据 2 , 数据 3,数据 4 }; | |
int arr4[][3] = { 1,2,3,4,5,6 }; | |
system("pause"); | |
return 0; | |
} |
总结:在定义二维数组时,如果初始化了数据,可以省略行数
# 二维数组数组名
- 查看二维数组所占内存空间
- 获取二维数组首地址
示例:
int main() { | |
// 二维数组数组名 | |
int arr[2][3] = | |
{ | |
{1,2,3}, | |
{4,5,6} | |
}; | |
cout << "二维数组大小: " << sizeof(arr) << endl; | |
cout << "二维数组一行大小: " << sizeof(arr[0]) << endl; | |
cout << "二维数组元素大小: " << sizeof(arr[0][0]) << endl; | |
cout << "二维数组行数: " << sizeof(arr) / sizeof(arr[0]) << endl; | |
cout << "二维数组列数: " << sizeof(arr[0]) / sizeof(arr[0][0]) << endl; | |
// 地址 | |
cout << "二维数组首地址:" << arr << endl; | |
cout << "二维数组第一行地址:" << arr[0] << endl; | |
cout << "二维数组第二行地址:" << arr[1] << endl; | |
cout << "二维数组第一个元素地址:" << &arr[0][0] << endl; | |
cout << "二维数组第二个元素地址:" << &arr[0][1] << endl; | |
system("pause"); | |
return 0; | |
} |
总结 1:二维数组名就是这个数组的首地址
总结 2:对二维数组名进行 sizeof 时,可以获取整个二维数组占用的内存空间大小
# 二维数组应用案例
考试成绩统计:
案例描述:有三名同学(张三,李四,王五),在一次考试中的成绩分别如下表,请分别输出三名同学的总成绩
语文 | 数学 | 英语 | |
---|---|---|---|
张三 | 100 | 100 | 100 |
李四 | 90 | 50 | 100 |
王五 | 60 | 70 | 80 |
参考答案:
int main() { | |
int scores[3][3] = | |
{ | |
{100,100,100}, | |
{90,50,100}, | |
{60,70,80}, | |
}; | |
string names[3] = { "张三","李四","王五" }; | |
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; | |
} | |
system("pause"); | |
return 0; | |
} |
# 函数
# 概述
作用: 将一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。
# 函数的定义
函数的定义一般主要有 5 个步骤:
- 返回值类型
- 函数名
- 参数表列
- 函数体语句
- return 表达式
语法:
返回值类型 函数名 (参数列表) | |
{ | |
函数体语句 | |
return表达式 | |
} |
- 返回值类型 :一个函数可以返回一个值。在函数定义中
- 函数名:给函数起个名称
- 参数列表:使用该函数时,传入的数据
- 函数体语句:花括号内的代码,函数内需要执行的语句
- return 表达式: 和返回值类型挂钩,函数执行完后,返回相应的数据
示例: 定义一个加法函数,实现两个数相加
// 函数定义 | |
int add(int num1, int num2) | |
{ | |
int sum = num1 + num2; | |
return sum; | |
} |
# 函数的调用
功能: 使用定义好的函数
语法: 函数名(参数)
示例:
// 函数定义 | |
int add(int num1, int num2) // 定义中的 num1,num2 称为形式参数,简称形参 | |
{ | |
int sum = num1 + num2; | |
return sum; | |
} | |
int main() { | |
int a = 10; | |
int b = 10; | |
// 调用 add 函数 | |
int sum = add(a, b);// 调用时的 a,b 称为实际参数,简称实参 | |
cout << "sum = " << sum << endl; | |
a = 100; | |
b = 100; | |
sum = add(a, b); | |
cout << "sum = " << sum << endl; | |
system("pause"); | |
return 0; | |
} |
总结:函数定义里小括号内称为形参,函数调用时传入的参数称为实参
# 值传递
- 所谓值传递,就是函数调用时实参将数值传入给形参
- 值传递时,如果形参发生,并不会影响实参
示例:
void swap(int num1, int num2) | |
{ | |
cout << "交换前:" << endl; | |
cout << "num1 = " << num1 << endl; | |
cout << "num2 = " << num2 << endl; | |
int temp = num1; | |
num1 = num2; | |
num2 = temp; | |
cout << "交换后:" << endl; | |
cout << "num1 = " << num1 << endl; | |
cout << "num2 = " << num2 << endl; | |
//return ; 当函数声明时候,不需要返回值,可以不写 return | |
} | |
int main() { | |
int a = 10; | |
int b = 20; | |
swap(a, b); | |
cout << "mian中的 a = " << a << endl; | |
cout << "mian中的 b = " << b << endl; | |
system("pause"); | |
return 0; | |
} |
总结: 值传递时,形参是修改不了实参的
# 函数的常见样式
常见的函数样式有 4 种
- 无参无返
- 有参无返
- 无参有返
- 有参有返
示例:
// 函数常见样式 | |
//1、 无参无返 | |
void test01() | |
{ | |
//void a = 10; // 无类型不可以创建变量,原因无法分配内存 | |
cout << "this is test01" << endl; | |
//test01 (); 函数调用 | |
} | |
//2、 有参无返 | |
void test02(int a) | |
{ | |
cout << "this is test02" << endl; | |
cout << "a = " << a << endl; | |
} | |
//3、无参有返 | |
int test03() | |
{ | |
cout << "this is test03 " << endl; | |
return 10; | |
} | |
//4、有参有返 | |
int test04(int a, int b) | |
{ | |
cout << "this is test04 " << endl; | |
int sum = a + b; | |
return sum; | |
} |
# 函数的声明
作用: 告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
- 函数的声明可以多次,但是函数的定义只能有一次
示例:
// 声明可以多次,定义只能一次 | |
// 声明 | |
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() { | |
int a = 100; | |
int b = 200; | |
cout << max(a, b) << endl; | |
system("pause"); | |
return 0; | |
} |
# 函数的分文件编写
作用: 让代码结构更加清晰
函数分文件编写一般有 4 个步骤
- 创建后缀名为.h 的头文件
- 创建后缀名为.cpp 的源文件
- 在头文件中写函数的声明
- 在源文件中写函数的定义
示例:
//swap.h 文件 | |
#include<iostream> | |
using namespace std; | |
// 实现两个数字交换的函数声明 | |
void swap(int a, int b); |
//swap.cpp 文件 | |
#include "swap.h" | |
void swap(int a, int b) | |
{ | |
int temp = a; | |
a = b; | |
b = temp; | |
cout << "a = " << a << endl; | |
cout << "b = " << b << endl; | |
} |
//main 函数文件 | |
#include "swap.h" | |
int main() { | |
int a = 100; | |
int b = 200; | |
swap(a, b); | |
system("pause"); | |
return 0; | |
} |
# 指针
# 指针的基本概念
指针的作用: 可以通过指针间接访问内存
- 内存编号是从 0 开始记录的,一般用十六进制数字表示
- 可以利用指针变量保存地址
# 指针变量的定义和使用
指针变量定义语法: 数据类型 * 变量名;
示例:
int main() { | |
//1、指针的定义 | |
int a = 10; // 定义整型变量 a | |
// 指针定义语法: 数据类型 * 变量名; | |
int * p; | |
// 指针变量赋值 | |
p = &a; // 指针指向变量 a 的地址 | |
cout << &a << endl; // 打印数据 a 的地址 | |
cout << p << endl; // 打印指针变量 p | |
//2、指针的使用 | |
// 通过 * 操作指针变量指向的内存 | |
cout << "*p = " << *p << endl; | |
system("pause"); | |
return 0; | |
} |
指针变量和普通变量的区别
- 普通变量存放的是数据,指针变量存放的是地址
- 指针变量可以通过 "*" 操作符,操作指针变量指向的内存空间,这个过程称为解引用
总结 1: 我们可以通过 & 符号 获取变量的地址
总结 2:利用指针可以记录地址
总结 3:对指针变量解引用,可以操作指针指向的内存
# 指针所占内存空间
提问:指针也是种数据类型,那么这种数据类型占用多少内存空间?
示例:
int main() { | |
int a = 10; | |
int * p; | |
p = &a; // 指针指向数据 a 的地址 | |
cout << *p << endl; //* 解引用 | |
cout << sizeof(p) << endl; | |
cout << sizeof(char *) << endl; | |
cout << sizeof(float *) << endl; | |
cout << sizeof(double *) << endl; | |
system("pause"); | |
return 0; | |
} |
总结:所有指针类型在 32 位操作系统下是 4 个字节
# 空指针和野指针
空指针:指针变量指向内存中编号为 0 的空间
用途: 初始化指针变量
注意: 空指针指向的内存是不可以访问的
示例 1:空指针
int main() { | |
// 指针变量 p 指向内存地址编号为 0 的空间 | |
int * p = NULL; | |
// 访问空指针报错 | |
// 内存编号 0 ~255 为系统占用内存,不允许用户访问 | |
cout << *p << endl; | |
system("pause"); | |
return 0; | |
} |
野指针:指针变量指向非法的内存空间
示例 2:野指针
int main() { | |
// 指针变量 p 指向内存地址编号为 0x1100 的空间 | |
int * p = (int *)0x1100; | |
// 访问野指针报错 | |
cout << *p << endl; | |
system("pause"); | |
return 0; | |
} |
总结:空指针和野指针都不是我们申请的空间,因此不要访问。
# const 修饰指针
const 修饰指针有三种情况
- const 修饰指针 --- 常量指针
- const 修饰常量 --- 指针常量
- const 即修饰指针,又修饰常量
示例:
int main() { | |
int a = 10; | |
int b = 10; | |
//const 修饰的是指针,指针指向可以改,指针指向的值不可以更改 | |
const int * p1 = &a; | |
p1 = &b; // 正确 | |
//*p1 = 100; 报错 | |
//const 修饰的是常量,指针指向不可以改,指针指向的值可以更改 | |
int * const p2 = &a; | |
//p2 = &b; // 错误 | |
*p2 = 100; // 正确 | |
//const 既修饰指针又修饰常量 | |
const int * const p3 = &a; | |
//p3 = &b; // 错误 | |
//*p3 = 100; // 错误 | |
system("pause"); | |
return 0; | |
} |
技巧:看 const 右侧紧跟着的是指针还是常量,是指针就是常量指针,是常量就是指针常量
# 指针和数组
作用: 利用指针访问数组中元素
示例:
int main() { | |
int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; | |
int * p = arr; // 指向数组的指针 | |
cout << "第一个元素: " << arr[0] << endl; | |
cout << "指针访问第一个元素: " << *p << endl; | |
for (int i = 0; i < 10; i++) | |
{ | |
// 利用指针遍历数组 | |
cout << *p << endl; | |
p++; | |
} | |
system("pause"); | |
return 0; | |
} |
# 指针和函数
作用: 利用指针作函数参数,可以修改实参的值
示例:
// 值传递 | |
void swap1(int a ,int b) | |
{ | |
int temp = a; | |
a = b; | |
b = temp; | |
} | |
// 地址传递 | |
void swap2(int * p1, int *p2) | |
{ | |
int temp = *p1; | |
*p1 = *p2; | |
*p2 = temp; | |
} | |
int main() { | |
int a = 10; | |
int b = 20; | |
swap1(a, b); // 值传递不会改变实参 | |
swap2(&a, &b); // 地址传递会改变实参 | |
cout << "a = " << a << endl; | |
cout << "b = " << b << endl; | |
system("pause"); | |
return 0; | |
} |
总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递
# 指针、数组、函数
案例描述: 封装一个函数,利用冒泡排序,实现对整型数组的升序排序
例如数组:int arr [10] = { 4,3,6,9,1,2,10,8,7,5 };
示例:
// 冒泡排序函数 | |
void bubbleSort(int * arr, int len) //int * arr 也可以写为 int arr [] | |
{ | |
for (int i = 0; i < len - 1; i++) | |
{ | |
for (int j = 0; j < len - 1 - i; j++) | |
{ | |
if (arr[j] > arr[j + 1]) | |
{ | |
int temp = arr[j]; | |
arr[j] = arr[j + 1]; | |
arr[j + 1] = temp; | |
} | |
} | |
} | |
} | |
// 打印数组函数 | |
void printArray(int arr[], int len) | |
{ | |
for (int i = 0; i < len; i++) | |
{ | |
cout << arr[i] << endl; | |
} | |
} | |
int main() { | |
int arr[10] = { 4,3,6,9,1,2,10,8,7,5 }; | |
int len = sizeof(arr) / sizeof(int); | |
bubbleSort(arr, len); | |
printArray(arr, len); | |
system("pause"); | |
return 0; | |
} |
总结:当数组名传入到函数作为参数时,被退化为指向首元素的指针
# 结构体
# 结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
# 结构体定义和使用
语法: struct 结构体名 { 结构体成员列表 };
通过结构体创建变量的方式有三种:
- struct 结构体名 变量名
- struct 结构体名 变量名 =
- 定义结构体时顺便创建变量
示例:
// 结构体定义 | |
struct student | |
{ | |
// 成员列表 | |
string name; // 姓名 | |
int age; // 年龄 | |
int score; // 分数 | |
}stu3; // 结构体变量创建方式 3 | |
int main() { | |
// 结构体变量创建方式 1 | |
struct student stu1; //struct 关键字可以省略 | |
stu1.name = "张三"; | |
stu1.age = 18; | |
stu1.score = 100; | |
cout << "姓名:" << stu1.name << " 年龄:" << stu1.age << " 分数:" << stu1.score << endl; | |
// 结构体变量创建方式 2 | |
struct student stu2 = { "李四",19,60 }; | |
cout << "姓名:" << stu2.name << " 年龄:" << stu2.age << " 分数:" << stu2.score << endl; | |
stu3.name = "王五"; | |
stu3.age = 18; | |
stu3.score = 80; | |
cout << "姓名:" << stu3.name << " 年龄:" << stu3.age << " 分数:" << stu3.score << endl; | |
system("pause"); | |
return 0; | |
} |
总结 1:定义结构体时的关键字是 struct,不可省略
总结 2:创建结构体变量时,关键字 struct 可以省略
总结 3:结构体变量利用操作符 ''.'' 访问成员
# 结构体数组
作用: 将自定义的结构体放入到数组中方便维护
语法: struct 结构体名 数组名[元素个数] = { {} , {} , ... {} }
示例:
// 结构体定义 | |
struct student | |
{ | |
// 成员列表 | |
string name; // 姓名 | |
int age; // 年龄 | |
int score; // 分数 | |
} | |
int main() { | |
// 结构体数组 | |
struct student arr[3]= | |
{ | |
{"张三",18,80 }, | |
{"李四",19,60 }, | |
{"王五",20,70 } | |
}; | |
for (int i = 0; i < 3; i++) | |
{ | |
cout << "姓名:" << arr[i].name << " 年龄:" << arr[i].age << " 分数:" << arr[i].score << endl; | |
} | |
system("pause"); | |
return 0; | |
} |
# 结构体指针
作用: 通过指针访问结构体中的成员
- 利用操作符
->
可以通过结构体指针访问结构体属性
示例:
// 结构体定义 | |
struct student | |
{ | |
// 成员列表 | |
string name; // 姓名 | |
int age; // 年龄 | |
int score; // 分数 | |
}; | |
int main() { | |
struct student stu = { "张三",18,100 }; | |
struct student * p = &stu; | |
p->score = 80; // 指针通过 -> 操作符可以访问成员 | |
cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl; | |
system("pause"); | |
return 0; | |
} |
总结:结构体指针可以通过 -> 操作符 来访问结构体中的成员
# 结构体嵌套结构体
作用: 结构体中的成员可以是另一个结构体
例如: 每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
示例:
// 学生结构体定义 | |
struct student | |
{ | |
// 成员列表 | |
string name; // 姓名 | |
int age; // 年龄 | |
int score; // 分数 | |
}; | |
// 教师结构体定义 | |
struct teacher | |
{ | |
// 成员列表 | |
int id; // 职工编号 | |
string name; // 教师姓名 | |
int age; // 教师年龄 | |
struct student stu; // 子结构体 学生 | |
}; | |
int main() { | |
struct teacher t1; | |
t1.id = 10000; | |
t1.name = "老王"; | |
t1.age = 40; | |
t1.stu.name = "张三"; | |
t1.stu.age = 18; | |
t1.stu.score = 100; | |
cout << "教师 职工编号: " << t1.id << " 姓名: " << t1.name << " 年龄: " << t1.age << endl; | |
cout << "辅导学员 姓名: " << t1.stu.name << " 年龄:" << t1.stu.age << " 考试分数: " << t1.stu.score << endl; | |
system("pause"); | |
return 0; | |
} |
总结: 在结构体中可以定义另一个结构体作为成员,用来解决实际问题
# 结构体做函数参数
作用: 将结构体作为参数向函数中传递
传递方式有两种:
- 值传递
- 地址传递
示例:
// 学生结构体定义 | |
struct student | |
{ | |
// 成员列表 | |
string name; // 姓名 | |
int age; // 年龄 | |
int score; // 分数 | |
}; | |
// 值传递 | |
void printStudent(student stu ) | |
{ | |
stu.age = 28; | |
cout << "子函数中 姓名:" << stu.name << " 年龄: " << stu.age << " 分数:" << stu.score << endl; | |
} | |
// 地址传递 | |
void printStudent2(student *stu) | |
{ | |
stu->age = 28; | |
cout << "子函数中 姓名:" << stu->name << " 年龄: " << stu->age << " 分数:" << stu->score << endl; | |
} | |
int main() { | |
student stu = { "张三",18,100}; | |
// 值传递 | |
printStudent(stu); | |
cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << " 分数:" << stu.score << endl; | |
cout << endl; | |
// 地址传递 | |
printStudent2(&stu); | |
cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << " 分数:" << stu.score << endl; | |
system("pause"); | |
return 0; | |
} |
总结:如果不想修改主函数中的数据,用值传递,反之用地址传递
# 结构体中 const 使用场景
作用: 用 const 来防止误操作
示例:
// 学生结构体定义 | |
struct student | |
{ | |
// 成员列表 | |
string name; // 姓名 | |
int age; // 年龄 | |
int score; // 分数 | |
}; | |
//const 使用场景 | |
void printStudent(const student *stu) // 加 const 防止函数体中的误操作 | |
{ | |
//stu->age = 100; // 操作失败,因为加了 const 修饰 | |
cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl; | |
} | |
int main() { | |
student stu = { "张三",18,100 }; | |
printStudent(&stu); | |
system("pause"); | |
return 0; | |
} |