C++基础入门
一、C++初识
1.1 第一个C++程序
- 创建项目
- 创建文件
- 编写代码
- 运行程序
1.1.1 创建项目
1.1.2 创建文件
1.1.3 编写代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World" << endl;
system("pause");
return 0;
}
1.1.4 运行程序
1.2 注释
**作用:**在代码中加一些说明和解释,方便自己或其他程序员阅读代码
两种格式
- 单行注释:
// 描述信息
- 多行注释:
/* 描述信息 */
1.3 变量
**作用:**给一段制定的内存空间起名,方便操作这段内存,管理内存空间
语法:数据类型 变量名 = 初始值;
示例:
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
int main()
{
int a = 10;
cout << "a = " << a << endl;
system("pause");
return 0;
}
1.4 常量
**作用:**用于记录程序中不可更改的数据
C++定义常量两种方式
- #define 宏常量:
#define 常量名 常量值
- 通常在文件上方定义,表示一个常量
- const 修饰的变量:
const 数据类型 常量名 = 常量值
- 通常在变量定义前加关键字const,修饰该变量为常量,不可修改
示例:
#include <iostream>
#define day 7 //1.#define 宏常量
using namespace std;
int main()
{
cout << "一周共有" << day << "天" << endl;
//day = 8; 会报错,不可修改
//2.const修饰的变量
const int month = 12;
//month = 13; 报错,不可修改
cout << "一年共有" << month << "月" << endl;
system("pause");
return 0;
}
1.5 关键字
**作用:**关键字是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 | esport | 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 |
提示:在给变量或者常量起名的时候,不要用c++的关键字,否则或产生歧义
1.6 标识符命名规则
**作用:**C++规定给标识符(变量、常量)命名时,有一套自己的规则
- 标识符不能是关键字
- 标识符只能由字母,数字,下划线组成 -> abc123_
- 第一个字符必须是字母或者下划线
- 标识符中字母分大小写
建议:给标识符命名时,争取见名知义,方便阅读
二、数据类型
C++规定在创建一个变量或常量时,必须要指定出相应的数据类型,否则无法给变量分配内存
2.1 整型
**作用:**整型变量表示的是整数类型的数据
C++中能够表示整型的类型有以下几种方式,区别在于所占的内存空间不同
数据类型 | 占用空间 | 取值范围 |
---|---|---|
short(短整型) | 2字节 | (-2^15 ~ 2^15-1) |
int(整型) | 4字节 | (-2^31 ~ 2^31-1) |
long(长整型) | Windows为四字节,Linux为4字节(32位),8字节(64位) | (-2^31 ~ 2^31-1) |
long long(长长整型) | 8字节 | (-2^63 ~ 2^63-1) |
#include <iostream>
using namespace std;
int main()
{
//整型 (int较常用)
//
//1、短整型(-32768 ~ 32767)
short num1 = 32768; //结果是-32768,循环回来了
//2、整型 (...~...)
int num2 = 10;
//3、长整型 (...~...)
long num3 = 10;
//4、长长整型 (...~...)
long long num4 = 10;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
cout << "num3 = " << num3 << endl;
cout << "num4 = " << num4 << endl;
return 0;
}
2.2 sizeof关键字
**作用:**利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof( 数据类型 /变量 )
示例:
#include <iostream>
using namespace std;
int main() {
//sizeof可以求出数据类型占用内存的大小
//语法:sizeof( 数据类型 / 变量 )
cout << "short 类型所占内存空间为:" << sizeof(short) << endl;//2
cout << "int 类型所占内存空间为:" << sizeof(int) << endl;//4
cout << "long 类型所占内存空间为:" << sizeof(long) << endl;//4
cout << "long long 类型所占内存空间为:" << sizeof(long) << endl;//8
//整型大小比较
// short < int <= long <= long long
return 0;
}
实型(浮点型)
**作用:**用于表示小数
浮点型变量分两种:
- 单精度 float
- 双精度 double
两者区别在于表示的有效数字范围不同:
数据类型 | 占用空间 | 有效数字范围 |
---|---|---|
float | 4字节 | 7位有效数字 |
double | 8字节 | 15~16位有效数字 |
示例:
#include <iostream>
using namespace std;
int main() {
//1.单精度 float
//2.双精度 double
//默认情况下,输出一个小数,会显示出六位有效数字,五位小数
float f1 = 3.141592653f;
double d2 = 3.14;
cout << "f1 = " << f1 << endl;
cout << "d2 = " << d2 << endl;
//统计float和double占用内存空间
// float 4
// double 8
cout << "float占用的内存空间为" << sizeof(float) << endl;
cout << "double占用的内存空间为" << sizeof(double) << endl;
//科学计数法
float f2 = 3e2; //3 * 10 ^ 2
cout << "f2 = " << f2 << endl; //300
float f3 = 3e-2; //3 * 0.1 ^ 2
cout << "f3 = " << f3 << endl; //0.03
system("pause");
return 0;
}
2.4 字符型
**作用:**字符型变量用于显示单个字符
语法:char ch = 'a';
注意1:在显示字符型变量时,用单引号将字符括起来,不用双引号
注意2:单引号只能有一个字符,不可以是字符串
-
C和C++中字符型变量只占用一个字节
-
字符型变量并不是把字符本身放在内存中存储,而是将对应的ASCII编码放入到存储单元
示例:
#include <iostream>
using namespace std;
int main() {
//1.字符型变量创建方式
char ch = 'a';
cout << ch << endl;
//2.字符型变量所占内存大小
cout << "字符型变量占用内存:" << sizeof(ch) << endl; //1
//3.字符型变量常见错误
//char ch2 = "b"; 用单引号
//char ch2 = 'abc'; 数量过多
//4.字符型变量对应ASCII编码
//a - 97
//A - 65
cout << (int)ch << endl; //97 就是 a 对应的ASCII码
system("pause");
return 0;
}
ASCII 码大致由以下两部分组成:
- ASCII 非打印字符:ASCII表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备
- ASCII 打印字符:数字 32-126 分配给了能在键盘上找到的字符,当查看或打印文档时就会出现
2.5 转移字符
**作用:**用于表示一些不能显示出来的ASCII字符
现阶段我们常用的转义字符有:\n \\ \t
转义字符 | 含义 | ASCII码 |
---|---|---|
\a | 响铃7 | 7 |
\b | 退格 | 8 |
\f | 换页 | 12 |
\n | 换行 | 10 |
\r | 回车 | 13 |
\t | 横向制表符 | 9 |
\v | 纵向制表符 | 11 |
\ | 反斜杠 | 92 |
’ | 单引号 | 39 |
" | 双引号 | 34 |
? | 问号 | 63 |
\0 | 空字符 | 0 |
\\ | 代表一个反斜线’\’ | 92 |
#include <iostream>
using namespace std;
int main() {
//转义字符
//换行符 \n
cout << "hello world\n" << endl;
//反斜杠 \\
cout << "\\" << endl;
//水平制表符 \t
//作用:可以整齐地输出数据
cout << "a\thello" << endl;
cout << "aaaaa\thello" << endl;
system("pause");
return 0;
}
2.6 字符串型
**作用:**用于表示一串字符
两种风格
-
C风格字符串:
char 变量名[] = "字符串值"
示例:
#include <iostream> using namespace std; int main() { char ch[] = "Hello World"; cout << ch << endl; return 0; }
注意:C风格的字符串要用双引号括起来
char 字符串名 []
-
C++风格字符串:
string 变量名 = "字符串值"
示例:
#include <iostream> #include <string> using namespace std; int main() { string ch = "Hello World"; cout << ch << endl; return 0; }
注意:需要包含一个头文件
#include <string>
vs2022貌似不用
2.7 布尔数据类型
**作用:**布尔数据类型代表真和假的值
bool 类型只有两个值:
-
true — 真(本质是1)(非0的其实都为真)
-
false — 假(本质是0)
bool类型占1个字节大小
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//1.创建bool数据类型
bool flag = true; //true代表真
cout << flag << endl;
bool flag2 = false; //假
cout << flag2 << endl;
//本质上 1代表真 0代表假
//2.查看bool类型所占内存空间
cout << "bool类型所占的内存空间:" << sizeof(bool) << endl; //1
return 0;
}
2.8 数据的输入
作用:用于从键盘获取数据
**关键字:**cin
语法: cin >> 变量
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//1.整型
//int a = 0;
//cout << "请给整型变量a赋值:" << endl;
//cin >> a;
//cout << "整型变量a = " << a << endl;
//2.浮点型
//float b = 3.14f;
//cout << "请给浮点型变量b赋值:" << endl;
//cin >> b;
//cout << "浮点型变量b = " << b << endl;
//3.字符型
//char ch = 'a';
//cout << "请给字符型变量ch赋值:" << endl;
//cin >> ch;
//cout << "字符型变量ch = "<< ch << endl;
//4.字符串型
//string str = "hello";
//cout << "请给字符串型变量str赋值:" << endl;
//cin >> str;
//cout << "字符串变量str = " << str << endl;
//5.布尔类型(非0的值都为真)
bool flag = false;
cout << "请给布尔类型的flag赋值:" << endl;
cin >> flag;
cout << "布尔类型的flag为" << flag << endl;
return 0;
}
三、运算符
**作用:**用于执行代码的运算
本章我们主要讲解一下几类运算符
运算符类型 | 作用 |
---|---|
算术运算符 | 用于四则运算 |
赋值运算符 | 用于将表达式的值赋给变量 |
比较运算符 | 用于表达式的比较,并返回一个真值或者假值 |
逻辑运算符 | 用于根据表达式的值返回真值或者假值 |
3.1 算数运算符
**作用:**用于四则运算
算数运算符包括以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | -3 | -3 |
+ | 加 | 10+5 | 15 |
- | 减 | 10-5 | 5 |
* | 乘 | 10*5 | 50 |
/ | 除 | 10/5 | 2 |
% | 取模(取余) | 10%3 | 1 |
++ | 前置递增 | a=2;b=++a; | a=3;b=3; |
++ | 后置递增 | a=2;b=a++; | a=3;b=2; |
– | 前置递减 | a=2;b=–a; | a=1;b=1; |
– | 后置递减 | a=2;b=a–; | a=1;b=2; |
加减乘除代码示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//加减乘除
int a1 = 10;
int b1 = 3;
cout << a1 + b1 << endl;
cout << a1 - b1 << endl;
cout << a1 * b1 << endl;
cout << a1 / b1 << endl; //两个整数相除,结果依然是整数,将小数部分去除
double f1 = 10;
double f2 = 3;
cout << f1 / f2 << endl; //这样结果就有小数
int a2 = 10;
int b2 = 20;
cout << a2 / b2 << endl; //0
//int a3 = 10;
//int b3 = 0; //除数不能为0
//cout << a3 / b3 << endl; 非法操作
system("pause");
return 0;
}
取模运算示例:
注意:两个小数是不可以做取模运算的
#include <iostream>
#include <string>
using namespace std;
int main()
{
//取模运算本质
int a1 = 10;
int b1 = 3;
cout << a1 % b1 << endl; //1
int a2 = 10;
int b2 = 20;
cout << a2 % b2 << endl; //10
//int a3 = 10;
//int b3 = 0;
//cout << a3 % b3 << endl; 非法
//两个小数是不可以做取模运算的
//double d1 = 3.14;
//double d2 = 1.1;
//cout << d1 % d2 << endl;
system("pause");
return 0;
}
递增递减示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//1.前置递增
int a = 10;
++a; //让变量进行+1的操作
cout << "a = " << a << endl;
//2.后置递增
int b = 10;
b++; //让变量进行+1的操作
cout << "b = " << b << endl;
//3.前置和后置的区别
//前置递增,先让变量+1,然后进行表达式运算
int a2 = 10;
int b2 = ++a2 * 10;
cout << "a2 = " << a2 << endl << "b2 = " << b2 << endl; //a2=11,b2=110
//后置递增,先进行表达式运算,然后变量+1
int a3 = 10;
int b3 = a3++ * 10;
cout << "a3 = " << a3 << endl << "b3 = " << b3 << endl; //a3=11,b3=100
system("pause");
return 0;
}
3.2 赋值运算符
**作用:**用于将表达式的值赋给变量
赋值运算符包括以下几种符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
= | 赋值 | a=2;b=3; | a=2;b=3; |
+= | 加等于 | a=0;a+=2; | a=2; |
-= | 减等于 | a=5;a-=3; | a=2; |
*= | 乘等于 | a=2;a*2; | a=4; |
/= | 除等于 | a=4;a/=2; | a=2; |
%= | 模等于 | a=3;a%2; | a=1; |
注:a+=2 就是 a=a+2 其他同理
简略示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 10;
a += 2;
cout << "a = " << a << endl; //12
system("pause");
return 0;
}
3.3 比较运算符
**作用:**用于表达式的比较,并返回一个真值或假值(用于判断!)
比较运算符有以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
== | 相等于 | 4 == 3 | 0 |
!= | 不相等 | 4 != 3 | 1 |
< | 小于 | 4 < 3 | 0 |
> | 大于 | 4 > 3 | 1 |
<= | 小于等于 | 4 <= 3 | 0 |
>= | 大于等于 | 4>= 1 | 1 |
简略示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
bool bo = true;
bo = 4 == 3;
cout << bo << endl; //0
//比较运算符
//==
int a = 10;
int b = 20;
cout << (a == b) << endl; //0 加()是先运算a == b再运算endl
//!=
cout << (a != b) << endl; //1
//...
system("pause");
return 0;
}
3.4 逻辑运算符
**作用:**用于根据表达式的值返回真值或假值
逻辑运算符有以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
! | 非 | !a | 如果a为假,则!a为真;如果a为真,则!a为假 |
&& | 与 | a&&b | 如果a和b都为真,则结果为真,否则为假 |
|| | 或 | a||b | 如果a和b有一个为真,则结果为真,二者都为假时,结果为假 |
**示例1:**逻辑非
#include <iostream>
#include <string>
using namespace std;
int main()
{
//逻辑运算符 非 !
int a = 10;
cout << !a << endl; //0
cout << !!a << endl; //1
system("pause");
return 0;
}
总结:真变假,假变真
**示例2:**逻辑与
#include <iostream>
#include <string>
using namespace std;
int main()
{
//逻辑运算符 与 &&
int a = 10;
int b = 10;
cout << (a && b) << endl; //1
int c = 10;
int d = 0;
cout << (c && d) << endl; //0
int e = 0;
int f = 0;
cout << (e && f) << endl; //0
system("pause");
return 0;
}
总结:都真为真,其余为假
**示例3:**逻辑或
#include <iostream>
#include <string>
using namespace std;
int main()
{
//逻辑运算符 或 ||
int a = 10;
int b = 10;
cout << (a || b) << endl;
int c = 10;
int d = 0;
cout << (c || d) << endl;
int e = 0;
int f = 0;
cout << (e || f) << endl;
system("pause");
return 0;
}
总结:都假为假,其余为真
四、程序流程结构
C/C++支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构
- 顺序结构:程序按顺序执行,不发生跳转
- 选择结构:依据条件是否满足,有选择的执行相应的功能
- 循环结构:依据条件是否满足,循环多次执行某段代码
4.1 选择语句
4.1.1 if语句
**作用:**执行满足条件的语句
if语句的三种形式
- 单行格式if语句
- 多行格式if语句
- 多条件的if语句
1.单行格式的if语句:if(条件){条件满足的语句}

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 0;
cout << "请输入你的分数:";
cin >> a;
if (a > 503) //这里不能有分号
{
cout << "你能考上一所一本大学" << endl;
}
system("pause");
return 0;
}
2.多行格式if语句:if(条件){条件满足的语句}else{条件不能满足的语句};

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 0;
cout << "请输入你的分数:";
cin >> a;
if (a >= 503) //这里不能有分号
{
cout << "你能考上一所一本大学" << endl;
}
else
{
cout << "你不能考上一本大学" << endl;
}
system("pause");
return 0;
}
3.多条件的if语句:if(条件1){条件1满足执行的语句} else if(条件2){条件2满足执行的语句}... else{都不满足执行的语句}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-99pAaMF0-1686840888801)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-05-04 211605.png)]
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 0;
cout << "请输入你的分数:";
cin >> a;
if (a>=0&&a<446) //这里不能有分号
{
cout << "你啥也考不上,去专科吧" << endl;
}
else if(a>=446&&a<503)
{
cout << "你能考上二本大学" << endl;
}
else if(a>=503&&a<700)
{
cout << "一本啊一本" << endl;
}
else if(a>=700&&a<=750)
{
cout << "你牛逼" << endl;
}
else
{
cout << "啥?" << endl;
}
system("pause");
return 0;
}
注意 与&& 或|| 符号的运用
**嵌套if语句:**在if语句中,可以嵌套使用if语句,达到更精确的条件判断
案例需求:
- 提示用户输入一个高考考试分数,根据分数做如下判断
- 分数如果大于600分视为考上一本,大于500分考上二本,大于400分考上三本,其余视为未考上本科
- 在一本分数中,如果大于700分,考入北大,大于650,考入清华,大于600考入人大
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
/*
要求:
- 提示用户输入一个高考考试分数,根据分数做如下判断
- 分数如果大于600分视为考上一本,大于500分考上二本,大于400分考上三本,其余视为未考上本科
- 在一本分数中,如果大于700分,考入北大,大于650,考入清华,大于600,考入人大
*/
//输入分数
int fen = 0;
cout << "请输入你的分数:" << endl;
cin >> fen;
cout << "你输入的分数为 " << fen << endl;
//判断一本600
if (fen > 600)
{
cout << "恭喜你可以考上一本" << endl;
//判断北大
if (fen > 700)
{
cout << "恭喜你可以考上北大!" << endl;
}
//判断清华
else if (fen > 650)
{
cout << "恭喜你可以考上清华!" << endl;
}
//判断人大
else if (fen > 600)
{
cout << "恭喜你可以考上人大!" << endl;
}
}
//判断二本500
else if (fen > 500)
{
cout << "恭喜你可以考上二本" << endl;
}
//判断三本400
else if (fen > 400)
{
cout << "恭喜你可以考上二本" << endl;
}
else
{
cout << "你啥jb也没考上兄弟" << endl;
}
system("pause");
return 0;
}
if语句练习案例:三只小猪称体重
有三只小猪ABC,请分别输入三只小猪的体重,并且判断哪只小猪最重?

#include <string>
#include <iostream>
using namespace std;
int main()
{
//有三只小猪ABC,请分别输入三只小猪的体重,并且判断哪只小猪最重?
//1.输入三只小猪的体重
int arr[3] = {0};
int i;
for (i = 0; i < 3; i++)
{
cout << "请输入第" << i + 1 << "只小猪的体重:" << endl;
cin >> arr[i];
cout << "您输入的第" << i + 1 << "个小猪的体重为:" << arr[i] << endl;
}
//2.判断三只小猪哪只最重
int max = arr[0];
for (i = 1; i < 3; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
for (i = 0; i < 3; i++)
{
if (arr[i] == max)
{
cout << "第" << i + 1 << "只小猪最重,它的体重为" << arr[i] << endl;
}
}
system("pause");
return 0;
}
4.1.2 三目运算符
**作用:**通过三目运算符实现简单的判断
语法:表达式1 ? 表达式2 : 表达式3
解释:
如果表达式1为真,执行表达式2,并返回表达式2的结果
如果表达式1为假,执行表达式3,并返回表达式3的结果
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//三目运算符
//创建三个变量 abc
//将a和b比较,将变量大的值赋给c
int a = 10;
int b = 20;
int c = 0;
c = (a > b ? a : b);
cout << "max1 = " <<c << endl;
//在C++中三目运算符返回的是变量,可以继续赋值
(a < b ? a : b) = 100;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
4.1.3 switch语句
**作用:**执行多条件的分支语句
语法:
switch(表达式)
{
case 结果1:执行语句;break;
case 结果2:执行语句;break;
...
default:执行语句;break;
}
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//switch语句
//给一个电影打分
//10~9 经典
//8~7 非常好
//6~5 一般
//5以下 烂
//1.提示用户评分
cout << "请给电影打分:" << endl;
//2.用户开始打分
int score = 0;
cin >> score;
cout << "您打出的分数为:" << score << endl;
//3.根据用户输入的分数提示用户最后的结果
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;
}
//if 和 switch 区别?
//switch 缺点,判断只能是整型或者字符型,不可以是一个区间
//switch 优点,结构清晰,执行效率高
system("pause");
return 0;
}
switch优缺点:
- 缺点:判断只能是整型或者字符型,不可以是一个区间
- 优点:结构清晰,执行效率高
4.2 循环结构
4.2.1 while循环语句
**作用:**满足循环条件,执行循环语句
语法:while(循环条件){循环语句}
**解释:**只要循环条件为真,就执行语句

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//while循环
//在屏幕中打印 0~9 这十个数字
int num = 0;
while (num < 10)
{
cout << num << endl;
num++;
}
system("pause");
return 0;
}
注意:记得提供挑出循环的出口,否则会出现死循环
while循环练习案例:猜数字
**案例描述:**系统随机生成一个1-100之间的数字,玩家进行猜测,如果猜错,提示玩家数字过大或者过小,如果猜对恭喜玩家胜利,并且退出游戏

流程图:

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//1.系统生成随机数
int num = rand() % 100 + 1; //生成 0 + 1 ~ 99 + 1 的随机数
cout << "随机数 = " << num << endl; //可屏蔽,这里做示范
//2.玩家进行猜测
int val = 0;
//3.判断玩家的猜测
while (1)
{
cin >> val;
if (val < num)
{
cout << "你输入的数字小了,请重新输入" << endl;
}
else if (val > num)
{
cout << "你输入的数字大了,请重新输入" << endl;
}
else
{
cout << "对溜!" << endl;
break;
}
}
//猜错 提示猜的结果 过大或者过小
//猜对 恭喜
system("pause");
return 0;
}
注:添加随机数种子(小方法)
#include <iostream>
#include <string>
//time系统时间头文件包含
#include <ctime>
using namespace std;
int main()
{
//添加随机数种子,作用利用当前系统时间生成随机数,防止每次随机数都一样
srand((unsigned int)time(NULL));
int num = rand() % 100;
cout << "随机数:" << num << endl;
system("pause");
return 0;
}
4.2.2 do…while循环语句
**作用:**满足循环条件,执行循环语句
语法:do{循环语句}while(循环条件);
**注意:**与while的区别在于do…while会先执行一次循环语句,再判断循环条件

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//do...while语句
//在屏幕中输出 0 到 9 这十个数字
int num = 0;
do
{
cout << num << endl;
num++;
}
while (num < 10);
//do...while和while循环的区别在于do...while会先执行一次循环语句
system("pause");
return 0;
}
总结:do…while和while循环的区别在于do…while会先执行一次循环语句
练习案例:水仙花数
**案例描述:**水仙花是指一个三位数,它的每个位上的数字的三次幂之和等于它本身
例如:1^3 + 5^3 + 3^3 = 153
请用do…while语句,求出所有三位数中的水仙花数
示例:
#include <iostream>
#include <string>
using namespace std;
/*
案例描述:水仙花是指一个三位数,它的每个位上的数字的三次幂之和等于它本身
例如:1^3 + 5^3 + 3^3 = 153
请用do...while语句,求出所有三位数中的水仙花数
*/
int main()
{
double num = 100;
int bai = 0, shi = 0, ge = 0;
do {
bai = (int)(num * 0.01);
shi = (int)((num-bai*100) * 0.1);
ge = (int)(num - bai * 100 - shi * 10);
if ((bai * bai * bai + shi * shi * shi + ge * ge * ge) == num)
{
cout << num << "是水仙花数" << endl;
}
num++;
} while (num < 1000);
system("pause");
return 0;
}
//或者取余
//ge = num % 10;
//shi = num / 10 % 10;
//bai = num / 100;
4.2.3 for循环语句
**作用:**满足循环条件,执行循环语句
语法:for(起始表达式;条件表达式;末尾循环体)
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int i = 0;
for (i = 0; i < 10; i++) //或者在内部定义i for (int i = 0 ; i < 10 ; i++)
{
cout << i << endl;
}
system("pause");
return 0;
}
//for循环可拆分为以下形式
//int i = 0;
//for ( ; ; )
//{
// if (i >= 10)
// {
// break;
// }
// i++;
//}
详解:

注意:for循环中的表达式,要用分号进行分隔
总结:while,do…while,for都是开发中常用的循环语句,for循环结构比较清晰,比较常用
练习案例:敲桌子
案例描述:从1开始数到数字100,如果数字个位含有7,或者数字十位含有7,或者该数字是7的倍数,我们打印敲桌子,其余数字直接打印输出

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
for (int i = 1; i <= 100; i++)
{
if (i % 10 == 7 || i / 10 == 7 || i % 7 == 0)
{
cout << "敲桌子" << endl;
}
else
{
cout << i << endl;
}
}
system("pause");
return 0;
}
4.2.4 嵌套循环
**作用:**在循环体中再嵌套一层循环,解决一些实际问题
例如我们想在屏幕中打印如下图片,就需要利用嵌套循环

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//利用嵌套循环实现星图
//打印一行星图
//外层循环
for (int i = 0; i < 10; i++)
{
//内层循环
for (int j = 0; j < 10; j++)
{
cout << "* ";
}
cout << endl;
}
system("pause");
return 0;
}
练习案例:乘法口诀表
案例描述:利用嵌套循环,实现九九乘法表

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//九九乘法表
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
if (j <= i)
{
cout << i << " * " << j << " = " << i * j << "\t";
}
}
cout << endl;
}
system("pause");
return 0;
}
4.3 跳转语句
4.3.1 break语句
**作用:**用于跳出选择结构或者循环结构
break使用的时机:
- 出现在switch条件语句中,作用是终止case并跳出switch
- 出现在循环语句中,作用是跳出当前的循环语句
- 出现在嵌套循环中,跳出最近的内层循环语句
示例1:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//break的使用时机
//1.出现在switch语句中
cout << "请选择副本难度" << endl;
cout << "1.普通" << endl;
cout << "2.中等" << endl;
cout << "3.困难" << endl;
int select = 0; //创建一个选择结果的变量
cin >> select; //等待用户输入数据
switch (select)
{
case 1:
cout << "您选择的是普通难度" << endl;
break;
case 2:
cout << "您选择的是中等难度" << endl;
break;
case 3:
cout << "您选择的是困难难度" << endl;
break;
default:
break;
}
//2.出现在循环语句中
for (int i = 0; i < 10; i++)
{
cout << i << endl;
//如果i = 5,退出循环,不再打印
if (i == 5)
{
break;
}
}
//3.出现在嵌套循环语句中
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
cout << "* ";
if (j == 5)
{
break; //退出内层循环
}
}
cout << endl;
}
system("pause");
return 0;
}
4.3.2 continue语句
**作用:**在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//continue语句的用途
for (int i = 0; i <= 100; i++)
{
//如果是奇数输出,偶数不输出
if (i % 2 == 0)
{
continue; //可以筛选条件,执行到此就不再向下执行,执行下一次循环
}
cout << i << endl;
}
system("pause");
return 0;
}
4.3.3 goto语句
**作用:**可以无条件跳转语句
语法:goto 标记;
**解释:**如果标记的名称存在的话,执行到goto语句时,会跳转到标记的位置

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//goto语句
cout << "1.XXXX" << endl;
cout << "2.XXXX" << endl;
goto FLAG;
cout << "3.XXXX" << endl;
cout << "4.XXXX" << endl;
cout << "5.XXXX" << endl;
FLAG:
cout << "6.XXXX" << endl;
system("pause");
return 0;
}
注:不经常用,不建议用
五、数组
5.1 概括
所谓数组,就是一个集合,里面存放了相同的数据元素
**特点1:**数组中的每个数据元素都是相同的数据类型
**特点2:**数组是由连续的内存位置组成的
5.2 一维数组
5.2.1 一维数组定义方式
三种方式:
数据类型 数组名[数组长度];
数据类型 数组名[数组长度] = {值1,值2,...};
数据类型 数组名[] = {值1,值2,...};
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
/*
1. 数据类型 数组名[数组长度];
2. 数据类型 数组名[数组长度] = {值1,值2,...};
3. 数据类型 数组名[] = {值1,值2,...};
*/
//1.数据类型 数组名[数组长度];
int arr[5];
//给数组中的元素进行赋值
//数组元素的下标是从0开始的
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
//访问数据元素
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << arr[3] << endl;
cout << arr[4] << endl;
//2.数据类型 数组名[数组长度] = {值1,值2,...};
//如果初始化数据时,没全部填写完,会用0来填补数据
int arr2[5] = { 10,20,30 };
cout << arr2[0] << endl;
cout << arr2[1] << endl;
cout << arr2[2] << endl;
cout << arr2[3] << endl;
cout << arr2[4] << endl;
//利用循环 输出数组中的元素
for (int i = 0; i < 5; i++)
{
cout << arr2[i] << endl;
}
//3.数据类型 数组名[] = { 值1,值2,... };
//定义数组的时候,必须有初始长度
int arr3[] = { 90,80,70,60,50,40,30,20,10 };
for (int j = 0; j < 9; j++)
{
cout << arr3[j] << endl;
}
system("pause");
return 0;
}
5.2.2 一维数组数组名
一维数组名称的用途:
- 可以统计整个数组在内存中的长度
sizeof(arr)
- 可以获取数组在内存中的首地址
cout << arr <<endl;
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//数组名的用途
//1.可以通过数组名统计整个数组占用内存大小
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "整个数组占用的内存空间为:" << sizeof(arr) << endl;
cout << "整个数组占用的内存空间为:" << sizeof(arr) << endl;
cout << "数组中元素个数是多少:" << sizeof(arr)/sizeof(arr[0]) << endl;
//2.可以通过数组名查看数组首地址
cout << "数组的首地址为:" << (int)arr << endl;
cout << "数组中第一个元素的地址:" << (int) & arr[0] << endl;
cout << "数组中第二个元素的地址:" << (int) & arr[1] << endl;
//数组名是常量,不可以进行赋值操作,它就等于他的首地址(初始是16进制的)
system("pause");
return 0;
}
练习案例1:
案例描述:
在一个数组中记录了五只小猪的体重,如:int arr[5] = {300,350,200,400,250};
要求:找出并打印最重的小猪的体重
#include <iostream>
#include <string>
using namespace std;
int main()
{
/*
在一个数组中记录了五只小猪的体重,如:int arr[5] = {300,350,200,400,250};
要求:找出并打印最重的小猪的体重
*/
//定义数组
int arr[5] = { 300,350,200,400,250 };
//判断最重的小猪
int max = arr[0];
for (int i = 1; i < 5; i++)
{
if (max < arr[i])
{
max = arr[i];
}
}
//输出最重小猪体重
cout << "最重的小猪体重为:" << max << endl;
system("pause");
return 0;
}
**练习案例2:**数组元素逆置
**案例描述:**请声明一个5个元素的数组,并且将元素逆置
(如原数组为 1,2,3,4,5; 逆置输出后为 5,4,3,2,1; )
#include <iostream>
#include <string>
using namespace std;
int main()
{
/*
请声明一个5个元素的数组,并且将元素逆置
(如原数组为 1,2,3,4,5; 逆置输出后为 5,4,3,2,1; )
*/
//定义数组
int arr[] = { 1,2,3,4,5 };
//计算数组长度
int length = sizeof(arr) / sizeof(arr[0]);
cout << "数组逆置前:" << endl;
for (int i = 0; i < length; i++)
{
cout << arr[i] << endl;
}
cout << "数组逆置后:" << endl;
for (int i = 0; i < length; i++) //例子中,长度5,循环5次
{
cout << arr[length - (i + 1)] << endl; //最后的元素就是 arr[length-1]
}
system("pause");
return 0;
}
5.2.3 冒泡排序
**作用:**最常用的排序算法,对数组内的元素进行排序
- 比较相邻的元素,如果第一个比第二个大,就交换他们两个
- 对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值
- 重复以上的步骤,每次比较次数-1,直到不需要比较
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cEXfCwL9-1686840888802)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-05-06 180114.png)]
**示例:**将数组{4,2,8,0,5,7,1,3,9}进行升序排序
#include <iostream>
#include <string>
using namespace std;
int main()
{
//冒泡排序
//题目:将数组{4,2,8,0,5,7,1,3,9}进行升序排序
int arr[] = { 4,2,8,0,5,7,1,3,9 };
int length = sizeof(arr) / sizeof(arr[0]);
int a = 0;
int b = 0;
for (int j = 0; j < length - 1; j++) //3.总共需要排序 length-1 次
{
for (int i = 0; i < length - (j + 1); i++) //2.总共有length个元素,那就调换 length-1 次
{
if (arr[i] > arr[i + 1]) //1.如果前一个元素比后一个元素大,就调换一下它俩的位置,最后挑一个最大的到最右边
{
a = arr[i];
b = arr[i + 1];
arr[i + 1] = a;
arr[i] = b;
}
}
}
//输出最终数组
cout << "最终数组为:" << endl;
for (int i = 0; i < length; i++)
{
cout << arr[i] << " " ;
}
system("pause");
return 0;
}
5.3 二维数组
二位数组就是在一维数组的基础上,多加一个维度

5.3.1 二维数组定义方式
四种方式:
数据类型 数组名[行数][列数];
数据类型 数组名[行数][列数] = {{数据1,数据2},{数据3,数据4}};
数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};
数据类型 数组名[ ][列数] = {数据1,数据2,数据3,数据4};
建议:以上4种定义方式,利用==第二种更加直观,提高代码的可读性==
图例:arr[2][3]
↓

示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//2.二维数组的定义方式
/*
1. 数据类型 数组名[行数][列数];
2. 数据类型 数组名[行数][列数] = {{数据1,数据2},{数据3,数据4}};
3. 数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};
4. 数据类型 数组名[ ][列数] = {数据1,数据2,数据3,数据4};
*/
//1. 数据类型 数组名[行数][列数];
int arr[2][3] = { 0 };
arr[0][1] = 2;
cout << arr[0][1] << endl;
//遍历方法:外层循环打印行数,内层循环打印列数
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 arr1[2][3] = {
{1,2,3},
{4,5,6}
};
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr1[i][j] << " ";
}
cout << endl;
}
//3.数据类型 数组名[ ][列数] = {数据1,数据2,数据3,数据4};
int arr2[2][3] = {1,2,3,4,5,6};
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 arr3[][3] = { 1,2,3,4,5,6 };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr3[i][j] << " ";
}
cout << endl;
}
system("pause");
return 0;
}
第二种最直观最常用
5.3.2 二维数组数组名
- 查看二维数组所占内存空间
- 获取二维数组首地址
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//二维数组名称用途
//1.可以查看占用的内存空间大小
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;
//2.可以查看二位数组的首地址
cout << "二维数组首地址:" << (int)arr << endl;
cout << "二维数组第一行的首地址:" << (int)arr[0] << endl;
cout << "二维数组第二行的首地址:" << (int)arr[1] << endl;
cout << "二维数组第一个元素的首地址:" << (int)&arr[0][0] << endl; // &!!!
system("pause");
return 0;
}
5.3.3 二维数组应用案例
考试成绩统计:
案例描述:有三民同学(张三,李四,王五),在一次考试中的成绩分别如下表,请分别输出三名同学的总成绩
语文 | 数学 | 英语 | |
---|---|---|---|
张三 | 100 | 100 | 100 |
李四 | 90 | 50 | 100 |
王五 | 60 | 70 | 80 |
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
/*
案例描述:有三民同学(张三,李四,王五),在一次考试中的成绩分别如下表
请分别输出三名同学的总成绩
*/
int sum = 0;
int arr[3][3] =
{
{100,100,100},
{90,50,100},
{60,70,80}
};
string name[3] = { "张三","李四","王五" };
for (int j = 0; j < 3 ; j++)
{
for (int i = 0; i < 3; i++)
{
sum = sum + arr[j][i];
}
cout << name[j] << "同学的总成绩为:" << sum << endl;
sum = 0;
}
system("pause");
return 0;
}
六、函数
6.1 概述
**作用:**讲一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能
6.2 函数的定义
函数的定义一般主要有5个步骤:
- 返回值类型
- 函数名
- 参数列表
- 函数体语句
- return 表达式
语法:
返回值类型 函数名 (参数列表)
{
函数体语句
return表达式
}
图例:


加法示例代码:
#include <iostream>
#include <string>
using namespace std;
//函数的定义
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
int main()
{
system("pause");
return 0;
}
- 返回值类型:一个函数可以返回一个值,在函数定义中
- 函数名:给函数起个名称
- 参数列表:使用该函数时,传入的数据
- 函数体语句:花括号内的代码,函数内需要执行的语句
- return 表达式:和返回值类型挂钩,函数执行完后,返回相应的数据
6.3 函数的调用
**功能:**使用定义好的函数
语法:函数名(参数)
示例:
#include <iostream>
#include <string>
using namespace std;
//函数的定义
//函数定义时,num1和num2并没有真的数据,他只是一个形式上的参数,简称形参
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
int main()
{
cout << "加法计算,请输入两个数字,中间用空格隔开:" << endl;
int b, c;
cin >> b;
cin >> c;
// a 和 b 称为 实际参数,简称实参
//当调用函数的时候,实参的值会传递给形参
int a = add(b,c);
cout << "两数相加为:" << a << endl;
system("pause");
return 0;
}
6.4 值传递
- 所谓值传递,就是参数调用时实参将数值传入给形参
- 值传递时,如果形参发生,并不会影响实参
示例:
#include <iostream>
#include <string>
using namespace std;
//值传递
//定义函数,实现两个数字交换的函数
//如果函数不需要返回值,声明的时候可以写 void(翻译:无效)
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;
}
int main()
{
int a = 10;
int b = 20;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
//当我们做值传递的时候,函数的形参发生改变,不会影响到实参
swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
6.5 函数的常见样式
常见样式有4种
- 无参无返
- 有参无返
- 无参有返
- 有参有返
示例:
#include <iostream>
#include <string>
using namespace std;
//函数的常见样式
//1.无参无返
void test01()
{
cout << "helloworld" << endl;
}
//2.有参无返
void test02(int a)
{
cout << "test02 a = " << a << endl;
}
//3.无参有返
int test03()
{
cout << "test03" << endl;
return 1000;
}
//4.有参有返
int test04(int num1)
{
int sum = num1 + 10;
return sum;
}
int main()
{
//无参无返的函数调用
test01();
//有参无返的函数调用
test02(100);
//无参有返函数调用
int num1 = test03();
cout << "num1 = " << num1 << endl;
//有参有返函数调用
int num2 = 10;
cout << "num2 + 10 = " << test04(num2) << endl;
system("pause");
return 0;
}
6.6 函数的声明
**作用:**告诉编译器函数名称及如何调用函数,函数的实际主体可以单独定义
- 函数的声明可以多次,但是函数的定义只能有一次
示例:
#include <iostream>
#include <string>
using namespace std;
//函数的声明
//比较函数,实现两个整型数字进行比较,返回较大的值
//定义
//int max(int a, int b)
//{
// //int Max = (a >= b ? a : b);
// //return Max;
//
// return a >= b ? a : b;
//
//}
//提前告诉编译器函数的存在,可以利用函数的声明(如果定义在main前可以不用声明)
//声明可以多次,定义只能有一次
int max(int a, int b);
//这一步其实vs2022可以不用了
int main()
{
//声明可以多次,定义只能有一次
int a = 10;
int b = 20;
cout << max(a, b) << endl;
system("pause");
return 0;
}
int max(int a, int b)
{
//int Max = (a >= b ? a : b);
//return Max;
return a >= b ? a : b;
}
6.7 函数的分文件编写
**作用:**让代码结构更加清晰
函数分文件编写一般有4个步骤
- 创建后缀名.h的头文件
- 创建后缀名为.cpp的源文件
- 在头文件中写函数的声明
- 在源文件中写函数的定义
示例:
头文件 swap.h
//声明
void swap(int a, int b);
源文件 swap.cpp
#include <iostream>
#include "swap.h" //双引号代表自定义
using namespace std;
//定义
void swap(int a, int b)
{
int c = a;
a = b;
b = c;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
主文件 函数的分文件编写
#include <iostream>
#include <string>
#include "swap.h"
using namespace std;
//函数的分文件编写
//实现两个数字交换的函数
//函数的声明
//void swap(int a, int b);
//函数的定义
//void swap(int a, int b)
//{
// int c = a;
// a = b;
// b = c;
//
// cout << "a = " << a << endl;
// cout << "b = " << b << endl;
//}
int main()
{
int a = 10;
int b = 20;
swap(a, b);
system("pause");
return 0;
}
注:#include “swap.h” //双引号代表自定义
七、指针
7.1 指针的基本概念
**指针的作用:**可以通过指针间接访问内存
- 内存编号是从0开始记录的,一般用十六进制数字表示
- 可以利用指针变量保存地址

可以认为,指针就是一个地址
实际上,指针是一个变量,其中保存着地址
7.2 指针变量的定义和使用
指针变量定义语法:数据类型 * 变量名
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//1.定义指针
int a = 10;
//指针定义的语法:数据类型 * 指针变量名;
int* p = &a; //让指针记录变量a的地址
cout << "a的地址为:" << &a << endl;
cout << "指针p为:" << p << endl;
//2.使用指针
//可以通过解引用的方式来找到指针指向的内存
//指针前加一个 * 代表解引用,找到指针指向的内存中的数据
*p = 1000;
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
system("pause");
return 0;
}
7.3 指针所占空间
提问:指针也是种数据类型,那么这种数据类型占用多少内存空间?
- 在32位操作系统下,任何类型的指针都是4个字节
- 在64位操作系统下,占8个字节
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//指针所占内存空间
int a = 10;
//int* p;
//p = &a;
int* p = &a;
cout << "sizeof int *p = " << sizeof(int*) << endl;
cout << "sizeof float *p = " << sizeof(float*) << endl;
cout << "sizeof double *p = " << sizeof(double*) << endl;
cout << "sizeof char *p = " << sizeof(char*) << endl;
system("pause");
return 0;
}
7.4 空指针和野指针
**空指针:**指针变量指向内存中编号为0的空间
**用途:**初始化指针变量
**注意:**空指针指向的内存是不可以访问的,0-255的内存是系统占用的,我们不能访问
示例1:空指针
#include <iostream>
#include <string>
using namespace std;
int main()
{
//空指针
//1.用于给指针变量初始化
int* p = NULL; //NULL = 0;
//2.空指针是不能用于访问的
//0~255之间的内存编号是系统占用的,因此不可以访问
//*p = 100;
int a = 10;
p = &a;
cout << "*p = " << *p << endl;
system("pause");
return 0;
}
**野指针:**指针变量指向非法的内存空间(你无法操控的内存空间等)
示例2:野指针
#include <iostream>
#include <string>
using namespace std;
int main()
{
//野指针
//在程序中,尽量避免出现野指针
int* p = (int*)0x1100;
//cout << *p << endl;
system("pause");
return 0;
}
总结:空指针和野指针都不是我们申请的空间,因此不要访问
7.5 const修饰指针
const修饰指针的三种情况:
- const 修饰指针 — 常量指针
- const 修饰常量 — 指针常量
- const 既修饰指针,又修饰常量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iv1H2HNl-1686840888803)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-05-07 175813.png)]
- 常量指针:
const int* p = &a;
- 特点:指针的指向可以改,但是指针指向的值不能改,即const作用在指向的变量上
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GpDuH2yV-1686840888803)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-05-07 180925.png)]
-
指针常量:
int* const p = &a;
-
特点:指针的指向不能改,指向的值可以改
-
const即修饰指针,又修饰常量
-
const int* const p = &a;
-
特点:指针的指向和指针的值都不能改
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//1.常量指针
int a = 10;
int b = 10;
const int* p = &a;
//指针指向的值不能改,指向可以改
//*p = 20; 错误
p = &b; //正确
//2.指针常量
int* const p1 = &a;
*p1 = 20; //正确
//p2 = &b; 错误
//3.const修饰常量和指针
const int* const p2 = &a;
//*p2 = 20; 错误
//p2 = &b; 错误
system("pause");
return 0;
}
7.6 指针和数组
**作用:**利用指针访问数组中的元素
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
//指针和数组
//利用指针访问数组
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "第一个元素是:" << arr[0] << endl;
int* p = arr; //arr存放了数组的首地址
cout << "利用指针来访问第一个元素:" << *p << endl;
p++; //往后推四个字节,整型指针直接++就行
cout << "利用指针来访问第二个元素:" << *p << endl;
cout << "利用指针遍历数组:" << endl;
int* p2 = arr;
for (int i = 0; i < 10; i++)
{
cout << "数组中第" << i + 1 << "个元素为:" << *p2 << endl;
p2++;
}
system("pause");
return 0;
}
7.7 指针和函数
**作用:**利用指针作函数的参数,可以修改实参的值
示例:
#include <iostream>
#include <string>
using namespace std;
//实现两个数字互换
void swap1(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
cout << "swap1 a = " << num1 << endl;
cout << "swap1 b = " << num2 << endl;
}
void swap2(int* p1, int* p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
//指针和函数
int a = 10;
int b = 20;
//1.值传递
//swap1(a, b);
//2.地址传递
//如果是地址传递,可以修饰实参
//也就是说传进去地址,然后解地址直接操作地址指向的内存
swap2(&a, &b);
cout << "a = " << a << endl; //20
cout << "b = " << b << endl; //10
system("pause");
return 0;
}
- 值传递:传进去的是值,实参不被操作
- 地址传递:可以修饰实参,也就是说传进去地址,然后解地址直接操作地址指向的内存
不想修改实参就用值传递,想修改实参就用地址传递
7.8 指针、数组、函数
**案例描述:**封装一个函数,利用冒泡排序,实现对整型数组的升序排序
例如:
数组:int arr[10] = {4,3,6,9,1,2,10,8,7,5};
!注:在 C++ 中,要声明一个二维数组作为函数参数,需要指定数组的列数。!
示例:
#include <iostream>
#include <string>
using namespace std;
void bublleSort(int* arr,int length) //int* arr也可以写成int arr[]
{
for (int i = 0; i < length-1; i++)
{
for (int j = 0; j < length-1; j++)
{
if (*(arr + j) > *(arr + 1 + j)) //也可以写成 arr[j] > arr[j + 1]
{
int temp = *(arr + 1 + j);
*(arr + 1 + j) = *(arr + j);
*(arr + j) = temp;
}
}
}
}
int main()
{
/*
案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序
int arr[10] = {4,3,6,9,1,2,10,8,7,5};
*/
int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
bublleSort(arr, 10);
for (int i = 0; i < 10; i++)
{
cout << arr[i] << endl;
}
system("pause");
return 0;
}
八、结构体
8.1 结构体基本概念
结构体属于用户自定义的数据类型,允许用户储存不同的数据类型
8.2 结构体定义和使用
语法:struct 结构体名 {结构体成员列表};
通过结构体创建变量的方式有三种:
- struct 结构体名 变量名
- struct 结构体名 变量名 = {成员1值,成员2值…}
- 定义结构体时顺便创建变量
示例:
#include <iostream>
#include <string>
using namespace std;
//1.创建学生数据类型:包括(姓名,年龄,分数)
//自定义数据类型,一些类型集合组成的一个类型
//语法 struct 类型名称 {成员列表}
struct Student //放属性的
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
double score;
}s3; //顺便创建结构体变量
//2.通过学生数据类型创建具体的学生
//2.1 struct Student s1;
//2.2 struct Student s2 = {...};
//2.3 在定义结构体时顺便创建结构体变量
int main()
{
//2.1 struct Student s1
//struct关键字可以省略
/*struct*/ Student s1; //s1算是成员
//给 s1 属性赋值,通过 . 访问结构体变量中的属性
s1.name = "张三";
s1.age = 18;
s1.score = 100;
cout << "姓名:" << s1.name << endl;
cout << "年龄:" << s1.age << endl;
cout << "成绩:" << s1.score << endl;
//2.2 struct Student s2 = {...}
//struct可以省略
struct Student s2 = { "李四",20,80 };
cout << "姓名:" << s2.name << endl;
cout << "年龄:" << s2.age << endl;
cout << "成绩:" << s2.score << endl;
//2.3 在定义结构体时顺便创建结构体变量(创建代码示例在上面)
//一般不用
s3.name = "王五";
s3.age = 19;
s3.score = 90;
system("pause");
return 0;
}
总结1:定义结构体时的关键字struct,不可省略
总结2:创建结构体变量时,关键字struct,可以省略
总结3:结构体变量利用操作符 . 访问成员(属性)
8.3 结构体数组
**作用:**将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名[元素个数] = {{},{},...{}};
示例:
#include <iostream>
#include <string>
using namespace std;
//1.定义结构体
struct student
{
string name;
int age;
double score;
};
int main()
{
//2.创建结构体数组
struct student stuArray[3] =
{
{"张三",18,100},
{"李四",19,90},
{"王五",18,80}
};
//3.给结构体数组中的元素赋值
stuArray[2].name = "赵六";
stuArray[2].age = 80;
stuArray[2].score = 60;
//4.遍历结构体数组
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << stuArray[i].name << endl;
cout << "年龄:" << stuArray[i].age << endl;
cout << "分数:" << stuArray[i].score << endl;
}
system("pause");
return 0;
}
8.4 结构体指针
**作用:**通过指针访问结构体中的成员
- 利用操作符 -> 可以通过结构体指针访问结构体属性
示例:
#include <iostream>
#include <string>
using namespace std;
//结构体指针
//定义学生的结构体
struct student
{
string name;
int age;
int score;
};
int main()
{
//创建学生的结构体变量
student s = { "张三",18,100 };
//通过指针指向结构体变量
student* p = &s;
//通过指针访问结构体变量中的数据
//通过结构体指针 访问结构体中的属性,需要利用 '->'
cout << "姓名:" << p->name << endl;
cout << "年龄:" << p->age << endl;
cout << "成绩:" << p->score << endl;
system("pause");
return 0;
}
总结:结构体指针可以通过 -> 操作符 来访问结构体中的成员
8.5 结构体嵌套结构体
**作用:**结构体中的成员可以是另一个结构体
**例如:**每个老师辅导一个学生,一个老师的结构体中,记录一个学生的结构体
示例:
#include <iostream>
#include <string>
using namespace std;
//学生结构体的定义
struct student
{
string name; //学生姓名
int age; //学生年龄
int score; //学生分数
};
//教师结构体的定义
struct teacher
{
int id; //职工id
string name; //职工姓名
int age; //职工年龄
student stu1; //子结构体 教的学生
};
int main()
{
teacher t;
t.id = 10000;
t.name = "老王";
t.age = 50;
t.stu1.name = "小王";
t.stu1.age = 20;
t.stu1.score = 60;
cout << "老师编号:" << t.id << endl;
cout << "老师名字:" << t.name << endl;
cout << "老师年龄:" << t.age << endl;
cout << "老师辅导的学生姓名:" << t.stu1.name << endl;
cout << "老师辅导的学生年龄:" << t.stu1.age << endl;
cout << "老师辅导的学生分数:" << t.stu1.score << endl;
system("pause");
return 0;
}
总结:在结构体中可以定义另一个结构体作为成员,用来解决实际问题
8.6 结构体做函数参数
**作用:**将结构体作为参数向函数中传递
传递方式有两种:
- 值传递(实参不被改变)
- 地址传递(实参被改变)
示例:
#include <iostream>
#include <string>
using namespace std;
//学生结构体定义
struct student
{
//姓名
string name;
//年龄
int age;
//分数
int score;
};
//打印学生信息的函数
//1.值传递
void printStudent1(student s)
{
s.score = 100;
cout << "在子函数中 姓名:" << s.name << endl;
cout << "在子函数中 年龄:" << s.age << endl;
cout << "在子函数中 分数:" << s.score << endl; //100
}
//2.地址传递
void printStudent2(student* p)
{
p->score = 100;
cout << "在子函数2中 姓名:" << p->name << endl;
cout << "在子函数2中 年龄:" << p->age << endl;
cout << "在子函数2中 分数:" << p->score << endl; //100
}
int main()
{
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//创建结构体变量
student s;
s.name = "张三";
s.age = 20;
s.score = 85;
printStudent1(s);
cout << "main函数中打印 姓名:" << s.name << endl;
cout << "main函数中打印 年龄:" << s.age << endl;
cout << "main函数中打印 分数:" << s.score << endl; //85
printStudent2(&s);
cout << "main函数中打印 姓名:" << s.name << endl;
cout << "main函数中打印 年龄:" << s.age << endl;
cout << "main函数中打印 分数:" << s.score << endl; //100
system("pause");
return 0;
}
总结:如果不想修改主函数中的数据,用值传递,反之用地址传递
8.7 结构体中 const 的使用场景
**作用:**用const来防止误操作
- 值传递实际是复制出副本,太大不好优化
- 要调用大的数据时可以直接地址传递
示例:
#include <iostream>
#include <string>
using namespace std;
//const的使用场景
struct student
{
string name;//姓名
int age;//年龄
int score;//分数
};
//将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
void printStudent(const student* p) //指针只占4个字节
{
//p->name = "李四"; 不行 加入const之后,一旦有修改的操作就会报错,可以防止我们误操作
cout << "学生姓名为:" << p->name << endl; // (*p).name 也可以
cout << "学生年龄为:" << p->age << endl;
cout << "学生分数为:" << p->score << endl;
}
int main()
{
//创建结构体变量
student s = { "张三",15,70 };
//通过函数打印结构体变量的信息
printStudent(&s);
system("pause");
return 0;
}
8.8 结构体案例
8.8.1 案例1
案例描述:
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
最终打印出老师数据以及老师所带的学生数据
示例:
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
/*
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
最终打印出老师数据以及老师所带的学生数据
*/
//创建老师结构体
struct student
{
string name;//学生姓名
int score;//学生分数
};
//创建学生结构体
struct teacher
{
string name;//老师姓名
student student[5];
};
//创建赋值函数
void assign(teacher teacher[], int len)
{
string nameSeed = "ABCDE";
//给老师赋值
for (int i = 0; i < len; i++)
{
teacher[i].name = "teacher_";
teacher[i].name += nameSeed[i];
//给学生赋值
for (int j = 0; j < 5; j++)
{
teacher[i].student[j].name = "student_";
teacher[i].student[j].name += nameSeed[j];
int random = rand() % 101; //随机数
teacher[i].student[j].score = random;
}
}
}
//打印所有信息
void printInfo(teacher teacher[], int len)
{
for (int i = 0; i < 3; i++)
{
cout << "教师姓名:" << teacher[i].name << endl;
cout << "学生信息:" << endl;
for (int j = 0; j < 5; j++)
{
cout << "学生姓名:" << teacher[i].student[j].name << endl;
cout << "学生成绩:" << teacher[i].student[j].score << endl;
}
}
}
int main()
{
//随机数种子
srand((unsigned int)time(NULL));
//srand是C语言中的随机数种子函数,它与rand()函数一同使用,用来产生随机数。
//无符号整数(Unsigned Integer)是一种整数类型,用于存储正整数或零。它与有符号整数类型相似,但有一个重要的区别,即它不允许存储负数。
//time(NULL)函数返回当前时间的UTC时间戳,以秒为单位。
//记得包含头文件 #include <ctime>
//给学生和老师赋值
teacher teacher[3];
int len = sizeof(teacher) / sizeof(teacher[0]);
assign(teacher,len);
//打印所有老师和学生的信息
printInfo(teacher, len);
system("pause");
return 0;
}
8.8.2 案例2
案例描述:
设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
#include <iostream>
#include <string>
using namespace std;
struct hero
{
string name;//名字
int age;//年龄
string sex;//性别
};
//冒泡排序算法
void bubbleSort(hero revenger[], int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - 1; j++)
{
if (revenger[j].age > revenger[j + 1].age)
{
hero temp = revenger[j];
revenger[j] = revenger[j + 1];
revenger[j + 1] = temp;
}
}
}
}
int main()
{
/*
设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
*/
hero revenger[5] =
{
{"张三",18,"男"},
{"李四",19,"女"},
{"王五",20,"男"},
{"寅子",40,"男"},
{"表哥",23,"男"}
};
int len = sizeof(revenger) / sizeof(revenger[0]);
//冒泡排序
bubbleSort(revenger, len);
//打印排序后的结果
for (int i = 0; i < len; i++)
{
cout << "英雄名字:" << revenger[i].name << endl;
cout << "英雄年龄:" << revenger[i].age << endl;
cout << "英雄性别:" << revenger[i].sex << endl;
cout << endl;
}
system("pause");
return 0;
}
九、课外补充
9.1 EasyX图形库
9.1.1 EasyX简单介绍
- 安装:本质上,查找VS的安装目录,并将相关文件分别拷贝至lib目录和include目录
- 安装成功后,包含头文件 graphics.h 即可开始学习
- 帮助文档链接:https://docs.easyx.cn/zh-cn/intro’
- 仅用于c++
9.1.2 EasyX颜色
补充:光的三原色是红、黄、蓝,我们表示颜色的使用就用三原色来表示
-
用RGB宏合成颜色,实际上合成出来的颜色是一个十六进制的整数
RGB(红色部分,绿色部分,蓝色部分);
每个颜色部分的值都是从0~255
9.1.3 EasyX坐标和设备
- 坐标默认的原点在窗口的左上角,X轴向右为正,Y轴向下为正,度量单位是像素点
- 设备:简单来说,就是绘图表面
- 在EasyX中,设备分两种,一种是默认的绘图窗口,另一种是IMAGE对象。通过SetWorkingImage()函数可以设置当前用于绘图的设备。设置当前用于绘图的设备以后,所有的绘图函数都会绘制在该设备上。(后面有详解)
9.1.4 窗口函数用于窗口的一些操作
初始化窗口
-
initgraph(int width,int height,int flag = NULL); 用于初始化绘图窗口(创建窗口)
width 指定窗口的宽度
height 指定窗口的高度
flag 窗口的样式,默认为NULL
-
closegraph(); 关闭绘图窗口
-
cleardevice(); 清空绘图设备
绘图函数
-
绘图函数从填充样式分类可分为无填充,有边框填充,无边框三种。
以画圆为例:
- circle() 无填充
- fillcircle() 有边框填充
- solidcircle() 无边框填充
-
从形状来分,常用的可以分为八种
- circle 画圆
- ellipse 画椭圆
- pie 画扇形
- polygon 画多边形
- rectangle 画矩形
- roundrect 画圆角矩形
- line 画线
- putpixel 画点
-
设置填充颜色 setfillcolor(颜色);
-
设置线条颜色 setlinecolor(颜色);
-
设置线条样式 setlinestyle(高度,宽度,字体);
设置背景颜色,以下两步必不可少(可以理解为设置的颜色在默认黑色背景的底下,然后清屏清除的是黑色)
-
设置背景颜色 setbkcolor(颜色);
-
清屏-清除原本背景颜色 cleardevice();
-
outtextxy(int x,int y,LPCTSTR str); 在指定位置输出字符串
-
settextcolor(COLORREF color); 设置当前文字颜色
-
settextstyle(int nHeight,int nWidth,LPCTSTR IpszFace) 设置字体样式
- nHeight 指定高度
- nWidth 字符的平均宽度。如果为0,则比例自适应
- IpszFace 字体名称
- 示例:
settextstyle(50, 0, "楷体");
以下两种函数可用于文本的垂直和水平居中显示
- textheight(LPCTSTR str); 获取字符串实际占用的像素高度
- textwidth(LPCTSTR str); 获取字符串实际占用的像素宽度
文字在矩形框居中示例代码:
fillrectangle(200, 50, 500, 100);//填充一个矩形,参数为 左上角坐标+右下角坐标
settextcolor(RGB(30, 30, 30));
char arr[] = "居中显示测试";
int width = textwidth(arr);//像素所占宽度
int height = textheight(arr);//像素所占高度
outtextxy(300 / 2 - width / 2 + 200, 50 / 2 - height / 2 + 50, "居中显示测试");//绘制字符串
全部示例代码:
#include <iostream>
#include <string>
#include <graphics.h>
using namespace std;
int main()
{
//创建一个窗口,确定窗口大小,show console 显示控制台
initgraph(640,480,SHOWCONSOLE);
//设置背景以下两步必不可少
//设置背景颜色
setbkcolor(YELLOW);
cleardevice();//清屏,清除黑色背景
//画粑粑,圆
setlinestyle(PS_SOLID, 5);//设置线条样式
setfillcolor(GREEN);//设置填充颜色
setlinecolor(BLUE);//设置线条颜色
circle(50, 50, 50);
fillcircle(50, 150, 50);
solidcircle(50, 250, 50);
//设置字体颜色
settextcolor(BLACK);
//设置字体大小,样式,字体..
settextstyle(20, 0, "楷体");
//设置背景模式 transparent-透明
setbkmode(TRANSPARENT);
//设置字体颜色
settextcolor(RGB(85, 177, 85));
//绘制文字
outtextxy(50, 50, 'a');//绘制字符
outtextxy(60, 50, "大家好");//绘制字符串
//把文字居中
fillrectangle(200, 50, 500, 100);//填充一个矩形,参数为 左上角坐标+右下角坐标
settextcolor(RGB(30, 30, 30));
char arr[] = "居中显示测试";
int width = textwidth(arr);//像素所占宽度
int height = textheight(arr);//像素所占高度
outtextxy(300 / 2 - width / 2 + 200, 50 / 2 - height / 2 + 50, "居中显示测试");//绘制字符串
//如果参数错误,找不到对应的函数
//是由于字符集导致的,那么解决方案有三种
//
//1.在字符串前面加大写的L 常用
//outtextxy(50, 50, L"大家好");
//
//2.用TEXT()把字符串包起来
//outtextxy(50, 50, TEXT("大家好"));
//
//3.用__TEXT()把字符串包起来
//
//实际上 TEXT() -> __TEXT() -> L"文本"
//
//4.不用添加任何代码,进 项目 -> 属性 -> 配置属性 -> 常规 -> 字符集 -> 改为多字节字符集 推荐使用这个!
int maye = 0;
cin >> maye;
cout << maye << endl;
//关闭窗口
closegraph();
system("pause");
return 0;
}
显示图片
-
在使用图像之前,需要定义一个变量(对象),然后把图片加载进变量才能使用。
- 平时定义变量都是使用的基础数据类型,比如:
int temp;
- 在使用图像的时候需要使用EasyX提供给我们的类型:IMAGE,如IMAGE img;
- 平时定义变量都是使用的基础数据类型,比如:
-
loadimage(IMAGE* pDstlmg,LPCTSTR plmgFile,int nWidth = 0,int nHeight = 0,bool bResize = false);从文件中读取图像
- pDstlmg //保存图像的IMAGE对象指针
- plmgFile //图片文件名
- nWidth = 0 //图片的拉伸宽度
- nHeight = 0 //图片的拉伸高度
- bResize = false //是否调整IMAGE的大小以适应图片
-
putimage(int dstX,int dstY,IMAGE* pSrclmg,DWORD dwRop = SRCCOPY);在当前设备上绘制指定的图像
- dstX //绘制位置的x坐标
- dstY //绘制位置的y坐标
- pSrclmg //要绘制的IMAGE对象指针
- dwRop = SRCCOPY //三元光栅操作码
示例代码:
#include <iostream>
#include <string>
#include <graphics.h>
using namespace std;
int main()
{
initgraph(640, 480, SHOWCONSOLE);
cleardevice();
//输出图片
IMAGE img;//定义一个对象
//加载图片
//相对路径 ./表示当前文件夹下(源文件所在的目录),../是当前文件夹的上一级目录
//绝对路径
loadimage(&img, "../666.jpg",640,480);
putimage(0, 0, &img);//(0,0)图片锚点是左上角
system("pause");
return 0;
}
鼠标操作
示例:
#include <iostream>
#include <string>
#include <easyx.h>
using namespace std;
void button(int x, int y, int w, int h,const char arr[])
{
setbkmode(TRANSPARENT);
setfillcolor(BROWN);
settextstyle(30, 0, "黑体");
fillroundrect(x, y, x + w, x + h, 10, 10);//10是圆角有多圆
int width = textwidth(arr);
int height = textheight(arr);
outtextxy(w / 2 - width / 2 + x, h / 2 - height / 2 + y, arr);
}
int main()
{
initgraph(640, 480, EX_SHOWCONSOLE);
button(50,50,150,150,"botton");
ExMessage msg;
while (1)
{
if (peekmessage(&msg, EX_MOUSE))
{
switch (msg.message)
{
case WM_LBUTTONDOWN:
if (msg.x >= 50 && msg.x <= 50 + 150 && msg.y >= 50 && msg.y <= 50 + 150)
{
cout << "我是按钮,我被点击了" << endl;
}
break;
default:
break;
}
}
}
system("pause");
return 0;
}
非EasyX函数——键盘消息函数
键盘消息函数用于获取键盘按键消息
-
getch();
需要头文件conio.h
-
getAsyncKeyState(键值);
需要头文件windows.h,但是由于EasyX包含了windows头文件,所以无需自己包含
(其他需要windows头文件的函数也一样,但是需要在graphics.h的下方包含:比如放音乐的头文件mmsystem.h)
-
getch(); 需要使用返回值来判断
-
与非ASCII表字符的按键比较,需要使用虚拟键值
上:72 下:80 左:75 右:77
-
如果是与字母比较直接写字母,比如’A’
-
详细使用方法,请看下图 (↓)
-
-
getAsyncKeyState(键值);需要传入一个键值,如果按下返回真
上:VK_UP 下:VK_DOWN 左:VK_LEFT 右:VK_RIGHT
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GRW96qyd-1686840888804)(E:\c.—c.—java-exercise\photo\QQ截图20230516183514.png)]
- 在设备上不断进行绘图操作时,会产生闪屏现象,针对这个现象,我们需要两个函数处理:
- BeginBatchDraw(); 开始批量绘图
- —中间放置绘图代码—
- EndBatchDraw(); 结束批量绘制
- GetHWnd(); 获取窗口句柄,获取之后可以用来操作窗口
9.2 容器map
9.2.1 map简介
map是c++标准模板库(STL)的一个关联容器,提供一对一的映射关系
“第一个”称为关键字(key),别名first,每个关键字只能在map中出现一次
“第二个”称为该关键字的值(value),别名second
**例:**建立一个朋友数据表,保存多个“姓名-电话号码”的对应关系,并保存在某种数据结构中
如:张三-123456
那么,可以定义一个map对象
map < string , string > friends;
把 朋友-电话号码 保存在friends中:
friends.insert("张三","123456"); //通过insert函数把张三以及对应他的电话号码保存在friends里面
要查询朋友的号码,通过
cout << "张三的电话号码是:" << friends.find("张三");
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, string>friends; //创建一个map映射
friends.insert(pair<string, string>("张三", "123456"));
//pair 由两个元素组成,分别命名为 first 和 second,它们可以是不同类型的任意数据类型,如 int,string 等。
//pair<string, string> 表示一个键和关联值都是 string 类型的 pair 对象。例如 pair<string, string> mypair ("hello", "world"); 用来定义一个字符串 “hello” 与字符串 “world” 的键值对形式的 pair 对象。
cout << "张三的电话号码是:" << friends.find("张三")->second; //find查询功能,second指电话号码
system("pause");
return 0;
}
**例:**给出一段英文
abacsdf
统计其中每个字母出现的次数
定义 map<char,int>cnt; //把每个字母出现的次数保存在cnt中
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<char, int> cnt; // 把每个字符出现的次数保存在 cnt 中
cnt.insert(pair<char, int>('a', 1));
cnt.insert(pair<char, int>('c', 1)); // 插入 ('c', 1) 键值对
// 将 a 字符的值增加 1
cnt['a']++;
// 输出每个字符出现的次数
for (auto& p : cnt) {
cout << p.first << ": " << p.second << endl;
}
/*
这是一个 C++ 11 引入的基于范围的 for 循环,也称为 for-each 循环,用于遍历容器(比如 vector,map,set 等)中的元素,无需使用迭代器,简化了代码的书写。
对于 map 容器,每个元素都是一对键值对,
因此 for (auto& p : cnt) 表示遍历 cnt 容器的所有元素,对于每个元素,auto& p 表示取出容器中的一个键值对,即键在 p.first 中,关联值在 p.second 中。
*/
system("pause");
return 0;
}
map以模版(泛型)的方式实现,可以储存任意类型的数据,包括使用者自定义的数据类型
如:
map<int,int>mp;
map<int,string>m2;
map<string,string>m3;
map<float,int>m4;
map<person,int>m6; //创建一个key位person型、value为int类型的map对象
在map内部所有的数据都是有序的
map由一棵红黑树实现,这棵树具有对数据自动排序的功能
9.2.2 插入元素
map<int,string>student;
方式一:用insert函数插入pair
student.insert(pair<int,string>(0,"Zhangsan"));
方式二:用insert函数插入value_type数据:
student.insert(map<int,string>::value_type(1,"Lisi"));
方式三:用类似数组的方式增加元素:
student[123]="Wangwu";
9.2.3 查找元素
find()返回一个迭代器,指向查找的元素,
找不到,则返回map::end()位置(NULL)
iter = student.find(123);
if(iter!=student.end())
cout<<"found,the value is"<<iter->second;
else
cout<<"not found";
如果关键字是整型,也可以通过
student[1]读取关键字1对应的值,如"Lisi"
9.2.4 引用方法
map<int,int>mp1;
第一种情况
int sum = 100;
mp1[10] = 3;
sum += map1[10]; //mp1中存在关键字10,它的对应值是3,所以sum累加后变为103
第二种情况
int sum = 100;
sum += map1[10]; //mp1中不存在关键字10,所以mp1返回的值是0,sum累加后仍为100
第三种情况
mp1[10]=3;
mp1[10]++; //mp1[10]的值变为4
第四种情况
mp1[20]++; //因关键字20不存在,增加一个关键字20,且其值从0自增到1
即mp1增加一个元素<20,1>
9.3 二叉数基本
根节点
左子树指针
右子树指针
孩子节点 LChild/2=parent(完全二叉树中任何一个左孩子节点除以2都等于父亲节点)
父节点
兄弟节点
姊妹节点
二叉树编序号从1开始
单一个体:结构体写法
9.3.1 基本概念
- 空二叉树:就是结构体指针 tree=NULL
- 只有根节点的二叉树
- 只有左子树或者右子树的二叉树
- 左右子树都存在的二叉树
- 完全二叉树:除了叶子节点(最后一个节点)之外,其他都是满的
- 满二叉树:左右子树都是完整的
9.3.2 遍历
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TIxaiCgR-1686840888812)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-06-13 204018.png)]
另:
层次遍历:就是从上到下依次遍历 ABC
前序遍历也叫先序遍历
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IU8imgVy-1686840888813)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-06-13 204508.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gCqSp7Sg-1686840888814)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-06-13 205400.png)]
9.3.3 创建、连接二叉树
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9oYOjK4q-1686840888814)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-06-13 212339.png)]
十、通讯录管理系统
10.1 系统要求
通讯录是一个可以记录亲人、好友的工具
本教程主要利用C++来实现一个通讯录管理系统
系统中需要实现的功能如下:
- 添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人
- 显示联系人:显示通讯录中所有联系人信息
- 删除联系人:按照姓名进行删除指定联系人
- 查找联系人:按照姓名查看指定联系人信息
- 修改联系人:按照姓名重新修改指定联系人
- 清空联系人:清空通讯录中所有信息
- 退出通讯录:退出当前使用的通讯录
10.2 创建项目
10.3 菜单功能
**功能描述:**用户选择功能的界面
菜单界面效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-65HPKZsn-1686840888814)(E:\c.—c.—java-exercise\photo\屏幕截图 2023-06-14 195405.png)]
步骤:
- 封装函数显示该界面 如:
void showMenu()
- 在main函数中调用封装好的函数
代码:
#include <iostream>
#include <stdio.h>
using namespace std;
void showMenu() //菜单界面View函数
{ //在控制台窗口打印菜单
cout << "*****************************" << endl;
cout << "***** 1、添加联系人 *****" << endl;
cout << "***** 2、显示联系人 *****" << endl;
cout << "***** 3、删除联系人 *****" << endl;
cout << "***** 4、查找联系人 *****" << endl;
cout << "***** 5、修改联系人 *****" << endl;
cout << "***** 6、清空联系人 *****" << endl;
cout << "***** 7、退出通讯录 *****" << endl;
cout << "*****************************" << endl;
}
int main()
{
showMenu();
return 0;
}
10.4 退出功能
**功能描述:**退出通讯录系统
思路:根据用户不同的选择,进入不同的功能,可以使用switch分支结构,将整个架构进行搭建
当用户选择0时,执行退出,选择其他先不做操作,也不会退出程序
代码:
int main()
{
int op;
while (1)
{
showMenu();
cin >> op;
switch (op)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 0:
cout << "退出成功" << endl;
break;
default:
cout << "未找到指令,请重新输入" << endl;
break;
}
break;
}
return 0;
}
10.5 添加联系人
功能描述:
实现添加联系人功能,联系人上限为1000人,联系人信息包括(姓名、性别、年龄、联系电话、家庭住址)
添加联系人实现步骤:
- 设计联系人结构体
- 设计通讯录结构体
- main函数中创建通讯录
- 封装添加联系人函数
- 测试添加联系人功能
10.5.1 设计联系人结构体
联系人信息包括:姓名、性别、年龄、联系电话、家庭住址
设计如下:
#include <string>
struct Contact //创建联系人结构体
{
string name; //姓名
int sex; //性别:1男,2女
double age; //年龄
int number; //号码
string address; //地址
};
10.5.2 设计通讯录结构体
设计时可以在通讯录结构体中,维护一个容量为1000的存放联系人的数组,并记录当前通讯录中联系人数量
设计如下
#define MAX 1000 //最大人数
struct addressBooks //创建通讯录结构体
{
Contact personArray[MAX]; //通讯录中保存联系人的数组
int Size; //通讯录中人员的个数
};
10.5.3 main函数中创建通讯录 & 添加联系人函数
//--------------------------Service---------------------------
void addPerson(addressBooks* abs)
{
//判断通讯录是否已满,如果满了就不再添加
if (abs->Size == MAX)
{
cout << "通讯录已满,无法添加" << endl;
return;
}
else
{
//添加具体联系人
//姓名
NAME:
string name1;
cout << "请输入姓名:" << endl;
cin >> name1;
//检测是否有同名
if(findPerson(abs,name1)==0) //用到之后写的查找联系人是否存在函数
{
abs->personArray[abs->Size].name = name1;
}
else
{
cout << "有同名联系人,请重新输入" << endl;
goto NAME;
}
//性别
int sex1;
cout << "请输入性别:1.男 2.女" << endl;
while (1)
{
cin >> sex1;
if (sex1 == 1 || sex1 == 2)
{
abs->personArray[abs->Size].sex = sex1;
break;
}
else
{
cout << "输入错误,请重新输入" << endl;
}
}
//年龄
double age1 = 0;
cout << "请输入年龄:" << endl;
cin >> age1;
abs->personArray[abs->Size].age = age1;
//电话
string number1;
cout << "请输入电话:" << endl;
cin >> number1;
abs->personArray[abs->Size].number = number1;
//住址
string address1;
cout << "请输入地址:" << endl;
cin >> address1;
abs->personArray[abs->Size].address = address1;
//更新通讯录人数
abs->Size++;
//提示完成
cout << "联系人添加完成" << endl;
system("pause"); //按任意键继续
system("cls"); //清屏操作
}
}
int main()
{
//创建通讯录结构体变量
addressBooks abs;
//初始化通讯录中当前人员个数
abs.Size = 0;
int op = 0;
while (1)
{
showMenu();
cin >> op;
switch (op)
{
case 1: //添加联系人
addPerson(&abs); //利用地址传递,可以修饰实参
break;
case 2: //显示联系人
break;
case 3: //删除联系人
break;
case 4: //查找联系人
break;
case 5: //修改联系人
break;
case 6: //清空联系人
break;
case 0: //退出通讯录
cout << "退出成功" << endl;
return 0;
default:
cout << "未找到指令,请重新输入" << endl;
break;
}
}
return 0;
}
10.6 显示联系人
功能描述:显示通讯录中已有的联系人信息
显示联系人实现步骤:
- 封装显示联系人函数
- 测试显示联系人功能
10.6.1 封装显示联系人函数
思路:判断如果当前通讯录中没有人员,就提示记录为空,人数大于0,显示通讯录中信息
显示联系人代码:
//显示联系人
void showPerson(addressBooks* abs)
{
if (abs->Size == 0)
{
cout << "记录为空" << endl;
system("pause");
system("cls"); //清屏操作
}
else
{
int i;
for (i = 0; i < abs->Size; i++)
{
cout << "姓名:" << abs->personArray[i].name << endl;
cout << "性别:" << (abs->personArray[i].sex == 1?"男":"女") << endl;
cout << "年龄:" << abs->personArray[i].age << endl;
cout << "电话:" << abs->personArray[i].number << endl;
cout << "地址:" << abs->personArray[i].address << endl;
cout << endl;
}
system("pause");
system("cls"); //清屏操作
}
}
10.7 删除联系人
功能描述:按照姓名进行删除指定联系人
删除联系人实现步骤
- 封装检测联系人是否存在
- 封装删除联系人函数
- 测试删除联系人功能
10.7.1 封装检测联系人是否存在
设计思路:
删除联系人前,我们需要先判断用户输入的联系人是否存在,如果存在删除,不存在提示用户没有要删除的联系人,因此我们可以把检测联系人是否存在封装成一个函数中,如果存在,返回联系人在通讯录中的位置,不存在返回-1
//检测联系人是否存在
int findPerson(addressBooks* abs, string name)
{
int i;
for (i = 0; i < abs->Size; i++)
{
if (name == abs->personArray[i].name)
{
return i;
}
}
return -1;
}
10.7.2 封装删除联系人函数
//删除联系人
void delPerson(addressBooks* abs, int i)
{
for (int j = i; j < abs->Size; j++)
{
abs->personArray[j] = abs->personArray[j + 1];
abs->Size--;
}
}
10.8 查找联系人
功能描述:按照姓名查看联系人信息
查找联系人实现步骤
- 封装查找联系人函数
- 测试查找指定联系人
10.8.1 封装查找联系人函数
注:上面已经实现过该函数,做部分修改即可
实现思路:判断用户指定的联系人是否存在,如果存在显示信息,不存在提示查无此人
查找联系人代码:
case 4: //查找联系人
{
cout << "请输入要查找的联系人姓名:" << endl;
string tmpname;
cin >> tmpname;
int tmp = findPerson(&abs, tmpname);
if (tmp == -1)
{
cout << "查无此人" << endl;
system("pause");
system("cls"); //清屏操作
}
else
{
cout << endl;
cout << "姓名:" << abs.personArray[tmp].name << endl;
cout << "性别:" << (abs.personArray[tmp].sex == 1 ? "男" : "女") << endl;
cout << "年龄:" << abs.personArray[tmp].age << endl;
cout << "电话:" << abs.personArray[tmp].number << endl;
cout << "地址:" << abs.personArray[tmp].address << endl;
cout << endl;
system("pause");
system("cls"); //清屏操作
}
break;
}
10.9 修改联系人
功能描述:按照姓名重新修改指定联系人
修改联系人实现步骤
- 封装修改联系人函数
- 测试修改联系人函数
10.9.1 封装修改联系人函数
实现思路:查找用户输入的联系人,如果查找成功进行修改操作,查找失败提示查无此人
修改联系人代码:
//修改联系人
void modifyPerson(addressBooks* abs)
{
cout << "请输入您想修改的联系人姓名:" << endl;
MODIFY:
string tmpname;
cin >> tmpname;
int tmp = findPerson(abs, tmpname); //查找联系人
if (tmp == -1) //未找到联系人
{
cout << "未查找到你想修改的联系人,请选择:"<<endl;
char op;
cout << "1.重新输入联系人姓名 或 2.退出修改" << endl;
MODIFY3:
cin >> op;
switch (op)
{
case '1':
cout << "请输入您想修改的联系人姓名:" << endl;
goto MODIFY;
case '2':
system("cls");
break;
default:
cout << "指令错误,请重新输入:" << endl;
goto MODIFY3;
}
}
else //找到联系人
{
cout << "找到了您想修改的联系人:" << tmpname << endl;
cout << "请选择您想修改的联系人信息:" << endl;
char op;
cout << "1.姓名 2.性别 3.年龄 4.电话 5.住址 6.退出修改" << endl;
MODIFY2:
cin >> op;
switch (op)
{
case '1':
{
//修改姓名
cout << "请输入修改后的姓名:" << endl;
string name1;
cin >> name1;
abs->personArray[tmp].name = name1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '2':
{
//修改性别
cout << "请输入修改后的性别:1.男 2.女" << endl;
MODIFY1:
int sex1;
cin >> sex1;
if (sex1 == 1 || sex1 == 2)
{
abs->personArray[tmp].sex = sex1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
else
{
cout << "输入错误,请重新输入 1 or 2 :" << endl;
goto MODIFY1;
}
}
case '3':
{
//修改年龄
cout << "请输入修改后的年龄:" << endl;
double age1;
cin >> age1;
abs->personArray[tmp].age = age1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '4':
{
//修改联系电话
cout << "请输入修改后的电话:" << endl;
string number1;
cin >> number1;
abs->personArray[tmp].number = number1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '5':
{
//修改住址
cout << "请输入修改后的住址:" << endl;
string address1;
cin >> address1;
abs->personArray[tmp].address = address1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '6':
{
//退出选择
system("cls");
break;
}
default:
cout << "指令输入错误,请重新输入:" << endl;
goto MODIFY2;
}
}
}
10.10 清空联系人
功能描述:清空通讯录中的所有信息
清空联系人实现步骤
- 封装清空联系人函数
- 测试清空联系人
10.10.1 封装清空联系人函数
实现思路:将通讯录所有联系人信息清除掉,只要将通讯录记录的联系人数置为0,做逻辑清空即可
清空联系人代码:
//清空联系人
void cleanPerson(addressBooks* abs)
{
cout << "您确定要清空通讯录么?" << endl;
char op;
cout << "1.是 2.否" << endl;
CLEAN:
cin >> op;
switch (op)
{
case '1':
{
abs->Size = 0;
cout << "通讯录已清空" << endl;
system("pause");
system("cls");
}
case '2':
{
system("cls");
break;
}
default:
{
cout << "指令错误,请重新输入:" << endl;
goto CLEAN;
}
}
}
10.11 总结
全部代码:
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
#define MAX 1000 //最大人数
struct Contact //创建联系人结构体
{
string name; //姓名
int sex; //性别:1男,2女
double age; //年龄
string number; //号码
string address; //地址
};
struct addressBooks //创建通讯录结构体
{
struct Contact personArray[MAX]; //通讯录中保存联系人的数组
int Size; //通讯录中人员的个数
};
//--------------------------View-----------------------------
void showMenu() //菜单界面View函数
{ //在控制台窗口打印菜单
cout << "*****************************" << endl;
cout << "***** 1、添加联系人 *****" << endl;
cout << "***** 2、显示联系人 *****" << endl;
cout << "***** 3、删除联系人 *****" << endl;
cout << "***** 4、查找联系人 *****" << endl;
cout << "***** 5、修改联系人 *****" << endl;
cout << "***** 6、清空联系人 *****" << endl;
cout << "***** 0、退出通讯录 *****" << endl;
cout << "*****************************" << endl;
cout << "请输入指令:" << endl;
}
//--------------------------Service---------------------------
//检测联系人是否存在
int findPerson(addressBooks* abs, string name)
{
int i;
for (i = 0; i < abs->Size; i++)
{
if (name == abs->personArray[i].name)
{
return i;
}
}
return -1;
}
//添加联系人
void addPerson(addressBooks* abs)
{
//判断通讯录是否已满,如果满了就不再添加
if (abs->Size == MAX)
{
cout << "通讯录已满,无法添加" << endl;
return;
}
else
{
//添加具体联系人
//姓名
NAME:
string name1;
cout << "请输入姓名:" << endl;
cin >> name1;
if (abs->Size == 0)
{
abs->personArray[abs->Size].name = name1;
}
else
{
//检测是否有同名
if (findPerson(abs, name1) == -1) //用到之后写的查找联系人是否存在函数
{
abs->personArray[abs->Size].name = name1;
}
else
{
cout << "有同名联系人,请重新输入" << endl;
goto NAME;
}
}
//性别
int sex1;
cout << "请输入性别:1.男 2.女" << endl;
while (1)
{
cin >> sex1;
if (sex1 == 1 || sex1 == 2)
{
abs->personArray[abs->Size].sex = sex1;
break;
}
else
{
cout << "输入错误,请重新输入" << endl;
}
}
//年龄
double age1 = 0;
cout << "请输入年龄:" << endl;
cin >> age1;
abs->personArray[abs->Size].age = age1;
//电话
string number1;
cout << "请输入电话:" << endl;
cin >> number1;
abs->personArray[abs->Size].number = number1;
//住址
string address1;
cout << "请输入地址:" << endl;
cin >> address1;
abs->personArray[abs->Size].address = address1;
//更新通讯录人数
abs->Size++;
//提示完成
cout << "联系人添加完成" << endl;
system("pause");
system("cls"); //清屏操作
}
}
//显示联系人
void showPerson(addressBooks* abs)
{
if (abs->Size == 0)
{
cout << "当前记录为空" << endl;
system("pause");
system("cls"); //清屏操作
}
else
{
int i;
for (i = 0; i < abs->Size; i++)
{
cout << "姓名:" << abs->personArray[i].name << endl;
cout << "性别:" << (abs->personArray[i].sex == 1?"男":"女") << endl;
cout << "年龄:" << abs->personArray[i].age << endl;
cout << "电话:" << abs->personArray[i].number << endl;
cout << "地址:" << abs->personArray[i].address << endl;
cout << endl;
}
system("pause");
system("cls"); //清屏操作
}
}
//删除联系人
void delPerson(addressBooks* abs, int i)
{
for (int j = i; j < abs->Size; j++)
{
abs->personArray[j] = abs->personArray[j + 1];
abs->Size--;
}
}
//修改联系人
void modifyPerson(addressBooks* abs)
{
cout << "请输入您想修改的联系人姓名:" << endl;
MODIFY:
string tmpname;
cin >> tmpname;
int tmp = findPerson(abs, tmpname); //查找联系人
if (tmp == -1) //未找到联系人
{
cout << "未查找到你想修改的联系人,请选择:"<<endl;
char op;
cout << "1.重新输入联系人姓名 或 2.退出修改" << endl;
MODIFY3:
cin >> op;
switch (op)
{
case '1':
cout << "请输入您想修改的联系人姓名:" << endl;
goto MODIFY;
case '2':
system("cls");
break;
default:
cout << "指令错误,请重新输入:" << endl;
goto MODIFY3;
}
}
else //找到联系人
{
cout << "找到了您想修改的联系人:" << tmpname << endl;
cout << "请选择您想修改的联系人信息:" << endl;
char op;
cout << "1.姓名 2.性别 3.年龄 4.电话 5.住址 6.退出修改" << endl;
MODIFY2:
cin >> op;
switch (op)
{
case '1':
{
//修改姓名
cout << "请输入修改后的姓名:" << endl;
string name1;
cin >> name1;
abs->personArray[tmp].name = name1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '2':
{
//修改性别
cout << "请输入修改后的性别:1.男 2.女" << endl;
MODIFY1:
int sex1;
cin >> sex1;
if (sex1 == 1 || sex1 == 2)
{
abs->personArray[tmp].sex = sex1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
else
{
cout << "输入错误,请重新输入 1 or 2 :" << endl;
goto MODIFY1;
}
}
case '3':
{
//修改年龄
cout << "请输入修改后的年龄:" << endl;
double age1;
cin >> age1;
abs->personArray[tmp].age = age1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '4':
{
//修改联系电话
cout << "请输入修改后的电话:" << endl;
string number1;
cin >> number1;
abs->personArray[tmp].number = number1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '5':
{
//修改住址
cout << "请输入修改后的住址:" << endl;
string address1;
cin >> address1;
abs->personArray[tmp].address = address1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '6':
{
//退出选择
system("cls");
break;
}
default:
cout << "指令输入错误,请重新输入:" << endl;
goto MODIFY2;
}
}
}
//清空联系人
void cleanPerson(addressBooks* abs)
{
cout << "您确定要清空通讯录么?" << endl;
char op;
cout << "1.是 2.否" << endl;
CLEAN:
cin >> op;
switch (op)
{
case '1':
{
abs->Size = 0;
cout << "通讯录已清空" << endl;
system("pause");
system("cls");
}
case '2':
{
system("cls");
break;
}
default:
{
cout << "指令错误,请重新输入:" << endl;
goto CLEAN;
}
}
}
int main()
{
//创建通讯录结构体变量
addressBooks abs;
//初始化通讯录中当前人员个数
abs.Size = 0;
char op = 0;
while (1)
{
showMenu();
cin >> op;
switch (op)
{
case '1': //添加联系人
addPerson(&abs); //利用地址传递,可以修饰实参
break;
case '2': //显示联系人
showPerson(&abs);
break;
case '3': //删除联系人
{
cout << "请输入要删除的联系人姓名:" << endl;
string tmpname;
DELPERSON:
cin >> tmpname;
int tmp = findPerson(&abs, tmpname);
if (tmp == -1)
{
cout << "未找到您要删除的联系人,请重新输入:" << endl;
goto DELPERSON;
}
else
{
delPerson(&abs, tmp);
cout << "删除成功" << endl;
}
break;
}
case '4': //查找联系人
{
cout << "请输入要查找的联系人姓名:" << endl;
string tmpname;
cin >> tmpname;
int tmp = findPerson(&abs, tmpname);
if (tmp == -1)
{
cout << "查无此人" << endl;
system("pause");
system("cls"); //清屏操作
}
else
{
cout << endl;
cout << "姓名:" << abs.personArray[tmp].name << endl;
cout << "性别:" << (abs.personArray[tmp].sex == 1 ? "男" : "女") << endl;
cout << "年龄:" << abs.personArray[tmp].age << endl;
cout << "电话:" << abs.personArray[tmp].number << endl;
cout << "地址:" << abs.personArray[tmp].address << endl;
cout << endl;
system("pause");
system("cls"); //清屏操作
}
break;
}
case '5': //修改联系人
modifyPerson(&abs);
break;
case '6': //清空联系人
cleanPerson(&abs);
break;
case '0': //退出通讯录
cout << "退出成功!" << endl;
return 0;
default:
cout << "未找到指令,请重新输入" << endl;
system("pause");
system("cls");
break;
}
}
return 0;
}
].sex = sex1;
break;
}
else
{
cout << “输入错误,请重新输入” << endl;
}
}
//年龄
double age1 = 0;
cout << "请输入年龄:" << endl;
cin >> age1;
abs->personArray[abs->Size].age = age1;
//电话
string number1;
cout << "请输入电话:" << endl;
cin >> number1;
abs->personArray[abs->Size].number = number1;
//住址
string address1;
cout << "请输入地址:" << endl;
cin >> address1;
abs->personArray[abs->Size].address = address1;
//更新通讯录人数
abs->Size++;
//提示完成
cout << "联系人添加完成" << endl;
system("pause");
system("cls"); //清屏操作
}
}
//显示联系人
void showPerson(addressBooks* abs)
{
if (abs->Size == 0)
{
cout << “当前记录为空” << endl;
system("pause");
system("cls"); //清屏操作
}
else
{
int i;
for (i = 0; i < abs->Size; i++)
{
cout << "姓名:" << abs->personArray[i].name << endl;
cout << "性别:" << (abs->personArray[i].sex == 1?"男":"女") << endl;
cout << "年龄:" << abs->personArray[i].age << endl;
cout << "电话:" << abs->personArray[i].number << endl;
cout << "地址:" << abs->personArray[i].address << endl;
cout << endl;
}
system("pause");
system("cls"); //清屏操作
}
}
//删除联系人
void delPerson(addressBooks* abs, int i)
{
for (int j = i; j < abs->Size; j++)
{
abs->personArray[j] = abs->personArray[j + 1];
abs->Size–;
}
}
//修改联系人
void modifyPerson(addressBooks* abs)
{
cout << “请输入您想修改的联系人姓名:” << endl;
MODIFY:
string tmpname;
cin >> tmpname;
int tmp = findPerson(abs, tmpname); //查找联系人
if (tmp == -1) //未找到联系人
{
cout << “未查找到你想修改的联系人,请选择:”<<endl;
char op;
cout << “1.重新输入联系人姓名 或 2.退出修改” << endl;
MODIFY3:
cin >> op;
switch (op)
{
case ‘1’:
cout << “请输入您想修改的联系人姓名:” << endl;
goto MODIFY;
case '2':
system("cls");
break;
default:
cout << "指令错误,请重新输入:" << endl;
goto MODIFY3;
}
}
else //找到联系人
{
cout << "找到了您想修改的联系人:" << tmpname << endl;
cout << "请选择您想修改的联系人信息:" << endl;
char op;
cout << "1.姓名 2.性别 3.年龄 4.电话 5.住址 6.退出修改" << endl;
MODIFY2:
cin >> op;
switch (op)
{
case '1':
{
//修改姓名
cout << "请输入修改后的姓名:" << endl;
string name1;
cin >> name1;
abs->personArray[tmp].name = name1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '2':
{
//修改性别
cout << "请输入修改后的性别:1.男 2.女" << endl;
MODIFY1:
int sex1;
cin >> sex1;
if (sex1 == 1 || sex1 == 2)
{
abs->personArray[tmp].sex = sex1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
else
{
cout << "输入错误,请重新输入 1 or 2 :" << endl;
goto MODIFY1;
}
}
case '3':
{
//修改年龄
cout << "请输入修改后的年龄:" << endl;
double age1;
cin >> age1;
abs->personArray[tmp].age = age1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '4':
{
//修改联系电话
cout << "请输入修改后的电话:" << endl;
string number1;
cin >> number1;
abs->personArray[tmp].number = number1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '5':
{
//修改住址
cout << "请输入修改后的住址:" << endl;
string address1;
cin >> address1;
abs->personArray[tmp].address = address1;
cout << "修改成功!" << endl;
goto MODIFY2;
}
case '6':
{
//退出选择
system("cls");
break;
}
default:
cout << "指令输入错误,请重新输入:" << endl;
goto MODIFY2;
}
}
}
//清空联系人
void cleanPerson(addressBooks* abs)
{
cout << “您确定要清空通讯录么?” << endl;
char op;
cout << “1.是 2.否” << endl;
CLEAN:
cin >> op;
switch (op)
{
case ‘1’:
{
abs->Size = 0;
cout << “通讯录已清空” << endl;
system(“pause”);
system(“cls”);
}
case ‘2’:
{
system(“cls”);
break;
}
default:
{
cout << “指令错误,请重新输入:” << endl;
goto CLEAN;
}
}
}
int main()
{
//创建通讯录结构体变量
addressBooks abs;
//初始化通讯录中当前人员个数
abs.Size = 0;
char op = 0;
while (1)
{
showMenu();
cin >> op;
switch (op)
{
case '1': //添加联系人
addPerson(&abs); //利用地址传递,可以修饰实参
break;
case '2': //显示联系人
showPerson(&abs);
break;
case '3': //删除联系人
{
cout << "请输入要删除的联系人姓名:" << endl;
string tmpname;
DELPERSON:
cin >> tmpname;
int tmp = findPerson(&abs, tmpname);
if (tmp == -1)
{
cout << "未找到您要删除的联系人,请重新输入:" << endl;
goto DELPERSON;
}
else
{
delPerson(&abs, tmp);
cout << "删除成功" << endl;
}
break;
}
case '4': //查找联系人
{
cout << "请输入要查找的联系人姓名:" << endl;
string tmpname;
cin >> tmpname;
int tmp = findPerson(&abs, tmpname);
if (tmp == -1)
{
cout << "查无此人" << endl;
system("pause");
system("cls"); //清屏操作
}
else
{
cout << endl;
cout << "姓名:" << abs.personArray[tmp].name << endl;
cout << "性别:" << (abs.personArray[tmp].sex == 1 ? "男" : "女") << endl;
cout << "年龄:" << abs.personArray[tmp].age << endl;
cout << "电话:" << abs.personArray[tmp].number << endl;
cout << "地址:" << abs.personArray[tmp].address << endl;
cout << endl;
system("pause");
system("cls"); //清屏操作
}
break;
}
case '5': //修改联系人
modifyPerson(&abs);
break;
case '6': //清空联系人
cleanPerson(&abs);
break;
case '0': //退出通讯录
cout << "退出成功!" << endl;
return 0;
default:
cout << "未找到指令,请重新输入" << endl;
system("pause");
system("cls");
break;
}
}
return 0;
}
## 十一、基础入门完结:2023/6/15 ---宇昕