C++入门基础第四篇

149 阅读4分钟

C++入门基础第四篇

1、指针

056指针-指针的定义和使用

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

  • 内存编号是从0开始记录的,一般用十六进制数字表示
  • 可以利用指针保存地址

指针的变量定义语法:数据类型 *变量名;

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int a = 10;
	//1、定义一个指针
	int *p;
	//让指针记录变量a的地址
	p = &a;
	cout << "a的地址为:" << &a << endl;
	cout << "指针p为:" << p << endl;
	//2、使用指针
	//可以通过解引用的方式来找到指针指向内存中的数据
	*p = 1000;
	cout << " a= " << a << endl;
	cout << "*p =" << *p << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

057指针-指针所占内存空间

提问:指针也是种数据类型,那么这种数据类型占用多少内存空间?

#include<iostream>
#include<string>
using namespace std;
int main()
{
	//指针所占的内存空间的大小
	int a = 10;
	int *p = &a;
	//在32位系统下,指针是占4个字节空间大小,不管是什么数据类型
	//在64位系统下,指针是占8个字节空间大小,不管是什么数据类型
	cout << "sizeof(int*) =" << sizeof(int*) << endl;
	cout << "sizeof(dobule*) =" << sizeof(double*) << endl;
	cout << "sizeof(float*) =" << sizeof(float*) << endl;
	cout << "sizeof(short*) =" << sizeof(short*) << endl;
	system("pause");
	return 0;
}

058指针-空指针

空指针:指针变量指向的内存中编号为0的空间 用途:初始化指针变量 注意:空指针指向的内存是不可以访问的

#include<iostream>
#include<string>
using namespace std;
int main()
{
	//空指针
	//1、空指针用于给指针变量进行初始化
	int* p = nullptr;
	//2、空指针是不可以进行访问的
	//0 ~ 255之间的编号是系统占用的,因此不可以访问
	*p = 100;
	system("pause");
	return 0;
}

在这里插入图片描述

059指针-野指针

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

空指针和野指针都不是我们申请的空间,因此不要访问。 在这里插入图片描述

060指针-const修饰指针

const修饰指针有三种情况:

  1. const修饰指针 ----常量指针
  2. const修饰常量 ----指针常量
  3. const修饰指针,又修饰常量 在这里插入图片描述
#include<iostream>
#include<string>
using namespace std;
int main()
{
	//1、const修饰指针   常量指针
	int a = 10, b = 20;
	const int *p = &a; //特点是指针指向的值不可以改,指针的指向可以改
	//*p = 20;//错误
	p = &b;
	//2、const修饰常量   指针常量
	int *const p2 = &a;//特点是指针的指向是不可以改,指针指向的值可以改
	*p2 = b;     //正确
	//p2 = &b;   //错误

	//3、const修饰指针和常量
	const int * const p3 = &a;//指针的指向和指针指向的值都不可以修改
	//*p3 = 100;  //错误
	//p3 = &b;    //错误
	system("pause");
	return 0;
}

061指针-指针和数组

作用:利用指针访问数组中元素

#include<iostream>
#include<string>
using namespace std;
int main()
{
	//指针和数组
	//利用指针访问数组中的元素
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8,  9, 10 };
	int *p = arr;  //arr就是数组的首地址
	cout << "利用指针访问第一个元素:" << *p << endl;
	p++;    //让指针向后偏移4个字节
	cout << "利用指针访问第二个元素:" << *p << endl;
	cout << "利用指针遍历数组" << endl;
	auto p2 = arr;
	for (int i = 0; i < 10; i++){
		cout << *p2 << " ";
		p2++;
	}
	cout << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

062指针-指针和函数

作用:利用指针做函数参数,可以修改实参的值

#include<iostream>
#include<string>
using namespace std;
static void swap01(int a, int b){
	int temp = a;
	a = b;
	b = temp;
}
static void swap02(int *a, int *b){
	int temp = *a;
	*a = *b;
	*b = temp;
}
int main()
{
	//指针和函数
	//1、值传递
	int a = 10, b = 20;
	swap01(a, b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	//2、地址传递
	swap02(&a, &b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	system("pause");
	return 0;
}

在这里插入图片描述 总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递。

063指针-指针配合数组和函数案例

案例封装:封装一个函数,利用冒泡排序,实现对整数型数组的升序排序 int arr[10] = {1,3,4,5,6,2,7,9,8,0};

#include<iostream>
#include<string>
using namespace std;
static 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])
				swap(arr[j], arr[j + 1]);
		}
	}
}
static void printArray(int*arr,int n){
	for (int i = 0; i < n; i++){
		cout << *arr << " ";
		arr++;
	}
	cout << endl;
}
int main()
{
	//1、先创建数组
	int arr[10] = { 1, 3, 4, 5, 6, 2, 7, 9, 8, 0 };
	int len = sizeof(arr) / sizeof(arr[0]);
	//2、创建函数,实现冒泡排序
	bubbleSort(arr, len);
	//3、打印排序后的数组
	printArray(arr, len);
	system("pause");
	return 0;
}

在这里插入图片描述

2、结构体

064结构体-结构体定义和使用

结构体的基本概念

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

结构体的定义和使用

语法:struct 结构体{结构体成员列表};

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

  • struct结构体名 变量名
  • struct结构体名 变量名 = {成员1值,成员2值....}
  • 定义结构体是顺便创建变量
#include<iostream>
#include<string>
using namespace std;
//自定义的数据类型,就是数据类型的集合的一个类型
struct Student{
	string m_Name;
	int m_Age;
	int m_Score;
}s3;
int main()
{
	//2.1 struct Student s1;
	Student s1;
	s1.m_Name = "张三";
	s1.m_Age = 20;
	s1.m_Score = 100;
	cout << "姓名:" << s1.m_Name << "\t年龄:" << s1.m_Age << "\t分数:" << s1.m_Score << endl;
	//2.2 struct Student s2 = { ... }
	Student s2 = { "李四", 18, 90 };
	cout << "姓名:" << s2.m_Name << "\t年龄:" << s2.m_Age << "\t分数:" << s2.m_Score << endl;
	//2.3 在定义结构体时顺便创建结构体变量
	s3.m_Name = "王五";
	s3.m_Age = 25;
	s3.m_Score = 100;
	cout << "姓名:" << s3.m_Name << "\t年龄:" << s3.m_Age << "\t分数:" << s3.m_Score << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

065结构体-结构体数组

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

语法:struct 结构体 数组名[元素个数] = { { },{ },... { }};

#include<iostream>
#include<string>
using namespace std;
//结构体数组
//1、定义结构体
struct Student{
	string m_Name;
	int m_Age;
	int m_Score;
};
int main()
{
	//2、创建结构体数组
	Student stuArray[3] = 
	{
		{ "张三", 18, 100 },
		{ "王五", 19, 90 },
		{ "李四", 15, 99 }
	};
	//3、给结构体数组中的元素赋值
	stuArray[2].m_Name = "赵六";
	stuArray[2].m_Age = 80;
	stuArray[2].m_Score = 80;
	//4、遍历结构体数组
	for (int i = 0; i < 3; i++){
		cout << "姓名:" << stuArray[i].m_Name
			<< "\t年龄:" << stuArray[i].m_Age
			<< "\t分数:" << stuArray[i].m_Score <<endl;
	}
	system("pause");
	return 0;
}

在这里插入图片描述

066结构体-结构体指针

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

  • 利用操作符->可以通过结构体指针访问结构体属性
#include<iostream>
#include<string>
using namespace std;
//结构体指针
//1、定义结构体
struct Student{
	string m_Name;
	int m_Age;
	int m_Score;
};
int main()
{
	//1、创建结构体变量
	Student s = { "张三", 18, 100 };
	//2、通过指针指向结构体变量
	Student  *sp = &s;
	//3、通过指针访问结构体变量中的数据
	cout << "姓名:" << sp->m_Age
		<< "\t年龄:" << (*sp).m_Age
		<< "\t分数:" << sp->m_Score << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

067结构体-结构体嵌套结构体

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

例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体

#include<iostream>
#include<string>
using namespace std;

//1、定义结构体
struct Student{
	string m_Name;
	int m_Age;
	int m_Score;
};
//定义老师的结构体
struct Teacher{
	int id;
	string name;
	int age;
	Student stu;
};

int main()
{
	Teacher t;
	t.id = 100;
	t.age = 50;
	t.name = "老王";
	t.stu.m_Name = "小王";
	t.stu.m_Age = 20;
	t.stu.m_Score = 100;

	cout << "老师的姓名: " << t.name << "\t老师的编号:" << t.id
		<< "\t老师的年龄:" << t.age << "\n" << "老师辅导的学生姓名:" << t.stu.m_Name
		<< "\t学生的年龄:" << t.stu.m_Age << "\t学生的考试分数:" << t.stu.m_Score << endl;
	system("pause");
	return 0;
}

068结构体-结构体做函数参数

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

传递的方式有:

  • 值传递
  • 地址传递
#include<iostream>
#include<string>
using namespace std;

//1、定义结构体
struct Student{
	string m_Name;
	int m_Age;
	int m_Score;
};
//1、值传递
static void printStudent1(Student s){
	s.m_Age = 100;
	cout << "子函数1中 姓名:\t" << s.m_Name <<
		"\t 年龄:" << s.m_Age << "\t 分数:" << s.m_Score << endl;
}
//2、地址传递
static void printStudent2(const Student *s){
	cout << "子函数2中 姓名:\t" << s->m_Name <<
		"\t 年龄:" << (*s).m_Age << "\t 分数:" << s->m_Score << endl;
}
int main()
{
	//结构体做函数参数
	//将学生传入到一个参数中,打印学生身上的所有信息
	//创建结构体变量
	Student s = { "张三", 18, 100 };
	cout << "main中函数打印 姓名\t " << s.m_Name <<
		"\t 年龄:" << s.m_Age << "\t 分数:" << s.m_Score << endl;
	printStudent1(s);
	//printStudent2(&s);
	system("pause");
	return 0;
}

在这里插入图片描述 总结:如果不想修改主函数中的数据,用值传递,反之用地址传递

069结构体-结构体中const使用场景

作用:用const 来防止误操作

将函数中的形参改为指针,可以减少内存空间,而且不会复制除新的副本出来

#include<iostream>
#include<string>
using namespace std;

//1、定义结构体
struct Student{
	string m_Name;
	int m_Age;
	int m_Score;
};
//将函数中的形参改为指针,可以减少内存空间,而且不会复制除新的副本出来
static void printStudent(const Student *s){
	//s->m_Age = 100;    //错误,禁止修改,防止误操作
	cout << "子函数2中 姓名:\t" << s->m_Name <<
		"\t 年龄:" << (*s).m_Age << "\t 分数:" << s->m_Score << endl;
}
int main()
{
	//创建结构体变量
	Student s = { "张三", 18, 100 };
	//通过函数打印结构体变量信息
	printStudent(&s);
	system("pause");
	return 0;
}

070结构体-结构体案例1

案例描述:

学校正在做毕业设计,每个老师带5个学生,总共有3名老师,需求如下

设计学生和老师的结构体,其中老师的结构体中,有老师 姓名和一个存放5名学生的数组作为成员,学生的成员有姓名、考试分数、创建数组存放3名老师,通过函数给每个老师及所带学生赋值最重打印出老师数据以及老师所带学生的数据。

在这里插入图片描述

#include<iostream>
#include<string>
#include<ctime>
using namespace std;
//学生的结构体
struct Student{
	string sName;
	int sScore;
};
//老师的结构体定义
struct Teacher{
	string tName;
	Student sArray[5];
};
//给老师和学生赋值的函数
static void allocateSpace(Teacher *tArray, int len){
	string nameSeed = "ABCDE";
	for (int i = 0; i < len; i++){//给老师赋值
		tArray[i].tName = "Teacher_";
		tArray[i].tName += nameSeed[i];

		//通过循环给每个老师的学生赋值
		for (int j = 0; j < 5; j++){
			tArray[i].sArray[j].sName = "Student_";
			tArray[i].sArray[j].sName += nameSeed[j];
			int random = rand() % 61 + 40; //40~99
			tArray[i].sArray[j].sScore = random;
		}
	}
}
//打印所有信息
static void printInfor(Teacher *tArray, int len){
	for (int i = 0; i < len; i++){
		cout << "老师的姓名:" << tArray[i].tName << endl;
		for (int j = 0; j < 5; j++){
			cout << "\t学生的姓名:" << tArray[i].sArray[j].sName 
				<< "\t考试的分数" << tArray[i].sArray[j].sScore << endl;
		}
	}
}
int main()
{
	//随机数种子
	srand((unsigned int)time(nullptr));
	//1、创建3名老师的数组
	Teacher tArray[3];
	//2、通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
	int len = sizeof(tArray) / sizeof(tArray[0]);
	allocateSpace(tArray, len);
	//3、打印所有老师及所带的学生信息
	printInfor(tArray, len);
	system("pause");
	return 0;
}

在这里插入图片描述

071结构体-结构体案例2

案例描述: 设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。 通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果

#include<iostream>
#include<string>
using namespace std;
//1、设计英雄的结构体
struct Hero{
	string name;
	int age;
	string sex;
};
static void bubbleSort(Hero *heroArray, int len){
	for (int i = 0; i < len - 1; i++){
		for (int j = 0; j < len - i - 1; j++){
			if (heroArray[j].age > heroArray[j + 1].age)
				swap(heroArray[j], heroArray[j + 1]);
		}
	}
}
static void printHeroArray(Hero *heroArray, int len){
	for (int i = 0; i < len; i++){
		cout << "英雄的姓名:" << heroArray[i].name << "英雄的年龄:" << heroArray[i].age
			 << "英雄的性别:" << heroArray[i].sex << endl;
	}
}
int main()
{
	//2、创建数组存放5个英雄
	Hero heroArray[5] =
	{
		{ "刘备", 54, "男" },
		{ "关于", 39, "男" },
		{ "张飞", 30, "男" },
		{ "赵云", 36, "男" },
		{ "貂蝉", 19, "女" }
	};
	int len = sizeof(heroArray) / sizeof(heroArray[0]);
	/*for (int i = 0; i < len; i++){
		cout << "姓名:" << heroArray[i].name << "\t年龄:" << 
		heroArray[i].age << "\t性别:" << heroArray[i].sex << endl;
	}*/
	//3、对数组进行排序,按照年龄进行升序排列
	bubbleSort(heroArray, len);
	//4、将排序后的打印输出
	printHeroArray(heroArray, len);
	system("pause");
	return 0;
}

在这里插入图片描述