结构体中套二级指针

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

typedef struct Teacher
{
	char name[64];    // 在用结构体类型定义变量的时候就已经分配了这64个字节
	char *pAlisname;  // 一级指针    只是分配了4个字节
	char **stuName;     // 二级指针   学生的名字
	int age;
}Teacher;

// 数组做函数参数会退化为指针
void printTeacher(Teacher *array, int num)
{
	int i = 0;
	for (i = 0; i < num; i++)
	{
		printf("age : %d \n", array[i].age);
	}
}


void sortTeacher(Teacher *array, int num)
{
	int i, j;
	Teacher tmp;
	for (i = 0; i < num; i++)
	{
		for (j = 0; j < num; j++)
		{
			if (array[i].age > array[j].age)
			{
				tmp = array[i];
				array[i] = array[j];
				array[j] = tmp;
			}
		}
	}
}




int createTeacher(Teacher **pTeacher, int num)
{
	int i = 0, j = 0;
	Teacher *tmp;
	tmp = (Teacher *)malloc(sizeof(Teacher) * num);
	if (tmp == NULL)
	{
		return -1;
	}
	memset(tmp, 0, sizeof(Teacher) * num);
	for (i = 0; i < num; i++)
	{
		char **p = NULL;
		// 每一个节点都要挂内存
		// 对结构体嵌套的一级指针显示地分配内存   一级指针
		(tmp + i)->pAlisname = (char *)malloc(60);
		// 自己打造二维内存空间    --  二级指针的第三种内存模型
		{
			p = (char **)malloc(sizeof(char *) * 3);
			for (j = 0; j < 3; j++)
			{
				p[j] = (char *)malloc(120);  // 要注意 i 跟 j
			}
			(tmp + i)->stuName = p;  // 挂到当前老师
		}
	}
	*pTeacher = tmp;
	return 0;
}





void FreeTeacher(Teacher *p, int num)
{
	int i = 0, j = 0;
	if (p == NULL)
	{
		return;
	}
	for (i = 0; i < num; i++)
	{

		// 释放一级指针
		if (p[i].pAlisname != NULL)
		{
			free(p[i].pAlisname);
		}
		// 释放二级指针
		if (p[i].stuName != NULL)
		{
			char **pS = p[i].stuName;
			for (j = 0; j < 3; j++)
			{
				if (pS[j] != NULL)
				{
					free(pS[j]);
				}
			}
			free(pS);
			p[i].stuName = NULL;
		}
	}
	free(p);
}




void main()
{
	int i = 0, j = 0, ret = 0;
	int num = 3;
	Teacher *pArray = NULL;
	ret = createTeacher(&pArray, 3);
	if (ret == -1)
	{
		printf("func createTeacher() err : %d\n", ret);
		return;
	}
	for (i = 0; i < 3; i++)
	{
		printf("\n please enter age: ");
		// scanf("%d", &((pArray + i)->age));
		scanf("%d", &(pArray[i].age));   // 这种写法也可以
		// scanf("%d", &(pArray->age));   // 错误的写法

		printf("\n please enter name: ");
		// 向指针所指向的内存空间拷贝数据
		scanf("%s", (pArray + i)->name);  // name本身是数组的首地址

		printf("\n please enter alisname: ");
		// 向指针所指向的内存空间拷贝数据
		scanf("%s", (pArray + i)->pAlisname);

		for (j = 0; j < 3; j++)
		{
			printf("\n please students name: ");
			scanf("%s", pArray[i].stuName[j]);
		}

	}
	// 打印老师的年龄
	printf("排序前+- : \n");
	printTeacher(pArray, 3);
	sortTeacher(pArray, 3);
	printf("排序后+- : \n");
	printTeacher(pArray, 3);

	FreeTeacher(pArray, 3);
	system("pause");

}

结构体中套二级指针_第1张图片

改进的程序:
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 


typedef struct Teacher
{
	char name[64];	// 在用结构体类型定义变量的时候就已经分配了这64个字节
	char *pAliasName;	// 一级指针  只分配了4个字节
	char **stuName;		// 二级指针  学生的名字
	int age;
}Teacher;


int createTeachers(Teacher **pTeachers, int num)
{
	int ret = 0, i = 0, j = 0;
	Teacher *tmpTeachers;
	tmpTeachers = (Teacher *)malloc(sizeof(Teacher) * num);
	if (tmpTeachers == NULL)
	{
		ret = -1;
		printf("func createTeachers() err %d : malloc(sizeof(Teacher) * num)", ret);
		goto END;
	}
	memset(tmpTeachers, 0, sizeof(Teacher) * num );
	for (i = 0; i < num; i++)
	{
		char **p = NULL;
		// 每一个老师都有一个一级指针pAliasName
		tmpTeachers[i].pAliasName = (char *)malloc(60);
		if (tmpTeachers[i].pAliasName == NULL)
		{
			ret = -2;
			printf("func createTeachers() err : %d (char *)malloc(60)", ret);
			goto END;
		}
		// 每一个老师下面都有三个学生,这是二级指针
		// 自己打造内存模型
		p = (char **)malloc(sizeof(char *) * 3);
		for (j = 0; j < 3; j++)
		{
			p[j] = (char *)malloc(120);
		}
		tmpTeachers[i].stuName = p;  // 将二级指针挂在当前老师
	}



END:
	if (ret != 0)  // 失败
	{
		int i = 0, j = 0;
		if (tmpTeachers == NULL)
		{
			return ret;
		}
		// tmpTeachers 分配了内存
		for (i = 0; i < num; i++)
		{
			if (tmpTeachers[i].pAliasName != NULL)
			{
				// 释放一级指指针前要将有二级指针的先释放掉
				for (j = 0; j < num; j++)
				{
					if (tmpTeachers[i].stuName[j] != NULL)
					{
						free(tmpTeachers[i].stuName[j]);
					}
				}
				// 有二级指针的都释放完了二级指针  一级指针就出错了的,不释放
				// 然后再释放一级指针
				free(tmpTeachers[i].pAliasName);
			}
		}
		// 释放掉了所有的资源  然后再释放pTeachers
		free(tmpTeachers);
	}
	else
	{
		*pTeachers = tmpTeachers;
		return ret;
	}


}

// 打印
void printTeachers(Teacher *pTeachers, int num)
{
	int i = 0, j = 0;
	for (i = 0; i < num; i++)
	{
		// 打印老师的name
		printf("name : %s \n", pTeachers[i].name);
		printf("alisName : %s \n", pTeachers[i].pAliasName);
		printf("age : %d \n", pTeachers[i].age);
		printf("---------students--------- \n");
		for (j = 0; j < num; j++)
		{
			printf("%s \n", pTeachers[i].stuName[j]);
		}
		printf("--------------------------\n");
	}

}

// 根据年龄排序
void sortTeachers(Teacher *pTeachers, int num)
{
	int i = 0, j = 0;
	Teacher tmpTeacher;
	for (i = 0; i < num; i++)
	{
		for (j = 0; j < num; j++)
		{
			if (pTeachers[i].age > pTeachers[j].age)
			{
				tmpTeacher = pTeachers[i];
				pTeachers[i] = pTeachers[j];
				pTeachers[j] = tmpTeacher;
			}
		}
	}
}



void FreeTeacher(Teacher *pTeachers, int num) 
{
	int i = 0, j = 0;
	if (pTeachers == NULL)
	{
		return;
	}
	for (i = 0; i < num; i++)
	{
		// 释放一级指针
		if (pTeachers[i].pAliasName != NULL)
		{
			free(pTeachers[i].pAliasName);
		}
		// 释放二级指针
		if (pTeachers[i].stuName != NULL)
		{
			char **pStuName = pTeachers[i].stuName;
			for (j = 0; j <3; j++)
			{
				if (pStuName[j] != NULL)
				{
					free(pStuName[j]);
				}
			}
			free(pStuName);
			pTeachers[i].stuName = NULL;
		}
	}
	free(pTeachers);
}


void main()
{
	int ret = 0, num = 3;
	int i = 0, j = 0;

	Teacher *pTeachers = NULL;
	ret = createTeachers(&pTeachers, num);
	if (ret != 0)
	{
		printf("func createTeachers() err : %d", ret);
		return;
	}

	// 键盘输入
	for (i = 0; i < 3; i++)
	{
		// 输入老师的名字
		printf("\n please enter name : ");
		scanf("%s", pTeachers[i].name);  // 注意: 不要加& 因为name本身就是数组的首地址

		// 输入老师的别名
		printf("\n please enter alisName : ");
		scanf("%s", pTeachers[i].pAliasName);  // 注意不要加& 否则变成二级指针了

		// 输入老师的年龄
		printf("\n please enter age : ");
		scanf("%d", &(pTeachers[i].age));

		// 输入学生的名字
		for (j = 0; j < 3; j++)
		{
			printf("\n please enter students name : ");
			// stuName 本身是一个二级指针
			scanf("%s", pTeachers[i].stuName[j]);
		}
	}

	printf("排序前 : \n");
	// 打印
	printTeachers(pTeachers, 3);

	// 排序
	sortTeachers(pTeachers, 3);
	printf("排序后 : \n");
	// 打印
	printTeachers(pTeachers, 3);


	// 释放内存
	FreeTeacher(pTeachers, 3);
	system("pause");
	return;
}

你可能感兴趣的:(结构体)