文章目录
1.第一个helloworld
#include <iostream>
using namespace std;
int main()
{
cout<<"hello world"<<endl;
return 0;
}
2.注释
作用: 在代码中加一些说明和解释,方便自己或其他程序员阅读代码(编译时会被忽略)
两种格式:
(1)单行注释:
// 描述信息
通常放在一行代码的上方或者末尾,对该行代码说明
(2)多行注释
/* 描述信息
描述信息
*/
通常放在一段代码的上方,对该段代码做整体说明
3.变量
作用: 给一段指定的内存空间取名,方便操作这段内存
语法:数据类型 变量名 = 初始值
示例:
#include<iostream>
using namespace std;
int main(){
int a = 10;
cout<<"a = "<<a<<endl;
system("pause");
return 0;
}
4.常量
作用: 用于记录程序中不可更改的数据,例如一周定义为7天,一天24小时
C++定义常量的两种方式:
(1)#define
宏常量
语法:#define 常量名 常量值
通常在文件上方定义,表示一个常量
(2)const
修饰的变量
语法:const 数据类型 常量名 = 常量值;
通常在变量定义前加关键字const,修饰该变量为常量,不可修改
示例:
#include <iostream>
using namespace std;
//1.宏常量
#define Day 7
int main()
{
//1、宏常量
//Day = 14; //错误,Day是常量,一旦修改就会报错
cout<<"一周总共有"<<Day<<"天"<<endl;
//2、const修饰的变量
const int hour = 24;
cout<<"一天总共有"<<hour<<"小时"<<endl;
return 0;
}
5.关键字
作用: 关键字是C++中预先保留的单词(标识符)
注: 在定义变量或者常量的时候,不要用关键字,否则会产生歧义
C++关键字如下:
6.变量(常量)命名规则
(1)不能是关键字
(2)只能由数字、字母、下划线组成
(3)第一个字符必须为字母或下划线
(4)命名中字母区分大小写
建议:命名时,尽量做到见名识义,增加可读性
7.数据类型
C++规定在创建一个变量或常量时,必须要指出相应的数据类型,否则无法给变量分配内存。
数据类型存在的意义即,给变量分配合适的内存空间
数据类型包括:整型、浮点型、字符型、字符串型、布尔型
7.1整型
作用: 整型变量表示的是整数类型的数据
C++中能够表示整型的类型有以下几种方式,区别在于所占内存空间不同:
short取值范围为-32768–32767,如果执行short a = 32768,输出的值为-32768
7.1.1sizeof关键字
作用: 使用sizeof关键字可以统计数据类型所占的内存大小
语法:sizeof(数据类型 / 变量)
示例:
#include<iostream>
using namespace std;
int main(){
short num1 = 10;
cout << "short占用内存空间为:" << sizeof(short) <<endl; //2
// 或cout << "short占用内存空间为:" << sizeof(num1) <<endl;
int num2 = 10;
cout << "int占用内存空间为:" << sizeof(int) <<endl; //4
long num3 = 10;
cout << "long占用内存空间为:" << sizeof(long) <<endl; //8
long long num4 = 10;
cout << "long long占用内存空间为:" << sizeof(long long) <<endl; //8
return 0;
}
整型大小比较:short<int<=long<=long long
7.2实型(浮点型)
作用: 用于表示小数
浮点型变量分为两种:
(1)单精度float
(2)双精度double
两者区别在于表示的有效数字范围不同。
示例:
#include<iostream>
using namespace std;
int main(){
//float f1 = 3.1415926;//编译器默认3.14是一个double类型,再转换为float类型
float f1 = 3.14f;//声明float类型的变量时后面加一个f直接来说明这是一个单精度的变量
cout<<"f1 = "<<f1<<endl; //3.14159
double d1 = 3.1415926;
cout<<"d1 = "<<d1<<endl; //3.14159
//统计占用内存空间
cout << "float占用内存空间为:" << sizeof(float) <<endl; //4字节
cout << "double占用内存空间为:" << sizeof(double) <<endl; //8字节
return 0;
}
注: 默认情况下输出一个小数,无论单双精度,会显示出6位有效数字
还可以使用科学计数法表示小数:
#include<iostream>
using namespace std;
int main(){
float f2 = 3e2; //3*10^2
cout<<"f2 = "<<f2<<endl;//300
float f3 = 3e-2; //3*10^(-2) =3*(1/10)^2
cout<<"f3 = "<<f3<<endl;//0.03
return 0;
}
7.3字符型
作用: 字符型变量用于显示单个字符
语法:char ch='a';
注1: 在显示字符型变量时,用单引号
将字符括起来,不要用双引号
注2: 单引号内只能有一个字符,不可以是字符串
C和C++中字符型变量只占用1个字节
字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元
示例:
#include <iostream>
using namespace std;
int main()
{
//字符型变量创建方式
char ch = 'a';
cout<<"ch = "<<ch<<endl;
//字符型变量所占内存大小
cout << "char占用内存空间为:" <<sizeof(ch)<<endl;//char占用内存空间为:1
//字符型变量常见错误
//char ch2 = "b"; //报错,创建字符型变量不可以使用双引号来赋值
//char ch3 = "abcde";//报错,创建字符型变量时,单引号内只能有一个字符
//字符型变量对应ASCII编码
cout<<int(ch)<<endl; //97,即字符'a'对应的ASCII编码
return 0;
}
ASCII码表:
7.3.1转义字符
作用: 用于表示一些不能显示出来的ASCII字符
现阶段我们常用的转义字符有:\n
、 \\
、 \t
示例:
#include<iostream>
using namespace std;
int main(){
//换行符\n
cout<< "hello\n world"<<endl;
//反斜杠字符
cout<< "\\"<<endl;
//制表符\t 可以整齐输出数据
cout<< "aaa\t hello world"<<endl;
/*
hello
world
aaa hello world
*/
return 0;
}
7.4字符串类型
作用: 用于表示一串字符
两种风格
(1)C语言风格的字符串char 变量名[] = "字符串值;"
示例:
#include<iostream>
using namespace std;
int main(){
char str[] = "hello world";
cout<< str <<endl; //hello world
return 0;
}
注1: char 字符串名加上中括号[]
注2: C语言风格的字符串要用双引号
括起来
(2)C++风格的字符串string 变量名 = "字符串值";
示例:
#include<iostream>
using namespace std;
#include<string>
int main(){
string str = "hello world";
cout<< str <<endl; //hello world
return 0;
}
注: C++风格的字符串,需要加入头文件#include<string>
7.5布尔型bool
作用: 布尔数据类型代表真或假的值
bool类型只有两个值:
(1)true——真(本质是1)
(2)false— 假(本质是0)
示例:
#include<iostream>
using namespace std;
int main(){
//1.创建bool数据类型
bool flag = true; // true代表真
cout<< flag <<endl; //1
flag = false; // false代表假
cout<< flag <<endl; //0
//本质上1代表真,0代表假
//查看bool类型所占内存空间
cout<< "bool类型所占内存空间:"<<sizeof(flag)<<endl;//1
return 0;
}
8.数据的输入
作用: 用于从键盘获取数据
关键字: cin
语法: cin>>
示例:
#include<iostream>
using namespace std;
#include<string>
int main(){
//1.整型
int a = 0;
cout<< "请给整型变量a赋值:"<<endl;
cin>>a;
cout<< "整型变量a="<< a <<endl;
//2.浮点型
float f = 3.14f;
cout<< "请给浮点型变量f赋值:"<<endl;
cin>>f;
cout<< "浮点型变量f="<< f <<endl;
//3.字符型
char ch = 'a';
cout<< "请给字符型变量ch赋值:"<<endl;
cin>>ch;
cout<< "字符型变量ch="<< ch <<endl;
//字符串型
string str = "hello";
cout<< "请给字符串型变量str赋值:"<<endl;
cin>>str;
cout<< "字符串型变量str="<< str <<endl;
//注:记得引入头文件#include<string>
//布尔型
bool flag = false;
cout<< "请给布尔型变量flag赋值:"<<endl;
cin>>flag;
cout<< "布尔型变量flag="<< flag <<endl;
return 0;
}
9.运算符
作用: 用于执行代码的运算
主要包括几类算术运算符:
9.1算术运算符
作用: 用于处理四则运算
算术运算符包括以下符号:
+可以作为正号也可以作为加号,同样-可以作为负号也可以作为减号.
9.1.1加减乘除
示例:
#include<iostream>
using namespace std;
int main(){
int a1 = 10;
int b1 = 3;
cout<< a1 + b1 <<endl;//13
cout<< a1 - b1 <<endl;//7
cout<< a1 * b1 <<endl;//30
cout<< a1 / b1 <<endl;//3
// 两个整数相除,结果依然是整数,将小数部分去除
int a2 = 10;
int b2 = 20;
cout<< a2 / b2 <<endl;//0
int a3 = 10;
int b3 = 0;
//cout<< a3 / b3 <<endl;//报错,除数不能为0
//两个小数可以相除
double d1 = 0.5;
double d2 = 0.22;
cout<< d1 / d2 <<endl;//2.27273 运算的结构也可以是小数
return 0;
}
9.1.2取模运算
示例:
#include<iostream>
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;//报错,除数不能为0,所以也做不了取模运算
//两个小数是不可以做取模运算的
double d1 = 3.14;
double d2 = 1.1;
//cout<< d1 % d2 <<endl;//报错
return 0;
}
注: 只有整型可以进行取模运算
9.1.3自增自减
示例:
#include<iostream>
using namespace std;
int main(){
//1.前置递增
int a = 10;
++a;//让变量+1
cout<<"a="<<a<<endl;//11
//2.后置递增
int b = 10;
b++;//让变量+1
cout<<"b="<<b<<endl;//11
//3.1.前置递增和后置递增的区别
//前置递增先让变量+1然后进行表达式运算
int a2 = 10;
int b2 = ++a2*10;
cout<<"a2="<<a2<<endl;//11
cout<<"b2="<<b2<<endl;//110
//后置递增先进行表达式运算然后让变量+1
int a3 = 10;
int b3 = a3++*10;
cout<<"a3="<<a3<<endl;//11
cout<<"b3="<<b3<<endl;//100
return 0;
}
9.2赋值运算符
作用: 用于将表达式的值赋给变量
赋值运算符包括以下几个符号:
示例:
#include<iostream>
using namespace std;
int main(){
// 1、=
int a = 10;
cout<<"a="<<a<<endl;//10
// 2、+=
a = 10;
a+=2;//a=a+2
cout<<"a="<<a<<endl;//12
// 3、-=
a = 10;
a-=2;//a=a-2
cout<<"a="<<a<<endl;//8
// 4、*=
a = 10;
a*=2;//a=a*2
cout<<"a="<<a<<endl;//20
// 5、/=
a = 10;
a/=2;//a=a/2
cout<<"a="<<a<<endl;//5
// 6、%=
a = 10;
a%=2;//a=a%2
cout<<"a="<<a<<endl;//0
return 0;
}
9.3比较运算符
作用: 用于表达式的比较,并返回一个bool真值或假值
比较运算符有以下符号:
示例:
#include<iostream>
using namespace std;
int main(){
// ==
int a = 10;
int b = 20;
cout<<(a==b)<<endl;//0
// !=
cout<<(a!=b)<<endl;//1
// >
cout<<(a>b)<<endl;//0
// <
cout<<(a<b)<<endl;//1
// >=
cout<<(a>=b)<<endl;//0
// =
cout<<(a<=b)<<endl;//1
return 0;
}
9.4逻辑运算符
作用: 用于根据表达式的值返回真值或者假值(1 or 0)
逻辑运算符有以下符号:
9.4.1逻辑非
示例:
#include<iostream>
using namespace std;
int main(){
//非:真变假,假变真
int a = 10;
cout<<!a<<endl; //0 c++中只要不是0,都是为真(1)
cout<<!!a<<endl; //1
return 0;
}
9.4.2逻辑与
示例:
#include<iostream>
using namespace std;
int main(){
//与:都真才真(同真),有假就假
int a = 10;
int b = 10;
cout<<(a && b)<<endl; //1
a = 0;
b = 10;
cout<<(a && b)<<endl; //0
a = 0;
b = 0;
cout<<(a && b)<<endl; //0
return 0;
}
9.4.3逻辑或
示例:
#include<iostream>
using namespace std;
int main(){
//或:有真就真,都假才假
int a = 10;
int b = 10;
cout<<(a || b)<<endl; //1
a = 0;
b = 10;
cout<<(a || b)<<endl; //1
a = 0;
b = 0;
cout<<(a || b)<<endl; //0
return 0;
}
10.程序流程结构
C/C++支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构
顺序结构:程序按照顺序执行,不发生跳转
选择结构:依据条件是否满足,有选择地执行相应功能
循环结构:依据条件是否满足,循环多次执行某段代码
10.1选择结构
10.1.1 if语句
作用: 执行满足条件的语句
if
语句的三种形式:
(1)单行格式if
语句
语法:if(条件){条件满足执行的语句}
示例:
#include<iostream>
using namespace std;
int main(){
//用户输入分数,如果分数大于600,视为考上一本大学,在屏幕输出
//用户输入分数
int score = 0;
cout<<"请输入一个分数:"<<endl;
cin>>score;
//打印用户输入分数
cout<<"您输入的分数为:"<<endl;
//判断分数是否大于600,如果大于,那么输出
//注意:if条件后面不要加分号
if (score>600){
cout<<"恭喜您考上了一本大学"<<endl;
}
return 0;
}
(2)多行格式if
语句
语法:if(条件){条件满足执行的语句}else{条件不满足执行的语句}
示例:
#include<iostream>
using namespace std;
int main(){
//用户输入分数,如果分数大于600,视为考上一本大学,在屏幕输出
//如果没考上,输出“未考上一本大学”
//用户输入分数
int score = 0;
cout<<"请输入一个分数:"<<endl;
cin>>score;
//提示用户输入的分数
cout<<"您输入的分数为:"<<endl;
//判断,如果大于600,打印考上一本
if (score>600){
cout<<"恭喜您考上了一本大学"<<endl;
}else{
cout<<"未考上一本大学"<<endl;
}
return 0;
}
(3)多条件的if
语句
语法:if(条件1){条件1满足执行的语句}else if(条件2){条件2满足执行的语句}...else{条件都不满足执行的语句}
示例:
#include<iostream>
using namespace std;
int main(){
//输入分数,如果大于600视为考上一本
//如果大于500视为考上二本
//如果大于400视为考上三本
//小于等于400视为未考上本科
//用户输入分数
int score = 0;
cout<<"请输入一个分数:"<<endl;
cin>>score;
//提示用户输入的分数
cout<<"您输入的分数为:"<<endl;
//判断
if (score>600){
cout<<"恭喜您考上了一本大学"<<endl;
}else if(score>500){
cout<<"恭喜您考上了二本大学"<<endl;
}else if(score>400){
cout<<"恭喜您考上了三本大学"<<endl;
}else{
cout<<"未考上大学"<<endl;
}
return 0;
}
10.1.2 嵌套if语句
在if
语句中,可以嵌套使用if
语句,达到更精确的条件判断
案例需求:
- 提示用户输入一个高考考试分数,根据分数做如下判断: ·
- 分数如果大于600视为考上一本,大于500考上二本,大于400考上三本,其余视为未考上本科 ·
- 在一本分数中,如果大于700,考入北大,大于650,考入清华,大于600考入人大
示例:
#include<iostream>
using namespace std;
int main(){
int score = 0;
cout<<"请输入一个分数:"<<endl;
cin>>score;
cout<<"您输入的分数为:"<<endl;
if (score>600){
cout<<"恭喜您考上了一本大学"<<endl;
if(score>700){
cout<<"恭喜您考上了一本大学"<<endl;
}else if(score>650){
}else{
}
}else if(score>500){
cout<<"恭喜您考上了二本大学"<<endl;
}else if(score>400){
cout<<"恭喜您考上了三本大学"<<endl;
}else{
cout<<"未考上大学"<<endl;
}
return 0;
}
案例:三只小猪称体重
有三只小猪A、B、C,请分别输入三只小猪的体重,并且判断哪只小猪最重?
#include<iostream>
using namespace std;
int main(){
int pigA = 0;
int pigB = 0;
int pigC = 0;
cout << "请输入三只小猪ABC的体重(KG):" << endl;
cin >> pigA >> pigB >> pigC; //输入方式: 23 45 67
if (pigA > pigB){
if (pigA > pigC){
cout << "小猪A最重,有:" << pigA << "KG" << endl;
}else{
cout << "小猪C最重,有:" << pigC << "KG" << endl;
}
}else{
if (pigB > pigC){
cout << "小猪B最重,有:" << pigB << "KG" << endl;
}else{
cout << "小猪C最重,有:" << pigC << "KG" << endl;
}
}
return 0;
}
10.1.3选择结构——三目运算符
作用: 通过三目运算符实现简单的判断
语法: 表达式1 ? 表达式2 : 表达式3
解释:
如果表达式1的值为真,执行表达式2,并返回表达式2的结果
如果表达式1的值为假,执行表达式3,并返回表达式3的结果
示例:
#include<iostream>
using namespace std;
int main(){
//创建三个变量abc
//将a和b作比较,将变量大的值赋值给变量c
int a = 10;
int b = 20;
int c = 0;
c = (a>b?a:b);
cout<<"c = "<< c <<endl;//c=20
//在C++中三目运算符返回的是变量,可以继续赋值
(a>b?a:b) = 100; //返回的是b的值
cout<<"a = "<< a <<endl;//a=10
cout<<"b = "<< b <<endl;//b=100
return 0;
}
10.1.4switch
作用: 执行多条件分支语句
语法:
switch(表达式){
case 结果1:执行语句;
break;
...
default:执行语句;
break;
}
示例:
#include<iostream>
using namespace std;
int main(){
//给电影进行打分
//10经典
//9非常好
//8一般
//7以下 烂片
//提示用户给电影进行打分
cout<<"请给电影进行打分"<<endl;
//用户开始进行打分
int score = 0;
cin>>score;
cout<<"您打的分数为:"<<score<<endl;
//根据用户输入的分数来提示用户最后的结果
switch(score){
case 10:
cout<<"您认为是经典电影"<<endl;
break; //退出当前分支
case 9:
cout<<"您认为电影非常好"<<endl;
break;
case 8:
cout<<"您认为电影一般"<<endl;
break;
default:
cout<<"您认为电影烂片"<<endl;
break;
}
return 0;
}
if
和switch
的区别:
switch
优点:结构清晰,执行效率高
switch
缺点:判断时候只能是整型或者字符型,不可以是一个区间
注1: switch
语句中表达式类型只能是整型或者字符型
注2: case
里如果没有break
,那么程序会一直向下执行
总结: 与if
语句相比,对于多条件判断时,switch
的结构清晰,执行效率高,缺点是switch
不可以判断区间。
10.2循环结构
10.2.1while语句
作用: 满足循环条件,执行循环语句
语法: while(循环条件){循环语句}
解释:
只要循环条件的结果为真,就执行循环语句
示例:
#include<iostream>
using namespace std;
int main(){
//打印0-9这10个数字
int num = 0;
while (num<10){
cout<<num<<endl;
num++;
}
return 0;
}
注: 在执行循环语句时,程序必须提供跳出循环的出口,否则出现死循环
案例:猜数字
案例描述:系统随机生成一个1到100之间的数字,玩家进行猜测,如果猜错,提示玩家数字过大或过小,如果猜对恭喜玩家胜利,并且退出游戏。
流程:
#include<iostream>
using namespace std;
#include<ctime>
int main(){
//添加随机数种子,作用是利用当前系统时间生成随机数,防止每次随机数都一样
srand((unsigned int)time(NULL));
//系统生成随机数
int num = rand()%100 + 1; //rand()%100+1生成0+1~99+1的随机数
//玩家进行猜测
int val = 0;
//cin>>val;
//判断玩家的猜测
while(1){
cin>>val;
//猜错 提示猜的结果 过大或者过小
if(val > num){
cout<<"猜测过大"<<endl;
}else if(val < num){
cout<<"猜测过小"<<endl;
}else{
//猜对 退出游戏
cout<<"猜对了"<<endl;
break;
}
}
return 0;
}
参考链接:C++随机数生成-菜鸟笔记 (coonote.com)
10.2.2 do-while语句
作用: 满足循环条件,执行循环语句
语法:do{循环语句} while(循环条件);
注: 与while的区别在于do…while会先执行一次,再判断循环条件
示例:
#include<iostream>
using namespace std;
int main(){
//输出0-9这10个数字
int num = 0;
do{
cout<<num<<endl;
num++;
}while(num<10);
return 0;
}
练习案例:水仙花数
案例描述:水仙花数是指一个3位数,它的每个位上的数字的3次幂之和等于它本身
例如:13 + 53 + 33 = 153
请利用do……while
语句,求出所有三位数中的水仙花数
流程:①输出所有的三位数(100-999)②在所有的三位数中找到水仙花数,先后获取个十百位三个数字,判断个位3+十位3+百位3=三位数本身
#include<iostream>
using namespace std;
int main(){
//先打印所有三位数字
int num = 100;
do{
//从所有水仙花数中找到水仙花数
int a = num % 10;//个
int b = num / 10 % 10;//十
int c = num / 100;//百
if(a*a*a+b*b*b+c*c*c==num){
//如果是水仙花数才打印
cout<<num<<endl;
}
num++;
}while(num<=999);
return 0;
}
10.2.3for循环
作用: 满足循环条件,执行循环语句
语法: for(起始表达式;条件表达式;末尾循环体){循环语句}
示例:
#include<iostream>
using namespace std;
int main(){
//输出0-9这10个数字
for(int i=0;i<10;i++){
cout<<i<<endl;
}
return 0;
}
注:for循环中的表达式,要用分号进行分割
总结: while
、do…while
、for
都是开发中常用的循环语句,for
循环结构比较清晰,比较常用
10.3循环结构案例——敲桌子
案例描述: 从1开始数到100,如果数字个位含有7,或者数字十位含有7,或者该数字是7的倍数,我们打印敲桌子,其余数字直接打印输出
#include<iostream>
using namespace std;
int main(){
for(int i=1;i<=100;i++){
// 数字个位含有7 (7):i % 10 == 7
// 数字十位含有7 (71、71...79):i / 10 == 7
// 数字是7的倍数 (14、21...):i % 7 == 0
if(i % 10 == 7 || i / 10 == 7 ||i % 7 == 0){
cout<<"敲桌子"<<endl;
}else{
cout<<i<<endl;
}
}
return 0;
}
10.4嵌套循环
作用: 在循环体中再嵌套一层循环,解决一些实际问题
例如我们想在屏幕中打印如下图片,就需要利用嵌套循环
#include<iostream>
using namespace std;
int main(){
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
cout<<"* ";
}
cout<<endl;
}
return 0;
}
注: 输出时最后加上endl会有换行的作用
endl
和\n
的区别:
· \n
是 C/C++ 中的转义字符,代表换行符。当程序执行到 \n
时,会在输出流中插入一个换行符,使得后续输出在新的一行开始 。使用 \n
只是简单地插入一个换行符,不会进行额外的性能开销。
·std::endl
是 C++ 中的流操作符,用于插入一个换行符并刷新输出流。与\n
不同的是,std::endl
不仅会插入换行符,还会强制刷新输出缓冲区,确保立即将内容输出到目标设备上 ,可能会导致性能上的损失。
参考链接: 比较c++中换行符\n与endl的区别_c++ 识别换行符-优快云博客
练习案例:乘法口诀表
案例描述:利用嵌套循环,实现九九乘法表
#include<iostream>
using namespace std;
int main(){
for(int i=1;i<10;i++){
for(int j=1;j<=i;j++){
cout<<j<<"*"<<i<<"="<<i*j<<" "; //列数*行数=结果
}
cout<<endl;
}
return 0;
}
输出结果:
10.5跳转语句
10.5.1break语句
作用: 用于跳出选择结构或者循环结构
break使用的时机:
· 出现在switch条件语句中,作用是终止case并跳出switch
示例1:
#include<iostream>
using namespace std;
int main(){
//在switch语句中使用break
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:
#include<iostream>
using namespace std;
int main(){
//出现在循环语句中
for(int i=0;i<10;i++){
//如果i等于5,退出循环
if(i==5){
break;
}
cout<<i<<endl;
}
return 0;
}
· 出现在嵌套循环中,跳出最近的内层循环语句
示例3:
#include<iostream>
using namespace std;
int main(){
//出现在嵌套循环语句中
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
if(j==5){
break;//退出内层循环
}
cout<<"*";
}
cout<<endl;
}
/*
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*/
return 0;
}
10.5.2continue语句
作用: 在循环语句中,跳过本次循环中余下尚未执行的语句,执行下一次循环
示例:
#include<iostream>
using namespace std;
int main(){
for(int i=0;i<100;i++){
//如果是奇数就输出,偶数不输出
if(i%2==0){
continue;
}else{
cout<<i<<endl;
}
}
return 0;
}
10.5.3goto语句
作用: 可以无条件跳转语句
语法: goto
标记;
解释: 如果标记的名称存在,执行到goto语句时,会跳转到标记的位置。
示例:
#include <iostream>
using namespace std;
int main() {
cout<<"1xxxx"<<endl;
cout<<"2xxxx"<<endl;
goto FLAGE;
cout<<"3xxxx"<<endl;
cout<<"4xxxx"<<endl;
FLAGE:
cout<<"5xxxx"<<endl;
return 0;
}
/*
1xxxx
2xxxx
5xxxx
*/
注: 在程序中不建议使用goto,以免造成程序流程混乱。
11.数组
所谓数组,就是一个集合,里面存放了相同类型的数据元素
特点1: 数组中的每个数据元素都是相同的数据类型
特点2: 数组是由连续的内存位置组成的
11.1一维数组
11.1.1一维数组定义的三种方式
(1)数据类型 数组名[数组长度];
#include <iostream>
using namespace std;
int main() {
//数据类型 数组名[数组长度]
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;
return 0;
}
(2)数据类型 数组名[数组长度]={值1,值2,...};
#include <iostream>
using namespace std;
int main() {
//数据类型 数组名[数组长度]={值1,值2,...}
int arr[5]={10,20,30,30,50};
//给数组中的元素进行赋值
//访问数据元素
for(int i=0;i<5;i++){
cout<<arr[i]<<endl;
}
//没被赋值的元素会默认用0填充
int arr2[5]={10,20,30};//arr2[5]={10,20,30,0,0}
return 0;
}
注: 如果初始没有给所有元素赋值,没被赋值的元素会默认用0填充。
(3)数据类型 数组名[]={值1,值2,...};
#include <iostream>
using namespace std;
int main() {
//数据类型 数组名[]={值1,值2,...}
int arr[]={90,80,70,60,50,40,30,20,10};
//给数组中的元素进行赋值
//访问数据元素
for(int i=0;i<9;i++){
cout<<arr[i]<<endl;
}
return 0;
}
总结1: 数组名的命名规范与变量名命名规范一致,不要和变量重名
总结2: 数组中下标是从0开始索引
11.1.2一维数组名称的用途
(1)可以统计整个数组在内存中的长度
(2)可以获取数组在内存中的首地址
sizeof(arr[0])
统计第一个元素所占内存大小
sizeof(arr)
统计整个数组所占内存大小
#include <iostream>
using namespace std;
int main() {
//可以通过数组名统计整个数组占用内存大小
int arr[10]={1,2,3,4,5,6,7,8,9,10};
cout<<"整个数组占用内存空间为:"<<sizeof(arr)<<endl;//40 = 10个元素*4字节
cout<<"每个数组占用内存空间为:"<<sizeof(arr[0])<<endl;//4
//可以通过数组名查看数组首地址
cout<<"数组首地址为:"<<arr<<endl; //0x7ffdfc32fb80
cout<<"数组中第一个元素的地址为:"<<&arr[0]<<endl;//0x7ffdfc32fb80
return 0;
}
注: 数组名是一个常量,不可以进行赋值操作
11.1.3案例1——五只小猪称体重
案例描述: 在一个数组中记录了五只小猪的体重,如:int arr[5]={300,350,200,400,250}; ,找出并打印最重的小猪体重。
思路: 定义一个最大值,访问数组中每个元素,如果这个元素比我认定的最大值要大,更新最大值。
#include <iostream>
using namespace std;
int main() {
int arr[5]={300,350,200,400,250};
int max = arr[0];
for(int i=1;i<5;i++){
if(arr[i]>max){
max = arr[i];
}
}
cout<<"最重的小猪体重为:"<<max<<endl;//400
return 0;
}
11.1.4案例2——元素逆置
案例描述: 请声明一个包含5个元素的数组,并且将元素逆置,如原数组为:1,3,2,5,4;逆置后输出结果为4,5,2,3,1
思路: 通过元素互换实现
#include <iostream>
using namespace std;
int main() {
int arr[5]={1,3,2,5,4};
//数组长度
int length = sizeof(arr) / sizeof(arr[0]);
int start = 0;
int end = length-1;
//1、while循环实现 当start大于等于end时,停止循环
while(start<end){
int temp = arr[start];
arr[start] = arr[end];
arr[end]= temp;
start++;
end--;
}
//2、for循环实现
for(int i=0;i<length/2;i++){
int temp = arr[i];
arr[i] = arr[length-i-1];
arr[length-i-1]= temp;
}
for(int j=0;j<length;j++){
cout<<arr[j];
}
return 0;
}
11.1.5案例3——冒泡排序
作用: 最常用的排序算法,对数组内元素进行排序
(1)比较相邻的元素。如果第一个比第二个大,就交换他们两个
(2)对每一对相邻元素做同样的操作,执行完毕后,找到第一个最大值
(3)重复以上步骤,每次比较次数-1,直到不需要比较
示例:将数组{4,2,8,0,5,7,1,3,9}进行升序排列
#include <iostream>
using namespace std;
int main() {
int arr[9]={4,2,8,0,5,7,1,3,9};
//数组长度
int n = sizeof(arr) / sizeof(arr[0]);
for(int i=0;i<n-1;i++){
for(int j=0;j<n-i-1;j++){
if(arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for(int j=0;j<n;j++){
cout<<arr[j]<<endl;
}
return 0;
}
11.2二维数组
二维数组就是在一维数组上,多加了一个维度
11.2.1二维数组定义的4种方式
(1)数据类型 数组名[行数][列数];
#include <iostream>
using namespace std;
int main() {
//数据类型 数组名[行数][列数]
int arr[2][3];
arr[0][0]=1;
arr[0][1]=2;
arr[0][2]=3;
arr[1][0]=4;
arr[1][1]=5;
arr[1][2]=6;
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
cout<<arr[i][j]<<endl;
}
}
return 0;
}
(2)数据类型 数组名[行数][列数]={{数据1,数据2},{数据3,数据4}};
#include <iostream>
using namespace std;
int main() {
//数据类型 数组名[行数][列数]={{数据1,数据2},{数据3,数据4}}
int arr[2][3]={{1,2,3},{4,5,6}};
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
cout<<arr[i][j]<<endl;
}
}
return 0;
}
(3)数据类型 数组名[行数][列数]={数据1, 数据2, 数据3, 数据4};
指定了行数列数,给出数据可以自动识别一行是几个数据
#include <iostream>
using namespace std;
int main() {
//数据类型 数组名[行数][列数]={数据1,数据2,数据3,数据4}
int arr[2][3]={1,2,3,4,5,6};
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
cout<<arr[i][j]<<endl;
}
}
return 0;
}
(4)数据类型 数组名[][列数]={数据1,数据2,数据3,数据4};
#include <iostream>
using namespace std;
int main() {
//数据类型 数组名[][列数]={数据1,数据2,数据3,数据4}
int arr[][3]={1,2,3,4,5,6};//每3列为一行
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
cout<<arr[i][j]<<endl;
}
}
return 0;
}
11.2.2二维数组数组名
作用:
查看二维数组所占内存空间
获取二维数组首地址
示例:
#include <iostream>
using namespace std;
int main() {
int arr[2][3] = {{1,2,3},{4,5,6}};
cout << "二维数组占用内存为:"<<sizeof(arr)<< endl;//24
cout << "二维数组第一行占用内存为:"<<sizeof(arr[0])<< endl;//12
cout << "二维数组第一个元素占用内存为:"<<sizeof(arr[0][0])<< endl;//4
cout << "二维数组行数为:"<<sizeof(arr) / sizeof(arr[0])<< endl;
cout << "二维数组列数为:"<<sizeof(arr[0]) / sizeof(arr[0][0])<< endl;
//查看二维数组的首地址
cout << "二维数组首地址为:"<<arr<< endl;
cout << "二维数组第一行首地址为:"<<arr[0]<< endl;
cout << "二维数组第二行首地址为:"<<arr[1]<< endl;
cout << "二维数组第一个元素首地址为:"<<&arr[0][0]<< endl;
cout << "二维数组第二个元素首地址为:"<<&arr[0][1]<< endl;
return 0;
}
/*
二维数组占用内存为:24
二维数组第一行占用内存为:12
二维数组第一个元素占用内存为:4
二维数组行数为:2
二维数组列数为:3
二维数组首地址为:0x7fffa966a690
二维数组第一行首地址为:0x7fffa966a690
二维数组第二行首地址为:0x7fffa966a69c
二维数组第一个元素首地址为:0x7fffa966a690
二维数组第二个元素首地址为:0x7fffa966a694
*/
11.2.3案例——考试成绩统计
案例描述: 有三名同学(张三、李四、王五),在一次考试中的成绩分别如下表,请分别输出三名同学的总成绩
#include <iostream>
using namespace std;
#include<string>
int main() {
int scores[3][3] = {
{100,100,100},
{90,50,100},
{60,70,80}
};
string names[3] = {"张三","李四","王五"};//注意使用string时要用双引号,并且需要引入相应头文件include<string>
for(int i=0;i<3;i++){
int sum = 0;
for(int j=0;j<3;j++){
sum += scores[i][j];
}
cout<<names[i]<<"的总分数为:"<<sum<<endl;
}
return 0;
}
12.函数
作用: 将一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能
12.1函数的定义
函数的定义主要有5个步骤
(1)返回值类型
(2)函数名
(3)参数列表
(4)函数体语句
(5)return
表达式
语法:返回值类型 函数名(参数列表){ 函数体语句 return 表达式 }
示例:定义一个加法函数,实现两个数相加
int add(int num1,int num2){
int sum = num1 + num2;
return sum;
}
返回值类型: 一个函数可以返回一个值。在函数定义中
函数名: 给函数起个名称
参数列表: 使用该函数时,传入的数据
函数体语句: 花括号内的代码,函数内需要执行的语句
return 表达式: 和返回值类型挂钩,函数执行完后,返回相应的数据
12.2函数的调用
功能: 使用定义好的函数
语法: 函数名(参数)
示例:
#include <iostream>
using namespace std;
#include<string>
//num1,num2为形参
int add(int num1,int num2){
int sum = num1 + num2;
return sum;
}
int main() {
//main函数中调用add函数
//a,b为实参,调用函数时,实参的值会传给形参
int a = 10;
int b = 20;
int result = add(a,b);
cout<<"result = "<<result<<endl;
return 0;
}
12.3函数的值传递
所谓值传递,就是函数调用时实参将数值传入给形参
值传递时,如果形参发生改变,并不会影响实参
#include <iostream>
using namespace std;
#include<string>
//定义函数,实现两个数字进行交换
//如果函数不需要返回值,声明的时候可以写void
void swap(int num1,int num2){
cout<<"交换前:"<<endl;
cout<<"num1 = "<<num1<<endl;
cout<<"num2 = "<<num2<<endl;
int temp = num1;
num1 = num2;
num2 = temp;
//不需要返回值时,可以不写return
cout<<"交换后:"<<endl;
cout<<"num1 = "<<num1<<endl;
cout<<"num2 = "<<num2<<endl;
}
int main() {
int a = 10;
int b = 20;
swap(a,b);
//函数的形参改变并不会影响实参
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
return 0;
}
/*
交换前:
num1 = 10
num2 = 20
交换后:
num1 = 20
num2 = 10
a = 10
b = 20
*/
12.4函数的常见样式
①无参无反
#include <iostream>
using namespace std;
void test01(){
cout<<"This is test01"<<endl;
}
int main() {
test01();
return 0;
}
②有参无反
#include <iostream>
using namespace std;
void test02(int a){
cout<<"This is test02 a="<<a<<endl;
}
int main() {
test02(100);
return 0;
}
③无参有反
#include <iostream>
using namespace std;
int test03(){
cout<<"This is test03"<<endl;
return 1000;
}
int main() {
int num1 = test03();
cout<<"num1="<<num1<<endl;//1000
return 0;
}
④有参有反
#include <iostream>
using namespace std;
int test04(int a){
cout<<"This is test04 a="<<a<<endl;//100
return a;
}
int main() {
int num1 = test04(100);
cout<<"num1="<<num1<<endl;//100
return 0;
}
12.5函数的声明
作用: 告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
· 函数的声明可以多次,但是函数的定义只能有一次。
示例:
#include <iostream>
using namespace std;
//函数的声明
//比较函数,实现两个整数的比较,返回大的那个
//提前告诉编译器函数的存在,可以利用函数的声明
//函数的声明
int main(int a, int b);
// 声明可以写多次,定义只能写一次
// int main(int a, int b);
// int main(int a, int b);
//定义
int max(int a, int b){
int c = a>b?a:b;
return c;
}
int main() {
int a = 10;
int b = 20;
cout<<max(a,b)<<endl;
return 0;
}
//定义 有提前声明函数时,定义可以写在main函数后面
// int max(int a, int b){
// int c = a>b?a:b;
// return c;
// }
12.6函数的分文件编写
参考链接:https://www.bilibili.com/video/BV1et411b73Z?p=55&vd_source=52619801716ef758e67c909b179fc361
13.指针
13.1指针的基本概念
指针的作用: 可以通过指针间接访问内存
· 内存的编号是从0开始记录的,一般用十六进制数字表示
· 可以利用指针变量保存地址
13.2指针变量的定义和使用
指针变量定义语法: 数据类型 *变量名;
示例:
#include <iostream>
using namespace std;
int main() {
//定义指针
int a = 10;
//指针定义的语法:数据类型 *指针变量
int * p;
//让指针记录变量a的地址
p = &a; // &为取址符号
cout<<"a的地址为:"<<&a<<endl; //0x7ffdf8c83a9c
cout<<"指针p为:"<<p<<endl; //0x7ffdf8c83a9c
//使用指针
//可以通过解引用的方式来找到指针指向的内存
//指针前加*代表解引用,找到指针指向的内存中的数据,并可以修改它
*p = 100;
cout<<"a="<<a<<endl; //100
cout<<"*p="<<*p<<endl; //100
return 0;
}
*p指向的就是指针所指向地址中的数据,可以对其进行访问和修改
13.3指针所占内存空间
提问:指针也是种数据类型,那么这种数据类型占用多少内存空间?
示例:
#include <iostream>
using namespace std;
int main() {
int a = 10;
int *p = &a;
cout << "sizeof int * =" <<sizeof(a)<< endl; //4
cout << "sizeof int * =" <<sizeof(*p)<< endl; //4
cout << "sizeof int * =" <<sizeof(p)<< endl; //8
//等价于
cout << "sizeof int * =" <<sizeof(int *)<< endl;//8
//32位操作系统下,指针都是占4个字节空间大小,不管什么数据类型
//64位操作系统下,指针都是占8个字节空间大小,不管什么数据类型
cout << "sizeof float * =" <<sizeof(float *)<< endl;//8
cout << "sizeof double * =" <<sizeof(double *)<< endl;//8
cout << "sizeof char * =" <<sizeof(char *)<< endl;//8
return 0;
}
13.4空指针和野指针
13.4.1空指针
空指针: 指针变量指向内存中编号为0的空间
用途: 初始化指针变量
注意: 空指针指向的内存是不可以访问的
示例:
#include <iostream>
using namespace std;
int main() {
//空指针用于给指针变量进行初始化
//int *p;//没有赋值的这种情况下,并不知道该指针指向哪里
int *p = NULL; //#define NULL 0 该指针编号为0
//空指针是不可以进行访问的
*p = 100; //报错
//0~255之间的内存编号是系统占用的,因此不可以访问
//知道指针变量的值之后再对前面的赋值操作进行更新
return 0;
}
13.4.2野指针
野指针: 指针变量指向非法的内存空间
示例:
#include <iostream>
using namespace std;
int main()
{
//指针变量p指向内存地址编号为0x1100的空间
int *p = (int *)0x1100;
//访问野指针报错
cout << *p << endl;
return 0;
}
总结: 空指针和野指针都不是我们申请访问的空间,因此不要访问
13.5const修饰指针
const
修饰指针有三种情况:const
修饰指针 --常量指针、const
修饰常量 --指针常量、const
既修饰指针,又修饰常量。
(1)const
修饰指针 --常量指针
注: 指针的指向可以修改,即可以指向a,也可以指向b
p=&a可以改为 p=&b
但是指针指向的值不可以改变,即 *p=20
错误
注: 输出p输出的是地址,输出*p输出的是该地址对应变量中的值
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
//常量指针
const int *p = &a;
p = &b;
cout << "p=" <<p<< endl; //p=0x7fffae759e3c
cout << "*p=" <<*p<< endl;//*p=20
*p = 20; //报错error: assignment of read-only location ‘* p’
return 0;
}
(2)const
修饰常量 --指针常量
注: 指针的指向不可以修改,但是指针指向的值可以修改
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
//指针常量
int * const p = &a;
*p = 20;
cout << "p=" <<p<< endl; //p=0x7fffae759e3c
cout << "*p=" <<*p<< endl;//*p=20
p = &b;//报错assignment of read-only variable ‘p’ p = &b
return 0;
}
(3)const既修饰指针,又修饰常量
注: 指针的指向和指针指向的值都不可以修改
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = 20;
const int * const p = &a;
*p = 20; //报错assignment of read-only location ‘*(const int*)p’
p = &b;//报错assignment of read-only variable ‘p’ p = &b
cout << "p=" <<p<< endl;
cout << "*p=" <<*p<< endl;
return 0;
}
总结:
const int *p = &a;
其中const
在 *p
前面,说明 *p
不可以修改,但p
可以修改
int * const p = &a;
其中const
在p
前面,说明p
不可以修改,但是*p
可以修改
const int * const p = &a;
,p
和*p
都不可以修改
13.6指针和数组
作用: 利用指针访问数组中元素
示例:
#include <iostream>
using namespace std;
int main() {
int arr[10] = {0,44,2,3,4,5,6,7,8,9};
cout<<"第一个元素为:"<<arr[0]<<endl;
//第一个元素为:0
int *p = arr; //arr为数组首地址
// 利用指针访问第一个元素
cout << "第一个元素为:" <<*p<< endl;
//第一个元素为:0
cout << "第二个元素为:" <<*(p+1)<< endl; //等价于*(++p) 让指针向后偏移4个字节
//第二个元素为:44
// 利用指针遍历数组
for(int i=0;i<10;i++){
cout << "第"<<i+1<<"个元素为:" <<*p<< endl;
p++;
}
/*
第1个元素为:0
第2个元素为:44
第3个元素为:2
第4个元素为:3
第5个元素为:4
第6个元素为:5
第7个元素为:6
第8个元素为:7
第9个元素为:8
第10个元素为:9
*/
return 0;
}
13.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() {
//值传递---不会改变实参
int a = 10;
int b = 20;
swap01(a,b);
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
/*
swap01 a = 20,swap01 b = 10
a = 10, b = 20
*/
//地址传递---会改变实参
swap02(&a,&b);//把变量a和b的地址作为参数传入函数中
cout<<"a = "<<a<<endl; //a=20
cout<<"b = "<<b<<endl; //b=10
return 0;
}
13.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 n){
for(int i=0;i<n-1;i++){
for(int j=0;j<n-i-1;j++){
if(arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
int main() {
//创建数组
int arr[10]={4,3,6,9,1,2,10,8,7,5};
//实现冒泡排序的函数
int len = sizeof(arr)/sizeof(arr[0]);
cout<<len<<endl;//10
bubbleSort(arr,len);
//打印排序后的结果
for(int i=0;i<10;i++){
cout<<arr[i]<<endl;
}
return 0;
}
14.结构体
14.1结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
14.2结构体定义和使用
语法: struct 结构体名{结构体成员列表};
通过结构体创建变量的方式有三种:
(1)struct 结构体名 变量名
(2)struct 结构体名 变量名 = {成员1值, 成员2值, ...}
(3)定义结构体时顺便创建变量
示例:
创建学生数据类型:包括姓名、年龄、分数,通过学生类型创建具体学生
#include <iostream>
using namespace std;
#include <string>
//创建学生数据类型:包括姓名、年龄、分数
//自定义数据类型,一些类型集合组成的一个类型
struct Student{
string name;
int age;
int score;
};
int main() {
//通过学生类型创建具体学生
//(1) struct Student s1
struct Student s1;
//struct关键字可以省略。即写为Student s1;也可以正常运行
//给s1属性赋值,通过.访问结构体变量中的属性
s1.name = "张三";
s1.age = 18;
s1.score = 100;
cout<<"姓名:"<<s1.name<<"年龄:"<<s1.age<<"分数:"<<s1.score<<endl;
//(2) struct Student s2 = {...}
struct Student s2 = {"李四",19,80};
cout<<"姓名:"<<s2.name<<"年龄:"<<s2.age<<"分数:"<<s2.score<<endl;
//(3) 在定义结构体时顺便创建结构体变量
struct Student{
string name;
int age;
int score;
}s3;//顺便创建一个结构体变量
s3.name = "王五";
s3.age = 18;
s3.score = 90;
cout<<"姓名:"<<s3.name<<"年龄:"<<s3.age<<"分数:"<<s3.score<<endl;
return 0;
}
14.3结构体数组
作用: 将自定义的结构体放入到数组中方便维护
语法: struct 结构体名数组名[元素个数]={{},{}, ...,{}}
示例:
#include <iostream>
using namespace std;
#include <string>
//定义结构体
struct Student{
string name;
int age;
int score;
};
int main() {
//创建结构体数组
struct Student stuArr[3] = {
{"张三",18,100},
{"李四",19,80},
{"王五",18,90}
};
//给结构体数组中的元素赋值
stuArr[2].name = "赵六";
stuArr[2].age = 17;
stuArr[2].score = 66;
//遍历结构体数组
for(int i=0;i<3;i++){
cout<<"姓名:"<<stuArr[i].name<<"年龄:"<<stuArr[i].age<<"分数:"<<stuArr[i].score<<endl;
}
return 0;
}
14.4结构体指针
作用: 通过指针访问结构体中的成员
利用操作符->
可以通过结构体指针访问结构体属性
示例:
#include <iostream>
using namespace std;
#include <string>
//定义学生的结构体
struct Student{
string name;
int age;
int score;
};
int main() {
//创建学生的结构体变量
struct Student s = {"张三",18,100}; //这里struct可以省略
//通过指针指向结构体变量
struct Student *p = &s; //这里struct可以省略
//通过指针访问结构体变量中的数据
//通过结构体指针,访问结构体中的属性,需要利用'->'
cout<<"姓名:"<<p->name<<"年龄:"<<p->age<<"分数:"<<p->score<<endl;
return 0;
}
14.5结构体嵌套结构体
作用: 结构体中的成员可以是另一个结构体
例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
示例:
#include <iostream>
using namespace std;
#include <string>
//
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 = 1000;
t.name = "老王";
t.age = 30;
t.stu.name = "张三";
t.stu.age = 18;
t.stu.score = 100;
cout <<"老师编号:"<<t.id<< "老师姓名:"<<t.name<<"老师年龄:"<<t.age
<<"辅导的学生姓名"<<t.stu.name<<"学生年龄"<<t.stu.age<<"学生分数"<<t.stu.score<< endl;
return 0;
}
14.5结构体做函数参数
作用: 将结构体作为参数向函数中传递
传递方式有两种:
①值传递
②地址传递
示例:
#include <iostream>
using namespace std;
#include <string>
//定义学生结构体
struct Student{
string name;
int age;
int score;
};
//打印学生信息的函数
//1.值传递
void printStu1(struct Student stu){
cout<<"printStu1"<<endl;
stu.age = 20;
cout<<"姓名"<<stu.name <<"年龄" <<stu.age<<"分数" <<stu.score<<endl;
}
//2.地址传递
void printStu2(struct Student *p){
cout<<"printStu2"<<endl;
p->age = 20;
cout<<"姓名"<<p->name <<"年龄" <<p->age<<"分数" <<p->score<<endl;
}
int main()
{
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//创建结构体变量
struct Student stu = {"张三",18,100};
//1.值传递
printStu1(stu);
cout<<"main1"<<endl;
cout<<"姓名"<<stu.name <<"年龄" <<stu.age<<"分数" <<stu.score<<endl;
//2.地址传递
printStu2(&stu);
cout<<"main2"<<endl;
cout<<"姓名"<<stu.name <<"年龄" <<stu.age<<"分数" <<stu.score<<endl;
return 0;
}
/*结果:
printStu1
姓名张三年龄20分数100
main1
姓名张三年龄18分数100
printStu2
姓名张三年龄20分数100
main2
姓名张三年龄20分数100
*/
14.6结构体中const使用场景
作用: 用const来防止误操作
示例:
#include <iostream>
using namespace std;
#include <string>
//定义学生结构体
struct Student{
string name;
int age;
int score;
};
//打印学生信息的函数
//将函数中的形参改为指针,可以减少内存空间,而且不会复制一个新的副本出来
void printStu(const struct Student *p){
cout<<"printStu"<<endl;
//p->age = 40;//会报错error: assignment of member 'Student::age' in read-only
//加入const之后,一旦有修改的操作就会报错,可以防止我们误操作
cout<<"姓名"<<p->name <<"年龄" <<p->age<<"分数" <<p->score<<endl;
}
int main()
{
//创建结构体变量
struct Student stu = {"张三",18,100};
//通过函数打印结构体信息
printStu(&stu);
cout<<"姓名"<<stu.name <<"年龄" <<stu.age<<"分数" <<stu.score<<endl;
return 0;
}
14.7结构体案例1
案例描述:
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员;
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带学生赋值;
最终打印出老师数据以及老师所带的学生数据。
#include <iostream>
using namespace std;
#include <string>
#include <ctime>
//定义学生结构体
struct Student{
string name;
int score;
};
//定义老师结构体
struct Teacher{
string name;
struct Student StuArr[5];
};
//给老师和学生赋值的函数
//void allocateSpace(struct Teacher *TeaArr,int len)
void allocateSpace(struct Teacher TeaArr[],int len){
string TeaName[3] = {"老王", "老李","老赵"};
string StuName[3][5] = {
{"张三","李四","王五","赵一","李华"},
{"李明","陈亮","刘琦","洛基","灵玉"},
{"王磊","周燕","李莉","赵恩","高瑞"}
};
int StuScors[3][5] = {
{100,90,90,98,70},
{88,78,90,100,100},
{88,78,90,100,100}
};
//给老师赋值
for(int i=0;i<len;i++){
TeaArr[i].name = TeaName[i];
//通过循环给每名老师带的学生赋值
for(int j = 0;j<5;j++){
TeaArr[i].StuArr[j].name = StuName[i][j];
//TeaArr[i].StuArr[j].score = StuScors[i][j];
//也可以使用随机数进行赋值
int random = rand() % 100; //随机选取0-100之间的数
TeaArr[i].StuArr[j].score = random;
}
}
}
//打印老师和学生的信息
//void printInfo(struct Teacher *TeaArr,int len)
void printInfo(struct Teacher TeaArr[],int len){
for(int i=0;i<len;i++){
cout<<"老师姓名:"<<TeaArr[i].name<<endl;
for(int j=0;j<5;j++){
cout<<"\t学生姓名:"<<TeaArr[i].StuArr[j].name<<"\t学生分数:"<<TeaArr[i].StuArr[j].score<<endl;
}
}
}
int main()
{
//随机数种子
srand((unsigned int)time(NULL));//防止随机数重复
//创建3名老师的数组
struct Teacher TeaArr[3];
//通过一个函数给3名老师的信息赋值,并给老师带的学生信息赋值
int len = sizeof(TeaArr)/sizeof(TeaArr[0]);
// cout<<len<<endl;//3
allocateSpace(TeaArr,len);
//打印所有老师及学生信息
printInfo(TeaArr,len);
return 0;
}
注意:
(1)使用随机数rand()
时,需要引入头文件#include <ctime>
(2)并且如果不想让随机数重复,可以在前面加入随机数种子srand((unsigned int)time(NULL));
,其中参数如果为固定数字如srand(1)那么每次取到的随机数也是固定的
14.8结构体案例2
案例描述:
设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄;
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
英雄信息:
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",22,"男"},
{"赵云",20,"男"},
{"貂蝉",19,"女"}
#include <iostream>
using namespace std;
#include <string>
//定义英雄结构体
struct Hero{
string name;
int age;
string gender;
};
//冒泡排序
//void bublbleSort(struct Hero *hArr, int n)
void bublbleSort(struct Hero hArr[], int n){
for(int i=0;i<n-1;i++){
for(int j=0; j<n-i-1;j++){
if(hArr[j].age>hArr[j+1].age){
struct Hero temp = hArr[j];
hArr[j] = hArr[j+1];
hArr[j+1] = temp;
}
}
}
}
//打印英雄的信息
//void printInfo(struct Hero *hArr,int len)
void printInfo(struct Hero hArr[],int len){
for(int i=0;i<len;i++){
cout<<"姓名:"<<hArr[i].name<<"\t年龄:"<<hArr[i].age<<"\t性别:"<<hArr[i].gender<<endl;
}
}
int main()
{
//创建5英雄的数组
struct Hero hArr[5] = {
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",22,"男"},
{"赵云",20,"男"},
{"貂蝉",19,"女"}
};
//通过函数给5个英雄赋值
int len = sizeof(hArr)/sizeof(hArr[0]);
// cout<<len<<endl;//5
//对年龄进行冒泡排序
bublbleSort(hArr,len);
//打印所有英雄信息
printInfo(hArr,len);
return 0;
}
/*结果:
姓名:貂蝉 年龄:19 性别:女
姓名:赵云 年龄:20 性别:男
姓名:关羽 年龄:22 性别:男
姓名:张飞 年龄:22 性别:男
姓名:刘备 年龄:23 性别:男
*/