#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");
}
改进的程序:
#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;
}