C++学习路线之C++基础(四)——指针和结构体

在昨天的学习中,学习了C++中数组和函数的相关知识,其中数组名是指向的是数组的起始地址,数组使用中需要一个注意的问题就是访问越界问题,数组下标的使用需要注意。函数是将一些特定的功能模块进行封装,之后需要使用时直接调用这些函数就行。在今天的学习中主要学习C++中指针和结构体相关的知识。

六、指针:

6.1、指针的基本概念

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

 定义指针与使用:

数据类型 * 指针名 

int *p ;

p = &a;//&:取地址符

通过解引用的方式,找到指针指向的内存。

*p 取p地址所存的值,也就是a的值

 代码示例:

#include<iostream>

using namespace std;

int main()
{
	int a = 10;
	int* p;
	p = &a;
	cout << "a = " << a << endl;
	cout << "*p = " << *p << endl;
	*p = 100;
	cout << "a = " << a << endl;
	cout << "*p = " << *p << endl;
	return 0;
}

6.2、指针所占内存空间

指针存储的是地址编号,在32位计算机操作系统下,指针占32位,共4B。在64位操作系统下,指针一共64位,占8B。

6.3、空指针和野指针:

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

用途:初始化指针变量。(空指针指向的内存时不可以访问的)——0-255之间的编号是系统占用的,不可以访问。

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

在程序中要避免出现野指针

int *p = (int *)0x1100;

空指针和野指针都不是我们申请的空间,因此不要访问。

6.4、const修饰指针 

6.4.1、常量指针

const修饰指针,const在指针前面

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

#include<iostream>

using namespace std;

int main()
{
	int a = 10;
	int b = 15;
	const int* p = &a;
	//*p = 20;//指针指向的值不可以修改,错误。
	p = &b;//指针指向可以改
}

6.4.2、指针常量

const修饰常量。

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

#include<iostream>

using namespace std;

int main()
{
	int a = 10;
	int b = 15;
	int* const q = &a;
	//q = &b;//指针指向不可以改
	*q = 20;//指针指向的值可以修改
}

6.4.3、既修饰指针,又修饰常量

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

#include<iostream>

using namespace std;

int main()
{
	int a = 10;
	int b = 15;
	const int* const r = &a;
	r = &b;//指针指向不可以改
	*r = 20;//指针指向的值不可以修改,错误。
	return 0;
}

 6.5、指针和数组

可以通过指针访问数组元素。

#include<iostream>

using namespace std;

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;//指针数组
	cout << "利用指针访问第一个元素" << *p << endl;
	p++;
	cout << "利用指针访问第二个元素" << *p << endl;
	return 0;
}

数组指针(行指针):定义为:int( * p)[n]; (注意优先级:()>[]> *),指向数组的指针

#include<iostream>

using namespace std;

int main()
{
	//数组指针:
	int score[3][2] = {
		{1,2},
		{3,4},
		{5,6}
	};
	int(*parr)[2] = score;//定义了一个指向含有两个元素的数组指针
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 2; j++)
		{
			cout << parr[i][j] << ",";
		}
		cout << endl;
	}
	return 0;
}

二维数组名在传递过程中弱化为数组指针。

指针数组:定义为:int* p[n]; (注意优先级:()>[]> *),数组里含有的元素为指针类型

int *p[3];     //定义指针数组
int a[3][4];
for(i=0;i<3;i++){
    p[i]=a[i];     //通过循环将a数组每行的首地址分别赋值给p里的元素  
}

6.6、指针和函数

地址传递,传递给函数的是一个地址,通过地址传递可以修改该地址中指向的值,不可以修改指针指向的地址。

#include<iostream>

using namespace std;

void swap(int* p, int* q)
{
	int temp;
	cout << "交换前*p = " << *p << endl;
	cout << "交换前*q = " << *q << endl;
	temp = *p;
	*p = *q;
	*q = temp;
	cout << "交换后*p = " << *p << endl;
	cout << "交换后*q = " << *q << endl;
}

int main()
{
	int a = 10;
	int b = 20;
	cout << "交换前a = " << a << endl;
	cout << "交换前b = " << b << endl;
	swap(&a, &b);
	cout << "交换后a = " << a << endl;
	cout << "交换后b = " << b << endl;
	return 0;
}

通过上面的代码可以发现,通过地址传递,可以修改实参a和b的值。

指针数组函数案例:

案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序。

示例数组:arr[10]={4,3,6,9,1,2,10,8,7,5};

#include<iostream>

using namespace std;

void swap(int* p, int* q)
{
	int temp;
	temp = *p;
	*p = *q;
	*q = temp;
}

void bubblesort(int* arr, int len)
{
	for (int i = len - 1; i > 0; i--)
	{
		for (int j = 0; j < i; j++) {
			if (arr[j] > arr[j + 1])
			{
				swap(arr[j], arr[j + 1]);
			}
		}
	}
}

int main()
{
	int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
	int len = sizeof(arr) / sizeof(arr[0]);
	bubblesort(arr, len);
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << ",";
	}
	cout << endl;
	return 0;
}

七、结构体

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

7.1、结构体定义和使用

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

 创建一个学生的数据类型:

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

struct Student 
{
	string name;
	int age;
	float score;
} s3={"lele",18,90.6};

typedef struct Student Student;//取别名

int main()
{
	//创建学生结构体三种方法
	Student s1;
	s1.age = 19;
	s1.name = "lihua";
	s1.score = 34.5;
	cout << s1.age << endl;
	cout << s1.name << endl;
	cout << s1.score << endl;
	Student s2 = { "lili",18,90.5 };
	cout << s2.age << endl;
	cout << s2.name << endl;
	cout << s2.score << endl;
	cout << s3.age << endl;
	cout << s3.name << endl;
	cout << s3.score << endl;
	return 0;
}

7.2、结构体数组

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

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

7.3、结构体指针

通过结构体指针访问结构体中的成员。

利用操作符->访问结构体成员。

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

struct Student
{
	string name;
	int age;
	float score;
};

typedef struct Student Student;//取别名

int main()
{
	Student s2 = { "lili",18,90.5 };
	Student* ps = &s2;
	cout << ps->age << endl;
	cout <<ps->name << endl;
	cout << ps->score << endl;
	return 0;
}

7.4、结构体嵌套结构体

结构体的成员可以是另一个结构体。

举例:老师辅导一个学员,老师结构体中记录学生信息。

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

struct Student
{
	string name;
	int age;
	float score;
};
struct teacher
{
	int id;
	string name;
	int age;
	Student stu;//辅导的学生,应该定义在定义老师之前
};

int main()
{
	teacher t;
	t.age = 40;
	t.id = 110;
	t.name = "wang wang";
	t.stu.age = 18;
	t.stu.name = "lili";
	t.stu.score = 90.5;
	cout << t.name << endl;
	cout <<t.age << endl;
	cout << t.id << endl;
	cout << t.stu.name << endl;
	cout << t.stu.age << endl;
	cout << t.stu.score << endl;
	return 0;
}

7.5、结构体作为函数参数

将结构体作为参数向函数传递,也分为值传递和地址传递两种。

7.6、结构体中const使用场景

作用:用const防止误操作。

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

struct Student
{
	string name;
	int age;
	float score;
};

void printstudent(const Student *p)//加入const后,一旦有修改操作就会报错,给函数设置只读
{
	cout << p->name << endl;
	cout << p->age << endl;
	cout << p->score << endl;
}

int main()
{
	Student s = { "lili",15,90.5 };
	printstudent(&s);
	return 0;
}

7.7结构体案例

案例一:

1个老师带5个学生,一共3名老师,需求如下:

设计学生和老师的结构体,在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员。

学生的成员有姓名,考试分数。

创建数组存放3名老师,通过函数给每个老师及其所带的学生赋值。最终打印出老师数据和老师所带学生数据。

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

struct student
{
	string sname;
	float score;
};

struct teacher
{
	string tname;
	student stuArray[5];
};

//输入学生信息
void allocateSpace(teacher* tArray, int len);
//打印老师和学生信息
void printteachers(const teacher* tArray, int len);

int main()
{
	//生成随机数种子
	srand((unsigned int)time(NULL));
	teacher teaArr[3];
	int len = sizeof(teaArr) / sizeof(teaArr[0]);
	allocateSpace(teaArr, len);
	printteachers(teaArr, len);
	return 0;
}

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].stuArray[j].sname = "Student_";
			tArray[i].stuArray[j].sname += nameSeed[j];
			int random = rand() % 61 + 40;//40-100的随机数
			tArray[i].stuArray[j].score = random;
		}
	}
}

void printteachers(const 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].stuArray[j].sname <<
				" 考试分数:" << tArray[i].stuArray[j].score << endl;
		}
	}
}

案例二:

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

五名英雄的信息如下:

{“刘备”,23,"男"},

{"关羽",22,"男"},

{"张飞",20,"男"},

{"赵云",21,"男"},

{"貂蝉",19,"女"},

#include<iostream>
#include<string>

using namespace std;

//创建英雄的结构体
struct hero
{
	string name;
	int age;
	string sex;
};

//冒泡排序
void bubblesort(hero* heroArray, int len);
//打印输出
void printhero(hero* heroArray, int len);

int main()
{
	hero heroArray[5] =
	{
		{"刘备",23,"男"},

		{"关羽",22,"男"},

		{"张飞",20,"男"},

		{"赵云",21,"男"},

		{"貂蝉",19,"女"}
	};
	int len = sizeof(heroArray) / sizeof(heroArray[0]);
	cout << "排序前打印:" << endl;
	printhero(heroArray, len);
	bubblesort(heroArray, len);
	cout << "排序后打印:" << endl;
	printhero(heroArray, len);
	return 0;
}

//冒泡排序
void bubblesort(hero* heroArray, int len)
{
	hero temp;
	for (int i = len - 1; i > 0; i--)
	{
		for (int j = 0; j < i; j++)
		{
			if (heroArray[j].age > heroArray[j + 1].age)
			{
				temp = heroArray[j];
				heroArray[j] = heroArray[j + 1];
				heroArray[j + 1] = temp;
			}
		}
	}
}
//打印输出
void printhero(hero* heroArray, int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << "英雄" << heroArray[i].name << "的年龄是" << heroArray[i].age <<
			" ,性别是:" << heroArray[i].sex << endl;
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值