【c++】一、 【基础阶段】第一个hello world程序

//c++ main()函数的返回值必须为int
#include <iostream>   //标准的输入输出流
using namespace std;  //声明一个命名空间  cout对象存在std作用域下
//单行注释
/*   多行注释
main是一个程序的入口
每个程序有且仅有一个main
*/


int main()
{
	//cout标准输出流
	//endl 换行
	cout << "hello world!" << endl;
	return 0;
}

1.3 变量

作用:给一段指定的内存空间起名字,方便操作这段内存

//c++ main()函数的返回值必须为int
#include <iostream>   //标准的输入输出流
using namespace std;  //声明一个命名空间  cout对象存在std作用域下
//单行注释
/*   多行注释
main是一个程序的入口
每个程序有且仅有一个main
*/


int main()
{
	//cout标准输出流
	//endl 换行
	cout << "hello world!" << endl;

	int a = 10;
	cout << "a=" << a << endl;
	return 0;
}


1.4 常量

作用:用于记录程序中不可更改的数据

c++定义常量的两种方法:

        1. #define 宏常量:#define 常量名 常量值

                  通常在文件上方定义,表示一个常量

        2.const修饰的变量:const 数据类型 常量名=常量值

                通常在变量定义之前加关键字const,修改该变量为常量,不可修改

//define定义的宏常量
#define Day 7
int main()
{
	
	cout << "一周总共有" << Day << "天" << endl;

	const int month = 12;  
	//month = 24;  //错误,const修饰的变量也称为常量
	cout << "一年总共有" << month << "个月" << endl;
	return 0;
}

1.5 关键字

作用: 关键字是c++中预先保留的单词(标识符)

        在定义常量或者变量(标识符)的时候,不要使用关键字

1.6 标识符(变量名,函数名)命名规则

作用:(争取见名知意)

        标识符不能是关键字;

        标识符只能由字母,数字,下划线组成;

        第一个字符必须为字母或下划线;

        字母区分大小写;

int main()
{
	 //1.标识符不能是关键字;
	//int int=1;
	
	//2.标识符只能由字母,数字,下划线组成;
	int a_b = 0;
	int _ab = 0;

	//第一个字符必须为字母或下划线;
	//int 1_a=0

	//字母区分大小写;
	int aaa = 100;
	int AAA = 100;//不是同一个
	
	return 0;
}

2. 数据类型

        创建一个常量或变量时,必须要指定相应的数据类型,否则无法给变量分配内存

        数据类型存在的意义就是给变量分配合适的内存空间,不要造成资源浪费

2.1 整形

        作用:整形变量表示的是整数类型的数据

int main()
{
	
	//短整型  2字节 (-32768~32767)
	short num1 = 10;
	//short num1 = 32768;  //输出-32768  超出上限后回到下限

	//整形  4字节
	int num2 = 10;
	//长整型 4字节(win)  4(linux 32)  8(linux 64)
	long num3 = 10;
	//长长整形 8字节
	long long num4 = 10;
	return 0;
}

2.2 sizeof关键字

作用:统计数据类型所占内存的大小

语法:sizeof(数据类型/变量)

       int a = 0;

        sizeof(int)   /  sizeof(a)

        short < int <= long <long long   整形大小比较

int main()
{
	
	//短整型  2字节 (-32768~32767)
	short num1 = 10;
	//short num1 = 32768;  //输出-32768  超出上限后回到下限
	//sizeof(数据类型/变量)占用内存空间
	cout << "短整型所占字节" << sizeof(num1) << endl;
	cout << "短整型所占字节" << sizeof(short) << endl;

	//整形  4字节
	int num2 = 10;
	//长整型 4字节(win)  4(linux 32)  8(linux 64)
	long num3 = 10;
	//长长整形 8字节
	long long num4 = 10;
	return 0;
}

2.3 浮点型

作用:用于表示小数(小数点前边也算有效数字)

浮点型变量分为两种类型:

        单精度浮点型:float

        双精度浮点型:double

        区别:表示的有效数字范围不同

3.14  有效数字有3位 3,1,4(一般情况下不论是什么类型,都会显示6位有效数字,不管是什么类型)

默认情况下,编译器会把小数类型看作双精度

2.4 字符型

只能用单引号,单引号里边只能有一个字符只占用一个字节的内存

char a = 'b'

字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII码值放到存储单元中

2.5 转义字符

/t   可以整齐的输出数据(8个空格)

2.6 字符串

char str[] = "abc"

#include<string>     string str = "abc"

#include <string>
int main()
{
	//c风格字符串
	//注意事项,加[]; =后面要用双引号包含字符串
	char str[] = "hello world";
	cout << str << endl;

	//c++风格字符串
	//注意事项   需要包含string头文件
	string str2 = "hello world";
	
	return 0;
}

2.7 布尔类型

作用:布尔数据类型代表真或假的值,占1个字节,非0的值都代表1,输出都为1(也包含负数 -1------>  1)

bool类型只有两个值:

        True    真(本质是1)

        False   假(本质是0)

int main()
{
	bool flag = true;
	cout << flag << endl;   //1

	bool flag2 = false;
	cout << flag2 << endl;  //0

	cout << sizeof(bool) << endl;   //1

	return 0;
}

2.8 数据的输入

作用:用于从键盘获取数据   cin>>变量

int main()
{
	bool a = 0;
	cout << "请给a赋值" << endl;
	cin >> a;   //输入键盘值
	cout << "整型变量a=" <<a<< endl;

	return 0;
}

3. 运算符

作用:用于执行代码的运算

3.1 算术运算符

两个整数相除,结果依然是整数,将小数部分去除(3/2=1) 

(/ %)除数≠0(分母),%本质是除法且两个小数之间可以做除法运算但不能做取余运算

++a  先加一再运算            a++  先运算再加一

int main()
{
	int a = 10;
	int b = ++a * 10;   //先加一再运算
	cout << "b=" << b << endl;   //a=11  11*10=110  
	
	int c = a++ * 10;   //先运算再加一
	cout << "c=" << c << endl;  //10*10=100  a=11

	return 0;
}

3.2 赋值运算符

3.3 比较运算符

3.4 逻辑运算符

4. 程序流程结构

4.1 选择结构

4.1.1 if 语句

4.1.2 三目运算符

在c++中三目运算符返回的是变量,可以继续赋值

int main()
{
	//创建三个变量
	//将a和b作比较,将变量大的值赋值给变量c

	int a = 10;
	int b = 20;
	int c = 0;
	c=(a > b ? a : b);
	cout << "c=" << c << endl;  //20

	//在c++中三目运算符返回的是变量,可以继续赋值
	(a > b ? a : b) = 100;
	cout << "b=" << b << endl;  //100

	return 0;
}

4.1.3 switch语句

作用:执行多条件分支语句

int main()
{
	//switch 语句
	//8-10 经典
	//5-7 非常好
	//5烂片

	//提示用户输入评分
	cout << "请给电影打分" << endl;
	int score = 0;
	cin >> score;
	cout << "您打的分数为" << score << endl;
	switch (score)
	{
	case 10:
		cout << "您认为这个是经典电影" << endl;
		break; //不加break语句下边的条件是否符合都会输出内容
	case 7:
		cout << "您认为这个是非常好电影" << endl;
		break;
	default:
		cout << "您认为这个是一般电影" << endl;
		break;
	}

	/*if 和switch区别?
	switch只能是整形或者字符型,不可以是一个区间
	优点:结构清晰,执行效率高*/
	return 0;
}

if 和switch区别?
switch缺点:只能是整形或者字符型,不可以是一个区间
优点:结构清晰,执行效率高

4.2 循环结构

4.2.1 while语句

int main()
{
	//在屏幕中打印10个数
	int num = 0;
	//注意事项,一定要避免死循环的出现
	while (num < 10)
	{
		num++;
		cout << "num=" <<num<< endl;
	}
	return 0;
}

while循环练习案例

猜数字

#include <ctime>  //time系统时间头文件包含
int main()
{
	//添加随机数种子,利用当前系统的时间生成随机数,防止每次生成的随机数一样
	srand((unsigned int)time(NULL));
	//1.随机生成一个数  ,这个每次生成的随机数都是固定的,因此需要添加一个随机数种子
	int num = rand() % 100 + 1;   //0-99  +1 1-100
	int val = 0;
	while (1)
	{
		//2.玩家猜测
		cin >> val;

		//3.判断猜测
		//猜对   结束游戏
		//猜错   给出提示,继续第2步
		if (val == num)
		{
			cout << "恭喜你猜测正确" << endl;
			break;//可以用break关键字退出当前循环
		}
		else if(val < num)
		{
			cout << "猜测过小" << endl;
		}
		else 
		{
			cout << "猜测过大" << endl;
		}
	}
	return 0;
}

4.2.2 do while 循环语句

与while的区别在于:do while会先执行一次循环语句,再判断;while是先进行判断,再执行

int main()
{
	//do while语句输出0-9
	int num = 0;
	do
	{
		cout << "num=" << num << endl;
		num++;
	} while (num<10);
	return 0;
}

练习案例:水仙花数

每个位数字的3次方之和是它本身

int main()
{
	int num = 100;
	//1.将所有三位数输出
	//2.找到水仙花数
	//获取个位,十位,百位(先对10取余,再除以10)
	//判断是否是水仙花数
	do 
	{
		int a = 0;
		int b = 0;
		int c = 0;
		a = num % 10;  //获取个位
		b = num / 10 % 10;//获取十位
		c = num / 100 ; //获取百位
		if(a*a*a+b*b*b+c*c*c==num)
		{
			cout << "水仙花数:" << num << endl;
		}
		num++;
	} while (num < 1000);

	return 0;
}

4.2.3 for循环语句

案例:敲桌子7

int main()
{
	//1.输出0-100的所有数
	//2.找出特殊数字
	//7的倍数(对7取模=0)
	//个位有7 (对10取模=7)
	//十位有7  (/10=7)
	for (int i = 0; i <= 100; i++)
	{
		
		if (i%7 == 0||i%10==7||i/10==7)//如果是特殊数字,敲桌子
		{
			cout << "敲桌子:" << i << endl;
		}
		else
		{
			cout << i << endl;
		}
	}
	
	return 0;
}

4.2.4 嵌套循环

作用:在循环中嵌套一层循环(10行10列*)

int main()
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			cout << "* ";
		}
		cout << endl;
	}
	return 0;
}

案例:九九乘法表

int main()
{
	//九九乘法表
	for (int i = 1; i < 10; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			cout << i<<"*"<<j<<"="<<i*j<<"  ";
		}
		cout << endl;
	}
	return 0;
}

4.3 跳转语句

4.3.1 break语句

作用:用于跳出选择结构或循环结构

int main()
{
	//break的使用时机
	//1. 出现在switch语句中
	cout << "请选择难度:" << endl;
	cout << "1" << endl;
	cout << "2" << endl;
	int num = 0;
	cin >> num;
	switch (num)
	{
	case 1:
		cout << "难度1" << endl;
		break;
	case 2:
		cout << "难度2" << endl;
		break;
	}

	//2. 出现在循环语句中
	for (int i = 0; i < 10; i++)
	{
		//如果i==5,退出循环
		if (5 == i)
		{
			break;
		}
		cout << i;
	}

	//3.出现在嵌套语句中
	for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j <10; j++)
			{
				if (5 == j)
				{
					break;//跳出离它最近的循环
				}
				cout << "*";  //10行5列
			}
			cout << endl;
		}
	return 0;
}

4.3.2 continue语句

作用:在循环语句中,跳过本次循环中尚未执行的语句,继续执行下一次循环

continue与break的区别:continue并未跳出循环;而break跳出了循环

int main()
{
	//奇数输出,偶数不输出
	for (int i = 0; i <= 100; i++)
	{
		if (i % 2 == 0)
		{
			continue;//可以筛选条件,执行到此就不再向下执行,执行下一次循环
            //break会退出循环,continue不会
		}
		cout << i << endl;
	}
	
	return 0;
}

4.3.3 goto语句

作用:可以无条件的跳转语句

语法:goto 标记

如果标记存在,就会跳到标记位置

int main()
{
	//goto 语句
	cout << "1" << endl;
	cout << "2" << endl;
	goto FLAG;
	cout << "3" << endl;
	cout << "4" << endl;
	FLAG;
	cout << "4" << endl;

	return 0;
}

5. 数组

5.1 概述

所谓数组,就是一个集合,里面存放了相同类型的数据元素

特点1:数组中的每个数据元素都是相同的数据类型

特点2:数组是由连续的内存位置组成的

5.2 一维数组

5.2.1 一维数组定义方式

一维数组定义的三种方式:

int main()
{
	//数组
	//1. 数据类型  数组名[数组长度]
	int arr[5];

	//2. 
	int arr2[5] = { 10,20,30,40,50 };
	for (int i = 0; i < 5; i++)
	{
		cout << arr2[i] << endl;
	}

	int arr2[5] = { 10,20,30 };//如果没有完全初始化,则用0补
	for (int i = 0; i < 5; i++)
	{
		cout << arr2[i] << endl;  //10,20,30,0,0
	}

	//3.不写数据元素,可以自己根据数据推测个数
	//定义数组的时候必须知道数组的长度(arrs[5],或者不写5,指定具体的数值)
	int arrs[] = { 1,2,3,4,5,6,7,8,9 };
	

	return 0;
}

5.2.2 一维数组的数组名

用途:统计整个数组中内存的长度   sizeof(arr)

            可以获取数组在内存中的首地址

int main()
{
	//2. 
	int arr2[5] = { 10,20,30,40,50 };
	cout << "整个数组占用内存空间为:" << sizeof(arr2)<<endl;    //20
	cout << "每个元素占用的内存空间:" << sizeof(arr2[0]) << endl;//4
	cout << "数组中元素个数:" << sizeof(arr2)/sizeof(arr2[0]) << endl;//5
	
	cout << "数组首地址:" <<(int)arr2 << endl;   //十进制
	cout << "第一个元素地址:" << (int)&arr2[0] << endl;
	cout << "第二个元素地址:" << (int)&arr2[1] << endl;   
	return 0;
}

案例:五只小猪称体重(在数组中找到最大值)

int main()
{
	//1. 创建五只小猪的体重
	int arr2[5] = { 10,20,30,40,50 };

	//2.从数组中找到最大值
	int max = 0;
	for (int i = 0; i < 10; i++)
	{
		//如果访问元素比最大值大,更新最大值
		if (arr2[i] > max)
		{
			max = arr2[i];
		}
	}
	cout << "最大值:" << max << endl;
	return 0;
}

案例:数组元素逆置(12345--54321)

int main()
{
	//实现数组元素逆置
	int arr[4] = { 10,20,30,40 };
	cout << "逆置前结果:" << endl;
	for (int i = 0; i < 4; i++)
		{
			cout << arr[i] << endl;
		}
	//创建临时变量
	int start = 0;  //起始下标
	int end = sizeof(arr) / sizeof(arr[0]) - 1;//最后下标
	int temp = arr[0];
	//在合法区间(start<end)进行互换
	while (start < end)
	{
		//交换元素
		arr[temp] = arr[start];
		arr[start] = arr[end];
		arr[end] = arr[temp];

		//更新下标
		start++;
		end--;
	}
	cout << "逆置后结果:" << endl;
	for (int i = 0; i < 4; i++)
	{
		cout << arr[i] << endl;
	}
	
	return 0;
}

5.2.3 冒泡排序

int main()
{
	//利用冒泡排序实现升序序列
	int arr[9] = {4,2,8,0,5,7,1,3,9};
	cout << "排序前:";
	for (int i = 0; i < 9; i++)
		{
			cout << arr[i] << " ";
		}
	//开始冒泡排序
	//总共排序轮数为元素个数-1
	for (int i = 0; i < 9-1; i++)
	{
		//内层循环对比   次数= 元素个数-当前轮数 -1
		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 << "排序后:";
	for (int i = 0; i < 9; i++)
	{
		cout << arr[i] << " ";
	}

	return 0;
}

5.2.4 二维数组的定义

1. 手动给每个元素进行赋值

2. 大括号里包小括号

3. 
4. 

6. 函数

函数可以多次声明,但是不能重复定义

7. 指针

7.1 指针的基本概念

指针的作用:可以通过指针间接访问内存

内存编号是从0开始记录的,一般用十六进制数字表示

可以利用指针变量保存地址

7.2 指针变量的定义和使用

int main()
{
	//1. 定义指针
	int a = 10;
	// 指针定义的语法: 数据类型 * 指针变量名
	int* p;
	// 让指针记录变量a的地址
	p = &a;
	cout << "a的地址为: " << &a << endl; //两个地址一样
	cout << "指针p为: " << p << endl;

	//2. 使用指针
	//可以通过解引用的方式来找到指针指向的内存
	//指针前加 * 代表解引用,找到指针指向的内存中的数据
	*p = 1000;
	cout << "a= " << a << endl;   //1000
	cout << "*p= " << *p << endl; //1000
}

7.3 指针所占的内存空间

在32位操作系统下:占4个字节        64位下占8个字节

int main()
{
	
	int a = 10;
	int* p = &a;
	//不管是什么数据类型 32位系统下  占4个字节;64位占8个
	cout << "int指针所占内存空间大小:" << sizeof(p) << endl; //8
	cout << "float指针所占内存空间大小:" << sizeof(float*) << endl; //8
	cout << "double指针所占内存空间大小:" << sizeof(double*) << endl; //8
	cout << "char指针所占内存空间大小:" << sizeof(char*) << endl; //8

}

7.4 空指针和野指针

空指针:指针变量指向内存编号为0的空间

用途:初始化指针变量

注意:空指针指向的内存是不可以访问的

int main()
{

	//空指针
	//1. 空指针用于给指针变量进行初始化
	int* p = NULL;

	//2. 空指针是不可以进行访问的
	//0-255之间的内存编号是系统占用的,因此不可以访问
	*p = 100;  //运行错误

	cout << "char指针所占内存空间大小:" << sizeof(char*) << endl; //8

}

野指针:指针变量指向非法的内存空间

int main()
{

	//野指针
	//指针变量p指向非法的内存空间,这个内存空间不知道是什么
	int* p = (int *)0x1100;

	//访问野指针报错
	cout << *p << endl;

	//cout << "char指针所占内存空间大小:" << sizeof(char*) << endl; //8

}

7.5 const修饰指针

const修饰指针有三种情况:

1. const修饰指针  --常量指针  (const int * p)

        特点:指针的指向可以改,但指针指向的值不可以改

2. const修饰常量  --指针常量  (int * const p)

        特点:指针的指向不可以改,指针指向的值可以改

3. const既修饰指针又修饰常量

        特点:指针的指向和指针指向的值都不可以改

记忆:const后边跟的是谁,谁就不能操作

        1. const int * p   跟的是*,所以*不能操作,即不能改变值

        2. int * const p    跟的是指针p,所以指针的指向不能改

1.  
	int a = 10;
	int b = 15;
	const int* p = &a;

	//*p = 20;//错误,指针指向的值不可以改
	p = &b;//正确,指针指向可以改
2.  
	int a = 10;
	int b = 15;
	 int * const p = &a;

	*p = 20;//正确,指针指向的值可以改
	//p = &b;//错误,指针指向不可以改

}
3.
	int a = 10;
	int b = 15;
	const int* const p = &a;

	//*p = 20;//错误,指针指向的值都不可以改
	//p = &b;//错误,指针指向不可以改

}

7.6 指针和数组

int main()
{
	//指针和数组
	//利用指针访问数组中的元素
	int arr[5] = { 1,2,3,4,5 };
	cout << "第一个元素为:" << arr[0] << endl;

	int* p = arr;//arr就是数组的首地址
	cout << "利用指针访问第一个元素为:" << *p << endl;
	p++;//一个指针占多少个字节,p++就加多少
	cout << "利用指针访问第二个元素为:" << *p << endl;

}

7.7 指针和函数

//实现两个数字进行交换
void swap01(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
	cout << "形参a=" << a << endl;
	cout << "形参b=" << b << endl;
}

void swap02(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
	cout << "形参a=" << *a << endl;
	cout << "形参b=" << *b << endl;
}
int main()
{
	//指针和函数
	//1. 值传递
	int a = 10;
	int b = 20;
	swap01(a, b);  //只是形参发生了改变a=20,b=10,外侧的实参并未发生改变
	cout << "a=" << a << endl;  //10
	cout << "b=" << b << endl;  //20

	//2. 地址传递
	//如果是地址传递,可以修改实参的值
	swap02(&a, &b);  //a=20,b=10  
	cout << "a=" << a << endl;  //20
	cout << "b=" << b << endl;  //10
	
	return 0;

}

7.8 指针、数组、函数

封装一个函数,利用冒泡排序,实现对整型数组的升序排列

//数组地址   数组长度
void bubbleSort(int* arr,int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			//如果j>i,交换
			if (arr[j] < arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}
//打印数组
void printarr(int* arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << endl;
	}
}
int main()
{
	//1.创建数组
	int arr[5] = { 1,2,3,4,5 };
	//2.创建函数,进行冒泡排序
	int len = sizeof(arr) / sizeof(arr[0]);
	bubbleSort(arr, len);
	//3.打印排序后的数组
	printarr(arr, len);

	
	return 0;

}

8. 结构体

8.1 结构体的基本概念

结构体属于用户自定义的数据类型,允许用户存储不同的数据类型

8.2 结构体定义与使用

通过结构体创建变量的方式有三种:

#include<string>
//1. 创建学生数据类型:学生包括(姓名,年龄,分数)
struct Student
{
	//成员列表
	string name;
	int age;
	int score;
}s3;//2.3 顺便创建结构体变量

int main()
{
	//2. 通过学生类型创建具体学生
	//2.1 struct Stu s1;
	//给s1属性赋值,通过.访问结构体变量中的属性
	Student s1;  //创建变量的时候,结构体类型可以省(struct)
	s1.name = "张三";
	s1.age = 18;
	s1.score = 100;
	cout << "姓名:" << s1.name << "年龄:" << s1.age << "分数" << s1.score << endl;
	//2.2 struct Stu s2={.....}
	struct Student s2 = { "李四",19,200 };
	cout << "姓名:" << s2.name << "年龄:" << s2.age << "分数" << s2.score << endl;
	//2.3 定义结构体时顺便创建结构体变量
	s3.name = "王五";
	s3.age = 21;
	s3.score = 300;
	cout << "姓名:" << s3.name << "年龄:" << s3.age << "分数" << s3.score << endl;
	return 0;
}

总结:定义结构体时的关键字是struct,不可省略

        创建结构体变量时,关键字struct可以省略

        结构体变量利用操作符"."访问成员

8.3 结构体数组

作用:将自定义的结构体放入到数组中方便维护

#include<string>
//1. 定义结构体
struct Student
{
	//成员列表
	string name;
	int age;
	int score;
};

int main()
{
	//2. 创建结构体数组
	struct Student stuarry[3] =
	{
		{"张三",18,100},
		{"里斯",19,200},
		{"王五",20,300}
	};

	//3. 给结构体数组中的元素赋值
	stuarry[2].name = "赵六";
	stuarry[2].age = 80;

	//4. 遍历结构体数组
	for (int i = 0; i < 3; i++)
	{
		cout << "姓名:" << stuarry[i].name 
			<< "年龄:" << stuarry[i].age 
			<< "分数" << stuarry[i].score
			<< endl;
	}
	
	return 0;
}

8.4 结构体指针

作用:通过指针访问结构体中的成员     ->访问成员

#include<string>
//结构体指针(Student 是数据类型)
struct Student
{
	//成员列表
	string name;
	int age;
	int score;
};

int main()
{
	//2. 创建学生结构体变量
	struct Student s = {"张三",19,5};
	//3. 通过指针访问结构体变量
	struct Student* p = &s;
	//4. 通过指针访问结构体变量中的数据
	cout << "姓名:" << p->name
		<< "年龄:" << p->age
		<< "分数:" << p->score
		<< endl;

	return 0;
}

8.5 结构体嵌套结构体

作用:结构体中的成员可以是另一个结构体

#include<string>
//结构体指针(Student 是数据类型)

struct Student
{
	//成员列表
	string name;
	int age;
	int score;
};
struct Teacher
{
	//成员列表
	int id;
	string name;
	int age;
	struct Student stu;
};


int main()
{
	//2. 创建老师
	struct Teacher t = { 100,"李",50 };
	t.stu.name = "张三";
	t.stu.age= 19;
	t.stu.score = 200;
	cout << "姓名:" <<t.name
		<< "年龄:" << t.age
		<< "id:" << t.id
		<<"学生姓名:"<<t.stu.name
		<< "学生年龄:" << t.stu.age
		<< "学生分数:" << t.stu.score
		<< endl;

	return 0;
}

8.6 结构体做函数参数

作用:将结构体作为参数向函数中传递

#include<string>
//结构体指针(Student 是数据类型)
struct Student
{
	//成员列表
	string name;
	int age;
	int score;
};

//打印学生信息的函数
//1. 值传递
void printStudent_1(struct Student s)
{
	s.age = 100;
	cout << "子函数1中结果姓名:" << s.name
		<< "年龄:" << s.age
		<< "分数:" << s.score
		<< endl;
}
void printStudent_2(struct Student * s)
{
	s->age = 200;
	cout << "子函数2中结果姓名:" << s->name
		<< "年龄:" << s->age
		<< "分数:" << s->score
		<< endl;
}
int main()
{
	//创建学生结构体变量
	struct Student s = {"张三",19,5};
	cout << "main中结果姓名:" << s.name
		<< "年龄:" << s.age
		<< "分数:" << s.score
		<< endl;

	printStudent_1(s);//值传递
	cout << "1后结果姓名:" << s.name
		<< "年龄:" << s.age
		<< "分数:" << s.score
		<< endl;
	printStudent_2(&s);//地址传递
	cout << "2后结果姓名:" << s.name
		<< "年龄:" << s.age
		<< "分数:" << s.score
		<< endl;

	return 0;
}

8.7 结构体中const使用场景

作用:用const来防止误操作

#include<string>
//结构体指针(Student 是数据类型)
struct Student
{
	//成员列表
	string name;
	int age;
	int score;
};

void printstudents(Student *s)
{
	s->age = 100;
	cout << "姓名:" << s->name
		<< "年龄:" << s->age
		<< "分数:" << s->score
		<< endl;
}

void printstudents_const(const Student *s)
{ 
	//s->age = 100;   加入const后,误操作修改成员属性会报错
	cout << "姓名:" << s->name
		<< "年龄:" << s->age
		<< "分数:" << s->score
		<< endl;
}
int main()
{
	
	struct Student s = {"张三",19,5};
	
	//通过函数打印结构体变量信息
	//printstudents(s);  //值传递每次调用都会拷贝一份数据,调用几次,拷贝几次,占用的内存过大
	printstudents(&s);  //将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
	
	//如果在函数体中修改内容,会违背本意,因此加const防止误操作
	printstudents_const(&s);
	return 0;
}

8.8 结构体案例

三个老师,每个老师带五个学生

#include<string>
#include<random>
#include<Ctime>
//结构体指针(Student 是数据类型)
struct Student
{
	//成员列表
	string name;
	int score;
};
struct Teacher
{
	//成员列表
	string name;
	struct Student stu[5];
};

void allocate(struct Teacher t[],int len)  //传数组的时候,一般也要传数组有多长
{
	string nameSeed = "abcde";
	//给老师开始赋值
	for (int i = 0; i < len; i++)
	{
		t[i].name = nameSeed[i];
		//通过循环给每名老师所带的学生赋值
		for (int j = 0; j < 5; j++)
		{
			t[i].stu[j].name = nameSeed[j];
			int randdom = rand() % 61+40; //40-100
			t[i].stu[j].score = randdom;
		}
	}

}

void printall(struct Teacher t[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << "老师姓名:" << t[i].name;
		//通过循环给每名老师所带的学生赋值
		for (int j = 0; j < 5; j++)
		{
			cout << "\t学生姓名:" << t[i].stu[j].name
				<< "学生成绩:" << t[i].stu[j].score
				<< endl;
		}
	}
}
int main()
{
	//随机数种子
	srand((unsigned int)time(NULL));
	//1. 创建3名老师数组
	struct Teacher t[3] ;
	//2. 创建一个给老师和学生赋值的函数
	int len = sizeof(t) / sizeof(t[0]);
	allocate(t, len);

	//输出所有老师的所有学生
	printall(t, len);



	return 0;
}

8.8.2 案例2

#include<string>
//1. 定义结构体
struct Hero
{
	//成员列表
	string name;
	int age;
};

//冒泡排序实现年龄升序排列
void bubbleSort(Hero hero[], int len)
{
	for (int i = 0; i < len-1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (hero[j].age > hero[j + 1].age)
			{
				struct Hero temp = hero[j];
				hero[j] = hero[j + 1];
				hero[j + 1] = temp;
			}
		}
	}
}
//打印排序后数组
void printHero(struct Hero hero[],int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << "姓名:" << hero[i].name
			<< "年龄:" << hero[i].age
			<< endl;
	}
}
int main()
{
	//2. 创建结构体数组
	struct Hero hero[3] =
	{
		{"张三",18},
		{"里斯",19},
		{"王五",20}
	};

	//
	int len = sizeof(hero) / sizeof(hero[0]);
	4. 遍历结构体数组
	//for (int i = 0; i < len; i++)
	//{
	//	cout << "姓名:" << hero[i].name 
	//		<< "年龄:" << hero[i].age 
	//		<< endl;
	//}
	//对数组中的年龄进行排序,升序
	bubbleSort(hero, len);

	printHero(hero, len);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值