C++基础入门
1 C++初识
1.1第一个C++程序
代码格式:
#include<iostream>//头文件
using namespace std;//使用标准文库
int main()
{
cout<<"hello world"<<endl;//cout 输出 endl 换行
system("pause");//屏幕暂停
return 0;
}
1.2注释
1.单行注释:// 行代码说明 放在代码上方或一条语句后面
2.多行注释:/* …*/ 段代码说明 放在代码上面
1.3变量
作用:给一段指定空间起名字,方便操作这段内存
语法:数据类型 变量名 =初始值//int a=10;
1.4常量
作用:用于记录程序中不可更改的数据
C++定义常量的两种方式(与c相同)
1.#define 宏常量:#define 常量名 常量值
- 通常在文件上方定义,表示一个常量
2.const修饰的变量 const 数据类型 常量名=常量值
- 通常在变量定义前加
const
,修饰该变量为常量不可修改
示例:
#include<iostream>
using namespace std;
//宏定义不可修改
#define Day 7
int main()
{
//Day为常量修改会报错
cout<<"一周共有:"<<Day<<"天"<<endl;
//const修饰的变量为常量
const int a=10;
cout<<a<<endl;
system ("pause") ;
return 0;
}
1.5关键字
作用:关键字是c++中预先保留的单词(标识符)
- 在定义变量或者常量时,不要用关键字
C++关键字如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZqGhsoo-1617370508935)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210301110328008.png)]
1.6标识符命名规则
作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则
- 标识符不能是关键字
- 标识符只能由字母、数字、下划线组成
- 第一个字符必须为下划线或字母
- 标识符中字母区分大小写
建议:给标识符命名时,争取做到见名知章的效果,方便自己和他人阅读(英语基础要扎实)
2 数据类型
C++规定在创建一个变量或者常量时,必须要指出相应的数据类型,否则无法给变量分配内存
2.1整型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hz034ccR-1617370508954)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210301112325673.png)]
短整型的取值范围是(-32768–32767) 超过则数据溢出从头开始
整型大小比较:short<int<=long(windows-4字节;linus-8字节)<=long long
2.2sizeof关键字
作用:利用sizeof关键字可以统计数据类型所占大小
语法:sizeof(整型类型 / 变量)
(/或者)
示例:
#include<iostream>
using namespace std;
int main()
{
cout<<"short占用空间内存为:" <<sizeof(short)<<endl;
cout<<"int占用空间内存为:" <<sizeof(int)<<endl;
long a=10;
cout<<"long占用空间内存为:" <<sizeof(a)<<endl;
cout<<"long long用空间内存为:" <<sizeof(long long)<<endl;
system ("pause") ;
return 0;
}
2.3实型
作用:用于表示小数
浮点型变量分为两类:
1.单精度float
2.双精度double
两者区别在于表示的有效数字不同。默认情况下输出一个小数会显示出6位有效数字
数据类型 | 占用空间 | 有效数字范围 |
---|---|---|
float | 4字节 | 7位有效数字 |
double | 8字节 | 15-16位有效数字 |
float a=3.214f;(最好带f表示float)
科学计数法:3e2= 3* 10*10(10的平方)
2.4字符型
作用:字符型变量用于显示单个字符
;
语法:char ch = 'a';
注意1:在显示字符型变量时,用单引号将字符括起来,不要用单引号
注意2:单引号内只能有一个字符,不可以是字符串
C和C++中的字符型变量只占用一个字节。
字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元。
char ch=‘a’;(a:97 ; A:65)
cout<<(int)ch<<endl;
output:97
ASCII表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XWIeXiOz-1617370508965)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210301120342895.png)]
2.5转义字符
作用:用于表示一些不能显示出来的**ASCII字符(c语言为/n)
现阶段常用:\n(换行) \ \(代表一个反斜杠\) \t(水平制表(HT)跳到下一个TAB 8个字符位置)
对齐 \t
示例:
#include<iostream>
using namespace std;
int main()
{
cout<<"aaaa\t helloworld"<<endl;
cout<<"aa\t helloworld"<<endl;
cout<<"aaaaaa\t helloworld"<<endl;
return 0;
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fK9Fecrj-1617370508979)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210301141211480.png)]
2.6字符串型
作用:用于表示一串字符
两种风格
1.C版本:char 变量名[ ] = "字符串值"
示例:
int main()
{
char str1[]="hello world";
cout<<str1<<endl;
system("pause");
return 0;
}
注意:C风格的字符串要用双引号括起来
2.C++风格:要加 #include 头文件
string 变量名 = “字符串值”
示例:
string str2="hello world";
2.7布尔类型 bool
作用:布尔数据类型代表真或假的值
bool类型只有两个值:
- true----真 (本质是1)
- false—假(本质是0)
bool类型只占一个字节大小
示例:
int main(){
//1.创建bool数据类型
bool flag = true;//true代表假
cout<<flag<<endl;
flag = false;//false代表假
cout<<flag<<endl;
//2.查看bool类型所占内存
cout<<"bool所占空间大小为 :"<<sizeof(bool)<<endl;
system("pause");
return 0;
}
2.8数据的输入
作用:用于从键盘上获取数据
关键字:cin
语法:cin>> 变量
示例:
int main(){
//1.整型
int a=0;
cout<<"请输入一个整型:"<<endl;
cin>>a;
cout<<"整型 a ="<<a<<endl;
//2.浮点型
float f=0;
cout<<"请输入一个浮点型:"<<endl;
cin>>f;
cout<<"float="<<f<<endl;
//3.字符型
char ch='a';
cout<<"请输入一个字符型:"<<endl;
cin>>ch;
cout<<"char="<<ch<<endl;
//4.字符串型
string str1="as";
cout<<"请输入一个字符串型:"<<endl;
cin>>str1;
cout<<"str1="<<str1<<endl;
//5.bool类型
bool flag=false;
cout<<"请给布尔类型赋值:" <<endl;
cin>>flag;//非0都为真值
cout<<"布尔类型的值为:" <<flag<<endl;
return 0;
}
3 运算符
作用:用于执行代码的运算
运算符类型 | 作用 |
---|---|
算术运算符 | 用于处理四则运算 |
赋值运算符 | 用于将表达式的值赋给变量 |
比较运算符 | 用于表达式比较,并返回一个真值或假值 |
逻辑运算符 | 用于根据表达式的值返回真值或假值 |
3.1算术运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XvkclO2i-1617370508985)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302122921934.png)]
注意:
1.a++:先传递a的值再将a+1
2.两个数相除为0,不能取模 %
3.两个小数不可以做取模运算
4.只有整型变量才可以进行取模运算
3.2赋值运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YARk3VXU-1617370509095)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302124458953.png)]
3.3比较运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HzQvZev7-1617370509102)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302124408833.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KXNt0zSW-1617370509110)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302124329441.png)]
3.4逻辑运算符
作用:用于表达式的值返回真值或假值
逻辑运算有以下符号
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
! | 非 | !a | 如果a为假,则!a为真;反之相反 |
&& | 与 | a&&b | 如果a,b都为真,则结果为真;否则为假 |
|| | 或 | a||b | a,b其中一个为真,则结果为真 |
C++中除了0都为真;
4 程序流程结构
C/C++支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构
- 顺序结构:程序按顺序进行,不发生跳转
- 选择结构:依据条件是否满足,有选择的执行相应的功能
- 循环结构:依据条件是否满足,循环多次执行某段代码
4.1选择结构
4.1.1 if语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iNf57Idw-1617370509116)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302154148717.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6dhCwO6O-1617370509121)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302155704547.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TqrG8Y1h-1617370509126)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302155553534.png)]
int main(){
int score=0;
cout<<"请输入高考分数:"<<endl;
cin>>score;
//注意从大到小判断
if(score>650)
cout<<"恭喜你考上清华"<<endl;
else if(score>500)
cout<<"恭喜你考上一本"<<endl;
else if(score>400)
cout<<"恭喜你考上本科"<<endl;
else
cout<<"继续努力" <<endl;
system("pause");
return 0;
}
if语句可以多层嵌套
练习案例:三只小猪称体重
有三只小猪ABC,请分别输入三只小猪的体重,并且判断哪只小猪最重?
代码示例:
#include<iostream>
using namespace std;
int main(){
int a=0,b=0,c=0;
cout<<"请输入三只小猪的体重"<<endl;
cin>>a;
cin>>b;
cin>>c;
//a和b比 两种情况 最大的和c比两种情况 一共4种情况
if(a>b){
if(a>c)
cout<<"A小猪最重"<<endl;
else
cout<<"C小猪最重"<<endl;
}
else
{
if(b>c)
cout<<"B小猪最重"<<endl;
else
cout<<"C小猪最重"<<endl;
}
system("pause");
return 0;
}
4.1.2 三目运算符
作用:通过三目运算符实现简单的判断
语法: 表达式1 ? 表达式 2 :表达式 3
解释:
如果表达式1为真,执行表达式2,并返回表达式2的结果;
如果表达式1为假,执行表达式3,并返回表达式3的结果;
示例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ew3sXN2x-1617370509131)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302162455647.png)]
4.1.3 switch语句
作用:执行多条件分支语句
语法:
swith(表达式)
{
case 结果1:执行语句;break;
case 结果2:执行语句;break;
...
default :执行语句;break;
}
if和switch的区别:
switch缺点,判断时候只能是整型或字符型,不可以是一个区间
switch优点,结构清晰,执行效率高
示例:(电影评分)
int main(){
int score=0;
cout<<"请输入电影评分:" <<endl;
cin>>score;
switch(score)
{
case 10 :cout<<"很棒!"<<endl;break;
case 9 :cout<<"很棒!"<<endl;break;
case 8 :cout<<"不错!"<<endl;break;
case 6 :cout<<"还行!"<<endl;break;
case 5 :cout<<"还好!"<<endl;break;
default :cout<<"烂片!"<<endl;break;
}
system("pause");
return 0;
}
4.2 循环结构
4.2.1while循环语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tz1KmMNv-1617370509137)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302174109984.png)]
注意:在执行语句时避免死循环 while(1)
练习:猜数字
案例描述:系统会随机生成一个1到100的数字,玩家进行猜测,如果猜错提示玩家数字过大或过小,如果猜对恭喜玩家胜出。
#include<iostream>
#include<cstdlib>//srand头文件
using namespace std;
#include<ctime>
int main(){
// 添加随机数种子 作用利用当前系统时间生成随机数,防止每次随机数一样
srand ((unsigned int)time(NULL));
// 1.系统生成随机数
int num = rand() %100 +1;//rand()%100+1生成1-100的随机数
// 2.玩家进行猜测
int value=0;
// 3.判断玩家猜测
// 猜对 退出游戏
// 猜错 提示猜的结果 过大或过小 重新返回第2步
while(1)
{
cin>>value;
if(value>num)
cout<<"太大了"<<endl;
else if(value<num)
cout<<"太小了"<<endl;
else
{
cout<<"恭喜答对了就是:"<<num<<endl;break;
}
}
system("pause");
return 0;
}
4.2.2do…while语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HDWPb5Dz-1617370509141)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210302184950231.png)]
练习案例:水仙花数
案例描述:水仙花数是一个3位数,它的每个位上的数字的3次幂之和等于它本身
例如:13+53+3^3=153
请利用do…while语句,求出所有3位数中的水仙花数
int main(){
int num=2;
do{
int a=0;
int b=0;
int c=0;
a=num/100;
b=num%100/10;
c=num%100%10;
if(a*a*a+b*b*b+c*c*c == num)
{
cout<<num<<endl;
}
num++;
}
while(num<1000);
system("pause");
return 0;
}
4.2.3 for循环语句
作用:满足循环条件,执行循环语句
语法:for(起始表达式;末尾是循环体){循环语句;}
示例:
//打印1-9的数字
int main(){
for(int i=1;i<10;i++)
{
cout<<i<<endl;
}
system("pause");
return 0;
}
案例练习:敲桌子
案例描述:从1开始到数字100,如果数字个位含有7,或者十位含有7,或者该数字是7的倍数,我们打印敲桌子,其余打印数字
#include<iostream>
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 嵌套循环
作用:在循环体中再嵌套一层循环,解决一些实际问题
打印正方形(4行5列):
#include<iostream>
using namespace std;
int main(){
int i,j;
//行嵌套列
for(i=0;i<4;i++)
{
for(j=0;j<5;j++)//一行有五个(列)
{
cout<<"* ";
}
cout<<endl;
}
system("pause");//在比赛的时候不能写
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WdALumo9-1617370509144)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210306160051967.png)]
练习案例:9*9乘法表
#include<iostream>
using namespace std;
int main(){
int i,j;
//行嵌套列
for(i=1;i<10;i++)
{
for(j=1;j<=i;j++)
{
cout<<i<<"*"<<j<<"="<<i*j<<" ";
}
cout<<endl;
}
system("pause");//在比赛的时候不能写
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rCARURW9-1617370509148)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210306161206540.png)]
4.3 break语句
4.3.1 break语句
作用:用于跳出选择语句或者循环语句(不会再执行后面的值)
break使用的时机:
- 出现在switch语句中,作用是终止case并跳出swith
- 出现在循环语句中,作用是跳出当前循环语句
- 出现在嵌套循环中,跳出最近的内层循环语句
4.3.2 continue语句
作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
示例:
int main(){
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语句时,会跳转到标记位置
示例:
int main(){
cout<<"1"<<endl;
goto FLAG;
cout<<"2"<<endl;
cout<<"3"<<endl;
cout<<"5"<<endl;
cout<<"6"<<endl;
cout<<"7"<<endl;
FLAG:
cout<<"s"<<endl;
system("pause");
return 0;
}
结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wKQklAGZ-1617370509154)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210306194113875.png)]
5 数组
5.1 概述
所谓数组,就是一个集合,里面存放了相同类型的数据元素
特点1:数组中的每个数据元素都是相同的数据类型
特点2:数组是由连续的内存位置组成的
5.2 一维数组
5.2.1 一维的定义方式
三种:
1.数据类型 数组名[ 数组长度 ];
2.数据类型 数组名[ 数组长度 ] = {值1,值2,值3…};
3.数据类型 数组名[ ] = {值1,值2…}
数组下标从0开始
定义数组时,必须有初始长度
5.2.2 一维数组数组名
一维数组数组名的用途:
1.可以统计整个数组在内存中的长度
2.可以获取数组在内存中的首地址
示例:
#include<iostream>
using namespace std;
int main(){
// 数组名用途
// 1.可以获取整个数组占用空间内存大小
int arr[10]={0,1,2,3,4,5,6,7,8,9};
cout<<"整个数组所占的内存空间为:"<<sizeof(arr)<<endl;
cout<<"每个元素所占的内存空间为:"<<sizeof(arr[0])<<endl;
cout<<"数组元素的个数为:"<<sizeof(arr)/sizeof(arr[0])<<endl;
// 2.可以通过数组名获取到数组首地址(int)arr转换为10进制
cout<<"数组的首地址为:"<<arr<<endl;
cout<<"数组中第一个元素的地址为:"<<&arr[0]<<endl;
cout<<"数组中第二个元素的地址为:"<<&arr[1]<<endl;
//数组名是常量 不可以进行赋值操作 arr=100(x)
system("pause");
return 0;
}
结果运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-82HUqLiX-1617370509159)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210306201753774.png)]
联系案例1:五只小猪称体重
案例描述:
在一个数组中记录了五只小猪的体重,如int arr[5]={300,350,200,400,250};
找出并打印最重的小猪。
int main(){
int arr[5]={300,350,200,400,250};
int max=0;
for(int i=0;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);
方法1:
int main(){
int arr[5]={1,2,3,4,5};
for(int i=4;i>=0;i--)
{
cout<<arr[i]<<endl;
}
system("pause");
return 0;
}
方法2:利用一个新的空间temp
int temp=arr[start];(start以空,进入temp)
arr[start]=arr[end];(end以空,进入start)
arr[end]=temp;(将temp放进end中)
start++,end–,当start>=end时不交换
int main(){
int arr[5]={2,4,5,1,8};
int temp=0;
int start=0;
int end=sizeof(arr)/sizeof(arr[0])-1;
cout<<"数组元素逆置前:"<<endl;
for(int i=0;i<5;i++){
cout<<arr[i]<<endl;
}
cout<<"数组元素逆置后:"<<endl;
for(int i=0;i<5;i++){
while(start<end){
temp=arr[start];
arr[start]=arr[end];
arr[end]=temp;
start++;
end--;
}
cout<<arr[i]<<endl;
}
system("pause");
return 0;
}
5.2.3 冒泡排序
作用:最常用的排序方法,对组内元素进行排序
1.比较相邻的元素。如果第一个比第二个大就,就交换他们两个
2.对比每一组相邻元素做同样的工作,执行完毕后,找到第一个最大值
3.重复以上步骤,每次比较次数-1,直到不需要比较
示例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V9qmSSZB-1617370509178)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210307075405529.png)]
排序轮数从0开始
排序总轮数 = 元素个数-1
每轮对比数 = 元素个数 - 排序轮数 - 1
示例:(把两层嵌套好即可得出答案)
int main(){
//利用冒泡排序实现升序降序
int arr[9]={4,2,8,0,5,7,1,3,9};
cout<<"排序前:"<<endl;
for(int i=0;i<9;i++){
cout<<arr[i]<<" ";
}
cout<<endl;
// 开始冒泡排序
// 总共排序轮数为 元素个数 - 1
for(int i=1;i<9-1;i++){
//内层循环对比 次数=元素个数-当前轮数-1 因为从0开始 所以排序轮数从0开始
for(int j=0;j<9-i-1;j++) {
//如果第一个数字,比第二个数字大,交换两个数字
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
cout<<"排序后:"<<endl;
for(int i=0;i<9;i++){
cout<<arr[i]<<" ";
}
cout<<endl;
system("pause");
return 0;
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CtJln7o6-1617370509182)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210307080937222.png)]
5.3 二维数组
在一维数组上,多加一个维度
5.3.1 二维数组定义方式
四种:
1.数据类型 数组名[ 行数 ] [ 列数 ];
2.数据类型 数组名[ 行数 ] [ 列数 ]={{数据1,数据2},{数据3,数据4}};
//每行的数据{}
3.数据类型 数组名[ 行数 ] [ 列数 ]={数据1,数据2,数据3,数据4};
4.数据类型 数组名[ ] [ 列数 ]={数据1,数据2,数据3,数据4};
第二组更加直观,提高代码可读性
5.3.2 二维数组组名
查看二维数组所占内存空间,获取二维数组首地址
示例:数组首地址=第一行首地址=第一个元素的首地址
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<<"二维数组的首地址为:" <<arr<<endl;
cout<<"二维数组第一行首地址为:" <<arr[0]<<endl;
cout<<"二维数组第二行首地址为:" <<arr[1]<<endl;
//单个元素要加&取值符号
cout<<"二维数组第一个元素首地址为:" <<&arr[0][0]<<endl;
system("pause");
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NUOqRcgS-1617370509187)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210307083901030.png)]
5.3.3 二维数组应用实例
考试成绩统计:
案例描述:有三名同学(张三、李四、王五),在一次考试中成绩分别如下表,请分别输出三名同学的成绩
语文 | 数学 | 英语 | |
---|---|---|---|
张三 | 100 | 100 | 100 |
李四 | 90 | 50 | 100 |
王五 | 60 | 70 | 80 |
代码示例:
#include<iostream>
#include<string>
using namespace std;
int main(){
int sorce[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+=sorce[i][j];
}
cout<<names[i]<<"的总成绩为:"<<sum<<endl;
}
system("pause");
return 0;
}
6 函数
6.1 概述
作用:将一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。
6.2 函数的定义
5个步骤:
1.返回值类型
2.函数名
3.参数列表
4.函数体语句
5.return 表达式
语法:
返回值类型 函数名 (参数列表)
{
函数体语句
return表达式
}
函数示例:
1.返回值类型 | int |
---|---|
2.函数名 | add |
3.参数列表 | (int num1,int num2) |
4.函数体语句 | int sum = num1+num2; |
5.return表达式 | return sum; |
综合可得:
int add(int num1,num2)
{
int sum=num1+num2;
return sum;
}
6.3 函数的调用
功能:使用定义好的函数
语法:函数名(参数)
示例:
#include<iostream>
using namespace std;
int add(int num1,int num2)
{
int sum = num1+num2;
return sum;
}
int main(){
int a=10;
int b=20;
cout<<"a+b="<<add(a,b)<<endl;
system("pause");
return 0;
}
6.4 值传递
- 函数调用时 实参 将数值传递给 形参
- 值传递时,如果形参发生改变,不会影响实参
案例示例:两个数值的交换
值传递时,如果形参发生改变,不会影响实参
#include<iostream>
using namespace std;
void swap(int num1,int num2)
{
//空的位置放在左边
int temp=num1;
num1=num2;
num2=temp;
}
int main(){
int a=10;
int b=20;
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
//值传递是指a,b(实参)将值传给形参 而实参本身并未变化
swap(a,b);
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
system("pause");
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ZKtOpQB-1617370509192)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210307214709127.png)]
改动:
#include<iostream>
using namespace std;
void swap(int num1,int num2)
{
//空的位置放在左边
int temp=num1;
num1=num2;
num2=temp;
cout<<"num1="<<num1<<endl;
cout<<"num2="<<num2<<endl;
}
int main(){
int a=10;
int b=20;
swap(a,b);
system("pause");
return 0;
}
结果运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xl8406hE-1617370509197)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210307215537326.png)]
6.5 函数常见样式
4种
1.无参无返
2.有参无返
3.无参有返
4.有参有返
示例:
//函数常见类型
//01 无参无返
void test01()
{
//void a=10;//无类型不可以创建变量,原因无法分配内存
cout<<"this is text01!"<<endl;
//text01();函数调用
}
//有参无返
void text02(int a)
{
cout<<"this is text02 a="<<a<<endl;
//text02(100);函数调用
}
int text03()
{
cout<<"this is text03"<<endl;
return 100;
//int num1=text03();
}
//04有参有返 很常见
6.6 函数的声明
作用:告诉编译器函数名称及如何调用函数,函数的实际主体可以单独定义。
- 函数声明可以多次,但是函数的定义只能有一次
(没声明之前函数只能写在main函数前面,声明后写在主函数后)
示例:
#include<iostream>
using namespace std;
//函数声明
int max(int a,int b);
int main(){
int a=10;
int b=10;
cout<<max(a,b)<<endl;
system("pause");
return 0;
}
//函数的定义
int max(int a,int b)
{
return a>b?a:b;
}
6.7 函数的分文件编写
作用:让代码结构更加清晰
函数分文件编写一般有四个步骤
1.创建后缀名为 .h 的头文件
2.创建后缀名为 .cpp 的源文件
3.在头文件中写函数声明
4.在原文件中写函数定义
示例:
一共三个文件 swap.h swap.cpp 多文件编程.cpp
//devC++头文件的创建:
//1.创建新项目 Console Application
//2.右键新建的项目,点击新建文件
//3.编写新文件代码
//4.右键 选择关闭选项 选择保存 在保存的文件属性中选择Header文件
//5.点击确定 头文件就能被调用了
//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;
}
//多文件编程.cpp
#include <iostream>
//头文件调用
#include "swap.h"
using namespace std;
int main(int argc, char** argv) {
int a=10;
int b=20;
swap(a,b);
system("pause");
return 0;
}
7 指针
7.1 指针的基本概念
指针的作用:可以通过指针间接访问内存
- 内存编号是从0开始记录的,一般用十六进制数字表示
- 可以利用指针变量保存地址
7.2 指针变量的定义和使用
指针变量定义语法:数据类型 * 变量名
示例:
#include<iostream>
using namespace std;
int main(){
//1、定义指针
int a=10;
//指针定义的语法:数据类型 * 指针变量名 ;
int *p;
//让指针记录变量a的地址
p = &a;
cout<<"a的地址为:"<<&a<<endl;
cout<<"指针p为:" <<p<<endl;
//2、使用指针
//就可以通过解引用的方式来找到指针指向的内存
//指针前加 * 代表解引用 ,找到指针指向的内存中的数据
//可以通过*p来修改a的值
*p=100;
cout<<"a="<<a<<endl;
cout<<"*p="<<*p<<endl;
system("pause");
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4rLvQzff-1617370509203)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210308154713212.png)]
7.3 指针所占内存空间
指针也是种数据类型,那么这种数据类型占用多少字符呢?
在32位(x86)操作系统下:占用4个字节空间;64位(x64)下占8个字节空间
#include<iostream>
using namespace std;
int main(){
int a=10;
int *p=&a;
//不管是什么数据类型的指针,指针的大小只和操作系统有关 32位4字节 64位8字节
cout<<"sizeof (int *)="<<sizeof(p)<<endl;//p就是int *
cout<<"sizeof (float *)="<<sizeof(float *)<<endl;
cout<<"sizeof (double *)="<<sizeof(double *)<<endl;
cout<<"sizeof (char *)="<<sizeof(char *)<<endl;
system("pause");
return 0;
}
运行结果:
1.32位
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ICSDZk0-1617370509207)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210309095716346.png)]
2.64位
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fI9xCCmR-1617370509211)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210309095636194.png)]
7.4 空指针和野指针
空指针:指针变量指向内存空间为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
示例1:空指针
#include<iostream>
using namespace std;
int main(){
//空指针
//1、空指针用于给指针变量初始化 int * p;不知道*p指向哪里
int * p=NULL;
// 空指针是不可以进行访问的
//0-255之间的内存编号是系统占用的,因此不可以访问
//出现*p程序就出错
*p=100;
cout<<*p<<endl;
system("pause");
return 0;
}
野指针:指针变量指向非法的内存空间
示例2:野指针
#include<iostream>
using namespace std;
int main(){
//指针变量p指向内存地址编号为0x1100的空间
//没有先申请一块内村
int * p=(int *)0x1100;
//访问野指针报错
cout<<*p<<endl;
system("pause");
return 0;
}
注意:空指针和野指针都不是我们申请的空间,因此不要访问。
7.5 const修饰指针
const修饰指针有三种情况:
1.const修饰指针----常量指针
2.const修饰常量----指针常量
3.const既修饰又修饰常量
const–常量 *–指针
所以const int * p;//常量指针 可以修改指针的取向 不可以修改指针指向的值
int * const p;//指针常量 可以修改指针的值 不可以修改指针的取向
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oZ5HUCQA-1617370509215)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210309104928134.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x0YFhcBl-1617370509236)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210309104859013.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YIKGeQ1C-1617370509240)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210309104829803.png)]
示例:
#include<iostream>
using namespace std;
int main(){
//1、const修饰指针 常量指针
int a=10;
int b=20;
const int *p=&a;
//*p=20错误
p=&b; //正确
cout<<*p<<endl;//此时*p的值也变成了b取向的值
//2、const修饰常量 常量指针
int * const p2=&a;
*p2=20;//正确
// p2=&b;//错误
//3、const修饰指针和常量
const int * const p3=&a;//都不能修改
}
7.6 指针和数组
作用:利用指针访问数组中的元素
示例:
#include<iostream>
using namespace std;
int main(){
//指针和数组
//利用指针访问数组中的元素
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int *p=arr;//arr就是数组首地址
cout<<"数组的第一个元素为:"<<arr[0]<<endl;
cout<<"利用指针访问第一个元素为:"<<*p<<endl;
p++;//指针向后偏移4个字节 整型指针解引用一下四个字节
cout<<"利用指针访问第二个元素为:"<<*p<<endl;
cout<<"利用指针遍历数组"<<endl;
int *p2=arr;
for(int i=0;i<10;i++){
cout<<*p2<<endl;
p2++;
}
system("pause");
return 0;
}
结果运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zk11FzgJ-1617370509245)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210311141609501.png)]
7.7 指针和数组
作用:利用指针做函数参数,可以修改实参的值
示例:
#include<iostream>
using namespace std;
void swap01 (int a,int b)
{
int temp=a;
a=b;
b=temp;
cout<<"swap01 a="<<a<<endl;
cout<<"swap01 b="<<b<<endl;
}
void swap02(int *p1,int *p2){
int temp=*p1;
*p1=*p2;
*p2=temp;
}
int main(){
//1、值传递
int a=10;
int b=20;
swap01(a,b);
cout<<"值传递a="<<a<<endl;
cout<<"值传递b="<<b<<endl;
//2、地址传递
//如果是地址传递可以修饰实参
swap02(&a,&b);
cout<<"地址传递a="<<a<<endl;
cout<<"地址传递b="<<b<<endl;
system("pause");
return 0;
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hNMWw3AB-1617370509248)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210311144252764.png)]
7.8 指针、数组、函数
案例描述:封装一个函数,利用冒泡排序,实现函数的升序排序
例如数组:int arr[10]={4,3,6,9,1,2,10,8,7,5};
示例:
#include<iostream>
using namespace std;
//创建函数 参数1 数组的首地址 参数2 数组的长度
void BubbleSort(int *arr,int len)
{
//外层总排序的次数
for(int i=0;i<len-1;i++)
{//内层 每次排序需要交换的次数
for(int j=0;j<len-i-1;j++)
{
//如果j>j+1交换数值
if(arr[j]>arr[j+1])
{
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
void printfArray(int *arr,int len)
{
for(int i=0;i<len;i++)
{
cout<<arr[i]<<endl;
}
}
int main(){
//1、创建数组
int arr[10]={4,3,6,9,1,2,10,8,7,5};
//数组长度
int len=sizeof(arr)/sizeof(arr[0]);
//2、创建函数,实现冒泡排序
BubbleSort(arr,len);
//3、打印排序后的数组
printfArray(arr,len);
system("pause");
return 0;
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgPwj3GC-1617370509253)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210311150017982.png)]
8 结构体
8.1 结构体的基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。
8.2 结构体的定义和使用
语法:struct 结构体名 { 结构体成员列表 };
通过结构体创建变量的方式有三种:
- struct 结构体名 变量名
- struct 结构体名 变量名 = { 成员值1,成员值2…}
- 定义结构体时顺便创建变量
示例:
#include<iostream>
#include<string>
using namespace std;
//1、创建学生的数据类型:学生包括(姓名,年龄,分数)
//自定义数据类型,一些类型集合组成的一个类型
//语法 struct 类型名称 {成员列表 }
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
} s3;//顺便定义 少用
//2、通过学生类型创建具体学生(结构体创建中的struct可以省略 定义时不行)
int main(){
//2.1 struct Student s1
struct Student s1;
//给s1属性赋值,通过访问.(点)结构体变量中的属性
s1.name= "张三";
s1.age=18;
s1.score=100;
cout<<"姓名:"<<s1.name<<" 年龄:"<<s1.age<<" 分数:"<<s1.score<<endl;
//2.2 struct Student s2={...}
struct Student s2={"李四",19,90};
cout<<"姓名:"<<s2.name<<" 年龄:"<<s2.age<<" 分数:"<<s2.score<<endl;
//2.3 在定义结构体时顺便创建结构体变量
s3.name= "王五";
s3.age=20;
s3.score=75;
cout<<"姓名:"<<s3.name<<" 年龄:"<<s3.age<<" 分数:"<<s3.score<<endl;
system("pause");
return 0;
}
结果运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NYKtMo6x-1617370509274)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210311194035779.png)]
8.3 结构体数组
作用:将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名 [元素个数]={{},{},{}....};
示例:
#include<iostream>
#include<string>
using namespace std;
//1、定义结构体
struct Student
{
string name;
int age;
int height;
};
int main(){
//2、创建结构体数组
//3、给结构体数组元素赋值
struct Student StuArray[3]=
{
{"张三",17,180},
{"李四",20,178},
{"王五",34,178}
};
//3.1修改结构体数组
StuArray[2].name="赵六";
StuArray[2].age=24;
//4、遍历结构体数组
for(int i=0;i<3;i++){
cout<<"姓名:"<<StuArray[i].name<<" 年龄:"<<StuArray[i].age<<" 身高:"<<StuArray[i].height<<endl;
}
system("pause");
return 0;
}
结果运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y3EDBkww-1617370509276)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210311201839758.png)]
8.4 结构体指针
利用操作符 ->
可以通过结构体指针访问结构体属性。
示例:
#include<iostream>
#include<string>
using namespace std;
//结构体指针
//定义结构体
struct Student
{
string name;
int age;
int score;
};
int main(){
//1、创建学生结构体变量
Student s={"张三",56,90};
//2、通过指针指向结构体变量
Student *p=&s;
//3、通过指针访问结构体变量中的数据
//指针通过‘->’可以访问结构体成员
cout<<"姓名:"<<p->name<<"年龄:"<<p->age<<"分数:"<<p->score<<endl;
system("pause");
return 0;
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j1NwZvzy-1617370509280)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210313193501483.png)]
8.5 结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体
例如:每个老师辅导两个学员,一个老师的结构体中,记录着两个学生的结构体
示例:
#include<iostream>
#include<string>
using namespace std;
//定义学生结构体
struct student
{
string name;//名字
int age;//年龄
int score;//分数
} ;
struct teacher
{
int id;//编号
string name;//姓名
int age;//年龄
struct student stu;//教师结构体中的嵌套学生结构体 学生要先在前面定义
};
int main(){
//创建教师结构体 直接在教师中创建学生的信息 方便
teacher t;
t.id=0001;
t.name="老王" ;
t.age=60;
t.stu.age=20;
t.stu.name="小黄";
t.stu.score=100;
cout<<"导师编号:"<<t.id<<" 导师姓名:"<<t.name<<" 导师年龄:"<<t.age<<endl;
cout<<"学生姓名:" <<t.stu.name<<" 年龄:"<<t.stu.age<<" 分数:"<<t.stu.score<<endl;
// student stu;
// stu.name="小黄";
// stu.age=20;
// stu.score=100;
system("pause");
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2sCJlK5-1617370509284)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210313200227923.png)]
printf("导师编号:%04d",t.id);
cout<<" 导师姓名:"<<t.name<<" 导师年龄:"<<t.age<<endl;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CCNDDssb-1617370509287)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210313202923653.png)]
8.6 结构体做函数
作用:将结构体作为参数向函数中传递
传递的方式有两种:
- 值传递(不能修改主函数中的值)
- 地址传递(可以修改主函数中的值)
示例1(值传递):
#include<iostream>
#include<string>
using namespace std;
//1、定义结构体
struct student
{
string name;
int age;
int score;
} ;
//值传递 打印学生信息
void printfStudent1(struct student s)
{
s.score=65;
cout<<"子函数中 姓名:"<<s.name<<" 年龄:" <<s.age<<" 分数:"<<s.score<<endl;
}
int main(){
//2、创建结构体变量
student s;
s.name="阿黄";
s.age=20;
s.score=59;
//3、打印结构体信息
cout<<"main函数中 姓名:" <<s.name<<" 年龄:"<<s.age<<" 分数:"<<s.score<<endl;
//函数1 值传递
printfStudent1(s);
system("pause");
return 0;
}
结果运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y3vwvfq4-1617370509290)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210313205853302.png)]
示例2(地址传递):
//地址传递 打印学生信息
void printfStudent2(struct student *p)//指针*p接收
{
p->score=78;
cout<<"子函数中2 姓名:"<<p->name<<" 年龄:" <<p->age<<" 分数:"<<p->score<<endl;
}
int main(){
//2、创建结构体变量
student s;
s.name="阿黄";
s.age=20;
s.score=59;
printfStudent2(&s);//取地址
//3、打印结构体信息
cout<<"main函数中 姓名:" <<s.name<<" 年龄:"<<s.age<<" 分数:"<<s.score<<endl;
system("pause");
return 0;
}
结果运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v8c1yBXI-1617370509296)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210313210523572.png)]
注意:函数要在主函数输入之前才能赋值
8.7 结构体中的const使用场景
作用:用const来防止误操作
示例:
#include<iostream>
#include<string>
using namespace std;
//定义结构体
struct Student
{
string name;
int age;
int score;
};
//struct可以不写
void printfStudent(const struct Student *p)//指针*p接收
{
//p->score=78;//加了const后指针不能修改数值 用地址传递的原因:节省内存空间(一个指针4个字节)
cout<<"子函数中 姓名:"<<p->name<<" 年龄:" <<p->age<<" 分数:"<<p->score<<endl;
}
int main(){
//1、创建学生结构体变量
Student s={"张三",56,90};
printfStudent(&s);
cout<<"主函数中 姓名:"<<s.name<<"年龄:"<<s.age<<"分数:"<<s.score<<endl;
system("pause");
return 0;
}
8.8 结构体案例
案例1
案例描述:学校正在做毕设项目,每名老师带领5名学生,总共有3名老师,需求如下:
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和存放一个五名学生的数组作为成员
学生的成员要有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
最终打印出老师的数据以及老师所带学生的数据。
示例:
#include<iostream>
#include<string>
#include<ctime>
#include<cstdlib>//srand头文件
using namespace std;
//1、定义学生结构体
//1.1学生结构体有 姓名 考试分数
struct Student
{
string sName;
int score;
} ;
//2、定义教师结构体
//2.1老师姓名和存放一个五名学生的数组
struct Teacher
{
string tName;
struct Student sArray[5];
};
//给老师和学生赋值的函数
void allocateSpace(struct Teacher tArray[],int len)//给老师开辟空间
{
string nameSeed1="ABCDE";
string nameSeed2="abcde";
//给老师开始赋值
for(int i=0;i<len;i++)
{
tArray[i].tName="Teacher_";
tArray[i].tName+=nameSeed1[i];//自动赋值老师姓名
//通过循环给每名老师所带的学生赋值
for(int j=0;j<5;j++)
{
tArray[i].sArray[j].sName="Student_";
tArray[i].sArray[j].sName+=nameSeed2[j];
//通过随机数给每名学生成绩赋值
int random=rand()%61+40;//40-100
tArray[i].sArray[j].score=random;
}
}
}
//打印老师学生的信息
void printfInfo(struct Teacher tArray[],int len)
{
for(int i=0;i<len;i++)
{
cout<<"老师姓名:"<<tArray[i].tName<<endl;
for(int j=0;j<5;j++)
{
cout<<"\t学生姓名:"<<tArray[i].sArray[j].sName<<
" 考试分数:"<<tArray[i].sArray[j].score<<endl;
}
}
}
int main(){
//随机数种子
srand((unsigned int)time(NULL)) ;
//3、创建结构体变量数组
//3.1创建数组存放3名老师
struct Teacher tArray[3];
//3.2通过函数给每个老师及所带的学生赋值
int len=sizeof(tArray)/sizeof(tArray[0]);
allocateSpace(tArray,len);
//3.3打印出老师的数据以及老师所带学生的数据
printfInfo(tArray,len);
system("pause");
return 0;
}
结果运行:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YynQaNwc-1617370509302)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210314213725825.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NfMS59Tn-1617370509308)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210314215455078.png)]
案例2
案例描述:设计一个英雄的结构体,包括姓名、年龄、性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印出排序后的结果。
5名英雄信息如下:
{"刘备",23,"男"},` `{"关羽",22,"男"},` `{"张飞",20,"男"},` `{"赵云",21,"男"},` `{"貂蝉",19,"女"}
示例:
#include<iostream>
#include<string>
using namespace std;
//1、一个英雄的结构体,包括姓名、年龄、性别
struct Hero
{
string name;
int age;
string sex;
} ;
void bubbleSort(struct Hero hArray[],int len)
{
for(int i=0;i<len-1;i++)
{
for(int j=0;j<len-i-1;j++)
{
//如果j下标的年龄大于j+1下标的元素年龄,交换两个元素
if(hArray[j].age>hArray[j+1].age) {
struct Hero temp=hArray[j];
hArray[j]=hArray[j+1];
hArray[j+1]=temp;
}
}
}
}
//打印排序后的结构体
void printfHero(struct Hero hArray[],int len)
{
for(int i=0;i<len;i++)
{
cout<<"姓名:"<<hArray[i].name<<" 年龄:"<<hArray[i].age<<" 性别:"<<hArray[i].sex<<endl;
}
}
int main(){
//2、创建结构体数组,数组中存放5名英雄。
struct Hero hArray[5]={
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"}
};
//3、冒泡排序,将数组中的英雄按照年龄进行升序排序
int len=sizeof(hArray)/sizeof(hArray[0]);
bubbleSort(hArray,len);
//4、打印出排序后的结果。
printfHero(hArray,len);
system("pause");
return 0;
}
结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Trui2Oa5-1617370509312)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210314222016817.png)]
通讯录管理系统
1 系统需求
通讯录是一个可以记录亲人、好友信息的工具。
C++实现通讯录管理系统,
系统需要实现功能如下:
- 添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人
- 显示联系人:显示通讯录中所有联系人的信息
- 删除联系人:按照姓名进行删除指定联系人
- 查找联系人:按照姓名查看指定联系人信息
- 修改联系人:按照姓名重新修改指定联系人
- 清空联系人:清空通讯录所有联系人
- 退出通讯录:退出当前使用的通讯录
2 创建项目
点击文件 - > 新建项目 - > 选择Console Application - > C++项目 - > 添加项目名 - >选择项目存储地址 - > 新建源文件.cpp
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBwsa4OO-1617370509317)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210317214102340.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JQIBS3IG-1617370509320)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210317214725967.png)]
3 菜单功能
功能描述:用户选择功能的界面
菜单界面效果如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HUJdrtJr-1617370509337)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210317220510602.png)]
步骤:
- 封装函数显示该界面 如
void showMenu()
- 在main函数中调用封装好的函数
代码:
// 封装函数显示该界面 如void showMenu()
// 在main函数中调用封装好的函数
#include <iostream>
using namespace std;
//菜单界面
void showMenu()
{
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;
}
int main(int argc, char** argv) {
//菜单的调用
showMenu();
system("pause");
return 0;
}
4 退出功能
功能描述:退出通讯录功能
思路:根据用户不同的选择,进入不同的功能,可以选择switch分支结构,将整个框架进行搭建
当用户选择0时,执行退出,选择其他先不做操作,也不会退出程序(其他还没学,狗头)
界面效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yS5nYiRV-1617370509342)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210317222250125.png)]
代码:
int main(int argc, char** argv) {
int select=0;//创建用户选择输入的变量
//菜单的调用
showMenu();
cin>>select;
//死循环 实现重复输入 直到输入0才退出程序
while(true)
{
switch(select)
{
case 1://1、添加联系人
break;
case 2://2、显示联系人
break;
case 3://3、删除联系人
break;
case 4://4、查找联系人
break;
case 5://5、修改联系人
break;
case 6://6、清空联系人
break;
case 0://0、退出联系人
cout<<"欢迎下次使用"<<endl;
system("pause");
return 0;//选择0则退出系统
break;
default:
break;
}
}
system("pause");
return 0;
}
5 添加联系人
功能描述:
实现添加联系人的功能,联系人上限为1000人,联系人的信息包括(姓名、性别、年龄、联系电话、家庭住址)
添加联系人的步骤:
- 设计联系人结构体
- 设计通讯录结构体
- main函数中创建通讯录
- 封装添加联系人的函数
- 测试添加联系人的功能
5.1设计联系人结构体
联系人信息包括:姓名、性别、年龄、联系电话、家庭住址
设计如下:
#include<string>//string头文件
//联系人结构体
struct Person
{
string m_Name;//姓名
int m_Sex;//性别 1男 2女
int m_Age;//年龄
string m_Phone;//电话
string m_Addr;//地址
};
5.2 设计通讯录结构体
设计时可以在通讯录结构体中,维护一个容量为1000的存放联系人的数组,并记录当前联系人数量
设计如下:
#define MAX 1000//最大人数
//通讯录结构体
struct Addressbooks
{
struct Person PersonArray[MAX];//通讯录中保存的联系人数组
int m_Size;//通讯录中人员个数
}
5.3 main函数中创建通讯录
添加联系人函数封装好后,在main函数中创建一个通讯录变量,这就是我们一直维护的通讯录
main函数起始的位置添加:
//创建结构体变量
Addressbooks abs;
//初始化通讯录中当前的人数
abs.m_Size=0;
5.4 封装添加联系人函数
思路:添加联系人前先判断通讯录是否已满,如果满了就不能在添加,未满情况将新联系人信息逐个加入到通讯录中
添加联系人代码:
//1、添加联系人
void addPerson(Addressbooks * abs)
{
//判断通讯录是否已满,如果满了不再添加
if(abs->m_Size==MAX)
{
cout<<"通讯录已满,无法添加"<<endl;
return ;
}
//添加联系人
else
{
//姓名
string name;
cout<<"请输入姓名:"<<endl;
cin>>name;
abs->PersonArrary[abs->m_Size].m_Name=name;
//性别
int sex=0;
cout<<"请输入性别:"<<endl;
cout<<"1---男 2---女"<<endl;
//输入性别有误时,无限循环输入 直至输入正确
while(true)
{
cin>>sex;
if(sex==1||sex==2)
{
abs->PersonArrary[abs->m_Size].m_Sex=sex;
break;
}
cout<<"输入有误,请重新输入"<<endl;
}
//年龄
int age=0;
cout<<"请输入年龄:"<<endl;
while(true)
{
cin>>age;
if(age<150)
{
abs->PersonArrary[abs->m_Size].m_Age=age;
break;
}
cout<<"输入有误,请重新输入"<<endl;
}
//电话
cout<<"请输入电话:"<<endl;
string phone;
cin>>phone;
abs->PersonArrary[abs->m_Size].m_Phone=phone;
//住址
cout<<"请输入住址:"<<endl;
string address;
cin>>address;
abs->PersonArrary[abs->m_Size].m_Addr=address;
//更新通讯录中的人数
abs->m_Size++;
cout<<"添加成功"<<endl;
system("pause");//请按任意键继续
system("cls") ;//清屏操作
}
}
5.5 测试添加联系人功能
选择界面中,如果玩家选择了1,代表添加联系人,
在switch case语句中,case1里添加:
case 1://1、添加联系人
addPerson(&abs);//用地址传递修饰实参
break;
测试结果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iEtmpeX7-1617370509347)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210318223652258.png)]
6 显示联系人
功能描述:显示通讯录中已有的联系人信息
显示联系人实现的步骤:
- 封装显示联系人函数
- 测试显示联系人功能
6.1 封装显示联系人函数
思路:判断如果当前通讯录中没有人员,就提示记录为空,人数大于0,显示通讯录中信息
显示联系人代码:
//2、显示所有联系人
void showPerson(Addressbooks * abs)
{
//判断通讯录中的人数是否为0,如果为0,提示记录为空
if(abs->m_Size==0)
{
cout<<"当前记录为空"<<endl;
}
//如果不为0,显示记录的联系人信息
else
{
//遍历所有的数据
for(int i=0;i<abs->m_Size;i++)
{
cout<<"姓名:"<<abs->PersonArray[i].m_Name<<"\t";//空八个字符
cout<<"性别:"<<(abs->PersonArray[i].m_Sex==1?"男":"女")<<"\t";
cout<<"年龄:"<<abs->PersonArray[i].m_Age<<"\t";
cout<<"电话:"<<abs->PersonArray[i].m_Phone<<"\t";
cout<<"住址:"<<abs->PersonArray[i].m_Addr<<endl;
}
}
system("pause");//请按任意键继续
system("cls") ;//清屏操作
}
6.2 测试显示联系人功能
选择界面中,如果玩家选择了2,代表显示联系人,
在switch case语句中,case 2里添加:
case 2://2、显示联系人
showPerson(&abs);
break;
结果示例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ByuABACq-1617370509353)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319105430905.png)]
7 删除联系人
功能描述:按照姓名进行删除指定联系人
删除联系人实现步骤:
- 封装检测联系人是否存在
- 封装删除联系人的函数
- 测试删除联系人功能
7.1 封装检测联系人是否存在
思路:删除联系人前,先判断用户输入的联系人是否存在,如果存在删除,不存在提示用户没有要删除的联系人,因此可以把检测联系人是否存在封装在一个函数中,如果存在,返回联系人在通讯录中的位置,不存在返回-1.
检测联系人代码:
//检测联系人是否存在,如果存在返回联系人所在数组中的具体位置
//参数1 通讯录 参数2 对比姓名
int isExist(Addressbooks*abs,string name)
{
for(int i=0;i<abs->m_Size;i++)
{
//找到用户输入的姓名了
if(abs->PersonArray[i].m_Name==name)
{
return i;//找到了,返回这个人在数组中的下标
}
}
return -1;//找不到,返回-1
}
预先测试代码:
case 3://3、删除联系人
// {
// cout<<"请输入删除联系人姓名:"<<endl;
// string name;
// cin>>name;
// if(isExist(&abs,name)==-1)
// {
// cout<<"查无此人"<<endl;
// }
// else
// {
// cout<<"找到此人"<<endl;
// }
// }
break;
7.2 封装删除联系人函数
根据用户输入的联系人判断该通讯录中是否有此人
查找进行删除,并提示删除成功
查不到提示查无此人
//3、删除联系人
void deletePerson(Addressbooks*abs)
{
cout<<"请输入您要删除的联系人"<<endl;
string name;
cin>>name;
//ret==-1未找到
//ret!=-1查到了
int ret=isExist(abs,name);
if(ret!=-1)
{
//查找到人,要进行删除操作
for(int i=ret;i<abs->m_Size;i++)
{
//数据前移
abs->PersonArray[i]= abs->PersonArray[i+1];
}
abs->m_Size--;//更新通讯录中的人数
cout<<"删除成功"<<endl;
}
else
{
cout<<"查无此人"<<endl;
}
system("pause");
system("cls");
}
7.3 测试删除联系人
switch中case 3:添加代码:
case 3://3、删除联系人
deletePerson(&abs);
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HzpT4JoD-1617370509356)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319123541309.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7JbtHqjG-1617370509361)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319123726930.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IY2CnzWU-1617370509366)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319123806898.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ND05flzv-1617370509370)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319123838416.png)]
8 查找联系人
功能描述:按照姓名查看指定联系人的信息
步骤:
- 封装查找函数
- 测试
封装查找函数
//4、查找联系人
void findPerson(Addressbooks*abs)
{
cout<<"请输入要查找的联系人的姓名:"<<endl;
string name;
cin>>name;
//ret==-1未找到
//ret!=-1查到了
int ret=isExist(abs,name);
if(ret!=-1){
cout<<"姓名:"<<abs->PersonArray[ret].m_Name<<"\t";//空八个字符
cout<<"性别:"<<(abs->PersonArray[ret].m_Sex==1?"男":"女")<<"\t";
cout<<"年龄:"<<abs->PersonArray[ret].m_Age<<"\t";
cout<<"电话:"<<abs->PersonArray[ret].m_Phone<<"\t";
cout<<"住址:"<<abs->PersonArray[ret].m_Addr<<endl;
}
else
{
cout<<"查无此人"<<endl;
}
system("pause");
system("cls");
}
测试:
case 4://4、查找联系人
findPerson(&abs);
break;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KNvhreKS-1617370509390)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319125336650.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bXYZrdW2-1617370509394)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319125407982.png)]
9 修改联系人
功能描述:按照姓名修改指定联系人
步骤:
- 封装修改函数
- 测试
封装修改函数
//5、修改联系人
void modifyPerson(Addressbooks*abs)
{
cout<<"请输入要修改的联系人的姓名:"<<endl;
string name;
cin>>name;
//ret==-1未找到
//ret!=-1查到了
int ret=isExist(abs,name);
//借用添加联系人的代码
if(ret!=-1){
//姓名
string name;
cout<<"请输入姓名:"<<endl;
cin>>name;
abs->PersonArray[ret].m_Name=name;
int sex=0;
cout<<"请输入性别:"<<endl;
cout<<"1---男 2---女"<<endl;
//输入性别有误时,无限循环输入 直至输入正确
while(true)
{
cin>>sex;
if(sex==1||sex==2)
{
abs->PersonArray[ret].m_Sex=sex;
break;
}
cout<<"输入有误,请重新输入"<<endl;
}
//年龄
int age=0;
cout<<"请输入年龄:"<<endl;
while(true)
{
cin>>age;
if(age<150)
{
abs->PersonArray[ret].m_Age=age;
break;
}
cout<<"输入有误,请重新输入"<<endl;
}
//电话
cout<<"请输入电话:"<<endl;
string phone;
cin>>phone;
abs->PersonArray[ret].m_Phone=phone;
//住址
cout<<"请输入住址:"<<endl;
string address;
cin>>address;
abs->PersonArray[ret].m_Addr=address;
cout<<"修改成功!"<<endl;
}
else
{
cout<<"查无此人"<<endl;
}
system("pause");
system("cls");
}
测试:
case 5://5、修改联系人
modifyPerson(&abs);
break;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zwcwrTCX-1617370509410)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319131219974.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ldWToRmp-1617370509415)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319131250856.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XMWFOnwq-1617370509419)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319131344460.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9nwRf2uY-1617370509433)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319131409280.png)]
10 清空联系人
功能描述:清空通讯录中所有的信息
清空联系人步骤:
- 封装清空联系人的函数
- 测试清空联系人
10.1 封装清空联系人的函数
实现思路:将通讯录中所有联系人信息清除掉,只要将通讯录记录的联系人数量记为0,做逻辑清空即可。
实现代码:
//6、清空联系人
void cleanPerson(Addressbooks * abs)
{
//提示是否要清空
cout<<"是否真的要清空所有联系人?"<<endl;
int dele=0;
cout<<"1---清空 2---再考虑一下"<<endl;
cin>>dele;
if(dele==1)
{
abs->m_Size=0;//将通讯录记录的联系人数量记为0,做逻辑清空即可。
cout<<"通讯录已清空"<<endl;
}
system("pause");
system("cls");
}
10.2 测试清空联系人
在switch case语句中,case 6里添加:
case 6://6、清空联系人
cleanPerson(&abs);
break;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O0B7FcDB-1617370509437)(C:\Users\徐老帅哥\AppData\Roaming\Typora\typora-user-images\image-20210319112107219.png)]
通讯录管理系统完成!
步骤:
- 封装查找函数
- 测试
封装查找函数
//4、查找联系人
void findPerson(Addressbooks*abs)
{
cout<<"请输入要查找的联系人的姓名:"<<endl;
string name;
cin>>name;
//ret==-1未找到
//ret!=-1查到了
int ret=isExist(abs,name);
if(ret!=-1){
cout<<"姓名:"<<abs->PersonArray[ret].m_Name<<"\t";//空八个字符
cout<<"性别:"<<(abs->PersonArray[ret].m_Sex==1?"男":"女")<<"\t";
cout<<"年龄:"<<abs->PersonArray[ret].m_Age<<"\t";
cout<<"电话:"<<abs->PersonArray[ret].m_Phone<<"\t";
cout<<"住址:"<<abs->PersonArray[ret].m_Addr<<endl;
}
else
{
cout<<"查无此人"<<endl;
}
system("pause");
system("cls");
}
测试:
case 4://4、查找联系人
findPerson(&abs);
break;
[外链图片转存中…(img-KNvhreKS-1617370509390)]
[外链图片转存中…(img-bXYZrdW2-1617370509394)]
9 修改联系人
功能描述:按照姓名修改指定联系人
步骤:
- 封装修改函数
- 测试
封装修改函数
//5、修改联系人
void modifyPerson(Addressbooks*abs)
{
cout<<"请输入要修改的联系人的姓名:"<<endl;
string name;
cin>>name;
//ret==-1未找到
//ret!=-1查到了
int ret=isExist(abs,name);
//借用添加联系人的代码
if(ret!=-1){
//姓名
string name;
cout<<"请输入姓名:"<<endl;
cin>>name;
abs->PersonArray[ret].m_Name=name;
int sex=0;
cout<<"请输入性别:"<<endl;
cout<<"1---男 2---女"<<endl;
//输入性别有误时,无限循环输入 直至输入正确
while(true)
{
cin>>sex;
if(sex==1||sex==2)
{
abs->PersonArray[ret].m_Sex=sex;
break;
}
cout<<"输入有误,请重新输入"<<endl;
}
//年龄
int age=0;
cout<<"请输入年龄:"<<endl;
while(true)
{
cin>>age;
if(age<150)
{
abs->PersonArray[ret].m_Age=age;
break;
}
cout<<"输入有误,请重新输入"<<endl;
}
//电话
cout<<"请输入电话:"<<endl;
string phone;
cin>>phone;
abs->PersonArray[ret].m_Phone=phone;
//住址
cout<<"请输入住址:"<<endl;
string address;
cin>>address;
abs->PersonArray[ret].m_Addr=address;
cout<<"修改成功!"<<endl;
}
else
{
cout<<"查无此人"<<endl;
}
system("pause");
system("cls");
}
测试:
case 5://5、修改联系人
modifyPerson(&abs);
break;
[外链图片转存中…(img-zwcwrTCX-1617370509410)]
[外链图片转存中…(img-ldWToRmp-1617370509415)]
[外链图片转存中…(img-XMWFOnwq-1617370509419)]
[外链图片转存中…(img-9nwRf2uY-1617370509433)]
10 清空联系人
功能描述:清空通讯录中所有的信息
清空联系人步骤:
- 封装清空联系人的函数
- 测试清空联系人
10.1 封装清空联系人的函数
实现思路:将通讯录中所有联系人信息清除掉,只要将通讯录记录的联系人数量记为0,做逻辑清空即可。
实现代码:
//6、清空联系人
void cleanPerson(Addressbooks * abs)
{
//提示是否要清空
cout<<"是否真的要清空所有联系人?"<<endl;
int dele=0;
cout<<"1---清空 2---再考虑一下"<<endl;
cin>>dele;
if(dele==1)
{
abs->m_Size=0;//将通讯录记录的联系人数量记为0,做逻辑清空即可。
cout<<"通讯录已清空"<<endl;
}
system("pause");
system("cls");
}
10.2 测试清空联系人
在switch case语句中,case 6里添加:
case 6://6、清空联系人
cleanPerson(&abs);
break;
[外链图片转存中…(img-O0B7FcDB-1617370509437)]
通讯录管理系统完成!