C++基础

文章目录

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;
}

ifswitch的区别:
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循环中的表达式,要用分号进行分割
总结: whiledo…whilefor都是开发中常用的循环语句,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;其中constp前面,说明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	性别:男
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值