学生信息管理系统(通讯录)----------通俗易懂、附源码、C语言实现

绪论:

本篇文章使结构体章节后的习题,如果你对C语言有问题,或者结构体有什么问题不妨看看我之前所写的文章(章回体),对于文件管理(已补上)和动态内存分配问题(已补上)我将在后面补上,对于这个学生信息管理系统我用了多种方法和分源管理的形式来写可能内容偏多,但都有着重大意义,可以自行对我的源码进行copy和删减一些用了多种方法的地方,当然直接用也是没什么问题的。

附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要

思维导图

要XMind思维导图的话可以私信哈

目录

1.界面的创建、和功能的选择

2.功能的实现

        2.1动态内存管理:

3.文件的保存、和文件的调用


补充:

对于分源管理:这样做的原因是可以将这个程序的实现,分开来实现,主函数放在了test.c中这里就像一个枢纽(主干)来选择功能,而contact.c 中放着的是这些主干后的分支(他代表着所要实现的功能的具体代码),而contact.h(头文件)这里存放着一些在test.c 和 contact.c 同时需要用到的东西,如头文件的应用、#define 定义的常量 、以及函数的声明 、这样只需在.c(源文件)中引用#include"contact" 即可包含该文件中的内容

如果不想分源也可以写在一个源文件内,只要把函数、以及结构体和头文件拷贝到一个test.c文件中即可

下面先上源码:

test.c:

 #define _CRT_SECURE_NO_WARNINGS 1

#include"contact.h"

enum function
{
	Exit ,
	Add,
	Del,
	Search,
	Modeify,
	Show,
	Sort,
	Refresh
};


void menu()
{
	printf("********************************\n");
	printf("********************************\n");
	printf("*****    1. Add  2.Del     *****\n");
	printf("********************************\n");
	printf("*****  3.Search  4.Modeify *****\n");
	printf("********************************\n");
	printf("*****   5.Show   6.Sort    *****\n");
	printf("********************************\n");
	printf("*****  7.refresh    0.exit *****\n");
	printf("********************************\n");
	printf("********************************\n");
}

int main()
{
	int input = 0;

	Info_System con ;
//初始化
	InitCon(&con);
	//初始化方法二:Info_System con = {0};直接将全部置成0
	do
	{
		menu();
		printf("请选择>:");
		scanf("%d", &input);

		switch(input)
		{
		case Add:
			Add_Stu_message(&con);
			break;
		case Del:
			Del_Stu_message(&con);
			break;
		case Search:
			Search_Stu_message(&con);
			break;
		case Modeify:
			Modeifyh_Stu_message(&con);
			break;
		case Show:
			Show_Stu_message(&con);
			break;
		case Sort:
			Sort_Stu_message(&con);
			break;
		case Refresh:
			Refresh_Stu_message(&con);
			break;
		case Exit:
			//保存文件
			SaveContact(&con);
			DestroyContact(&con);
			printf("退出\n");

			break;
		default:
			printf("选择错误,重新选择:\n");
			break;
		}


	} while (input);

	return 0;
}

contact.h:

#pragma once

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>


#define Name_Max 20
#define Sex_Max 5
#define Class_Max 20
#define Room_Max 20

#define PeoMax 100


#define InitPeo 3
#define AddCap 2

typedef struct PeoInfo//学生信息
{
	int ID;// 学号
	char Name[Name_Max];// 姓名
	char Sex[Sex_Max];// 性别
	char Class[Class_Max];// 班级
	char Room[Room_Max];// 宿舍号
	int Score;// 成绩

}PeoInfo;
//
//typedef struct management_System
//{
//
//	PeoInfo Contact[PeoMax];//存放人的信息
//	int sz;//已近存放了多少个人
//}Info_System;

typedef struct management_System
{

	PeoInfo* Contact;//存放人的信息
	int sz;//已近存放了多少个人
	int capacity;//容量大小

}Info_System;


void InitCon(Info_System *con);

void Add_Stu_message(Info_System* con);

void Show_Stu_message(const Info_System* con);

void Del_Stu_message (Info_System* con);

void Search_Stu_message(const Info_System* con);

void Modeifyh_Stu_message(Info_System* con);

void Sort_Stu_message(Info_System* con);

void Refresh_Stu_message(Info_System* con);

void DestroyContact(Info_System* con);


//保存文件
void SaveContact(Info_System*  con);

//加载文件
void LoadContact(Info_System* pc);

contact.c:

 #define _CRT_SECURE_NO_WARNINGS 1

#include"contact.h"


void AddCapacity(Info_System* con)
{
	assert(con);
	PeoInfo* ptr = (PeoInfo*)realloc(con->Contact,sizeof(PeoInfo) * (AddCap+ con->capacity));
	if (ptr == NULL)
	{
		perror("realloc");

		return ;
	}
	con->Contact = ptr;
	con->capacity += AddCap;

	ptr = NULL;
	printf("增容成功\n");
}

void LoadContact(Info_System* pc)
{
	//读数据
	//1. 打开文件
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadContact");
	}
	else
	{
		//2. 读数据
		PeoInfo tmp = { 0 };
		int i = 0;
		while (fread(&tmp, sizeof(PeoInfo), 1, pf))//用fread先读到临时变量tmp内
		{
			//增容
			Check_Capacity(pc);
			pc->Contact[i] = tmp;//把tmp内的文件取进来
			pc->sz++;//增加人数
			i++;
		}
		fclose(pf);//关闭文件
		pf = NULL;
	}
}


void InitCon(Info_System* con)
{
	Refresh_Stu_message(con);

	LoadContact(con);
}


//初始化
//void InitCon(Info_System* con)
//{
//	assert(con);
//	con->sz = 0;
//	memset(con->Contact, 0, sizeof(Info_System));//利用memset将一块连续的空间初始化成0最后
//要初始化多少个字节
//}

int FindById(int Id, const Info_System* con)
{
	int t = con->sz;//不要改变sz,用t来代替需要查找的人
	while (t--)
	{
		if (Id == con->Contact[t].ID)
		{
			return t;
		}
	}
	printf("找不到此人\n");
	return -1 ;//返回-1是因为区别于返回0(返回0表示查找的人的下标为0)
}
int FindByName(char * name,const Info_System* con)
{
	int t = con->sz;//不要改变sz,用t来代替需要查找的人
	while (t--)
	{
		if (strcmp(name, con->Contact[t].Name) == 0)//--ret 是因为ret表示的是总人数,而总人数-1才能找到最后一个人
		{
			return t;
		}

	}
	printf("找不到此人\n");

	return -1;//返回-1是因为区别于返回0(返回0表示查找的人的下标为0)
}

//增加
void Add_Stu_message(Info_System* con)
{
	assert(con);
	if (con->sz == PeoMax)
	{
		AddCapacity(con);
	}
	printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");
	scanf("%d %s %s %s %s %d", &con->Contact[con->sz].ID,
		con->Contact[con->sz].Name,
		con->Contact[con->sz].Class,
		con->Contact[con->sz].Sex,
		con->Contact[con->sz].Room,
		&con->Contact[con->sz].Score
	);
	con->sz += 1;
	//con->sz++;
	printf("添加完成\n");
}


void Show_Stu_message(const Info_System* con)
{
	assert(con);

	printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");
	for (int i = 0; i < con->sz;i++)//解引用操作符的优先级都很(最)高
	{
		printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[i].ID,
			con->Contact[i].Name,
			con->Contact[i].Class,
			con->Contact[i].Sex,
			con->Contact[i].Room,
			con->Contact[i].Score);
	}

}


void Del_Stu_message(Info_System* con)
{
	assert(con);
	if (con->sz == 0)
	{
		printf("没有学生信息\n");
		return;
	}
	int input = 0;
	printf("输入学号进行删除;>");
	scanf("%d", &input);
	int ret = FindById(input,con);
	if (ret != -1)
	{
		for (ret; ret < con-> sz - 1; ret++) //sz -1 也要转化成下标
		{
			con->Contact[ret] = con->Contact[ret+1]; //注意返回的就是所对应的下标
		}
		con->sz--;
		printf("删除成功\n");
	}
	//if (ret!=-1)
	//{
	//	memmove(con->Contact + ret, con->Contact + ret + 1, (con->sz)*sizeof(PeoInfo) - (ret) * sizeof(PeoInfo));
	//	con->sz--;
	//	printf("删除成功\n");
	//}

}


void Search_Stu_message(const Info_System* con)
{
	assert(con);
	int i = 0;
	printf("1.Id\n2.Name\n选择查找方法:>");
	scanf("%d", &i);
	if (i == 1)
	{
		int input = 0;

		printf("输入学号进行查找:>");
		scanf("%d", &input);
		int ret = FindById(input, con);
		if (ret != -1)
		{
			printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");

			printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				con->Contact[ret].Score);
		}
	}
	else if (i == 2)
	{
		char name[20] = { 0 };
		printf("输入姓名进行查找:>");
		scanf("%s",name);
		int ret = FindByName(name, con);
		
		if (ret != -1)
		{
			printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");

			printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				con->Contact[ret].Score);
		}
	}

	else
	{
		printf("选择错误\n");
	}
	

}


void Modeifyh_Stu_message(Info_System* con)
{
	assert(con);
	int i = 0;
	printf("1.Id\n2.Name\n选择查找方法:>");
	scanf("%d", &i);
	if (i == 1)
	{
		int input = 0;

		printf("输入要修改的学生信息的学号:>");
		scanf("%d", &input);
		int ret = FindById(input, con);
		if (ret != -1)
		{
			printf("修改:>\n");
			printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");
			scanf("%d %s %s %s %s %d", &con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				&con->Contact[ret].Score
			);

			printf("修改完成\n");
		}
	}
	else if (i == 2)
	{
		char name[20] = { 0 };
		printf("输入要修改的学生信息的姓名:>");
		scanf("%s", name);
		int ret = FindByName(name, con);

		if (ret != -1)
		{
			printf("修改:>\n");
			printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");
			scanf("%d %s %s %s %s %d", &con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				&con->Contact[ret].Score
			);
			printf("修改完成\n");

		}
	}

	else
	{
		printf("选择错误\n");
	}
}

int Sort_Name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->Name, ((PeoInfo*)e2)->Name);

}

int Sort_age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e1)->ID  - ((PeoInfo*)e2)->ID;
}
void Sort_Stu_message(Info_System* con)
{
	assert(con);
	int input = 0;
	printf("1.以名字排序\n2.以学号排序\n");
	scanf("%d", &input);
	switch (input)
	{
	case 1:

		qsort(con->Contact, con->sz, sizeof(con->Contact[0]), Sort_Name);

		printf("排序成功\n");

		break;
	case 2:

		qsort(con->Contact, con->sz, sizeof(con->Contact[0]), Sort_age);
		printf("排序成功\n");
		break;
	default:
		printf("输入错误\n");
		break;
	}
}

void Refresh_Stu_message(Info_System* con)
{
	InitCon(con);
	printf("刷新成功\n");
}



void DestroyContact(Info_System* con)
{
	free(con->Contact);
	con->Contact = NULL;

	con->capacity = 0;
	con->sz = 0;
	con = NULL;
}

void SaveContact(Info_System* con)
{
	FILE* pf = fopen("contact.txt","wb");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		fwrite(con->Contact + i, sizeof(PeoInfo), 1, pf);
	}
	
	fclose(pf);
	pf = NULL;

}



1.界面的创建、和功能的选择

创建目录(界面):

在main函数内创建一个目录函数

int main()
{
	menu();
    retrn 0;
}

直接通过打印的方法,打印出自己所想要的目录(界面)

创建选择功能:

通过dowhile循环来不断的进行选择并且通过switch语句来控制所选择功能,并且通过枚举变量来实现。

int main()
{
	int input = 0;
	do
	{
		printf("请选择>:");
		scanf("%d", &input);
		switch(input)
		{
		case Add:
			Add_Stu_message(&con);
			break;
		case Del:
			Del_Stu_message(&con);
			break;
		case Search:
			Search_Stu_message(&con);
			break;
		case Modeify:
			Modeifyh_Stu_message(&con);
			break;
		case Show:
			Show_Stu_message(&con);
			break;
		case Sort:
			Sort_Stu_message(&con);
			break;
		case Refresh:
			Refresh_Stu_message(&con);
			break;
		case Exit:
			printf("退出\n");
			break;
		default:
			printf("选择错误,重新选择:\n");
			break;
		}
	} while (input);
	return 0;
}

初始化学生信息:

对于已经创建好的结构体,他们此时还是一些随机值需要初始化

所以写一个初始化函数来进行初始化

void InitCon(Info_System* con)
{
	assert(con);
	con->sz = 0;
	memset(con->Contact, 0, sizeof(Info_System));//利用memset将一块连续的空间初始化成0最后要初始化多少个字节
}

其中有到了memset来直接对其初始化:

第一个元素放目标地址,第二个元素表示要放东西的整形形式(如0 -> 0 ;而 'a' -> 97),第三个元素表示这个目标的大小(byte),具体用法可以看这篇博客:进阶C语言第三章-------《字符函数和内存函数》 完整思维导图+基本练习题+深入细节+通俗易懂+知识点+建议收藏_溟洵的博客-CSDN博客


2.功能的实现

添加学生信息:

对于下面的scanf操作的解释:

        我们需要引用并且存进结构体中而对于数组来说不需要加上& (因为其数组名表示其地址 而对于整形就需要&了)
        先从con通过->访问其里面的成员Contact  而其又是PeoInfo结构体的数组变量所以就可以通过访问数组空间 再用.操作符来找到学生的信息(这里不用-> 是因为前面con->Contact[con->sz] 已经表示成Contact[PeoMax]结构体变量了不需要在*解引用了 )

void Add_Stu_message(Info_System* con)
{
assert(con);
if (con->sz == PeoMax)
{
	printf("信息已满,请删除或刷新后再试\n");
	return;
}
printf("依次输入%s %s %s %s %s %s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");
scanf("%d %s %s %s %s %d",                  
&con->Contact[con->sz].ID,                                            
con->Contact[con->sz].Name,                             
con->Contact[con->sz].Class,                             
con->Contact[con->sz].Sex,                                
con->Contact[con->sz].Room,                          
&con->Contact[con->sz].Score
);
printf("添加完成\n");
}

展示学生信息:

void Show_Stu_message(Info_System* con)
{
	assert(con);
	printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");
	for (int i = 0; i < con->sz;i++)
		{
			printf("%-10d %-20s %-20s %-5s %-20s %-10d\n",
			 con->Contact[i].ID,
			con->Contact[i].Name,
			con->Contact[i].Class,
			con->Contact[i].Sex,
			con->Contact[i].Room,
			con->Contact[i].Score
			);
		}
}

对于printf打印只需要满足所给条件(%d)和所写条件(con->Contact[i].ID)对应的类型一致即可。


删除学生信息:


void Del_Stu_message(Info_System* con)
{
	assert(con);
	if (con->sz == 0)
	{
		printf("没有学生信息\n");
		return;
	}
	int input = 0;
	printf("输入学号进行删除;>");
	scanf("%d", &input);
	int ret = FindById(input,con);
	if (ret != -1)
	{
		for (ret; ret < con-> sz - 1; ret++) //sz -1 也要转化成下标
		{
			con->Contact[ret] = con->Contact[ret+1]; //注意返回的就是所对应的下标
		}
		con->sz--;
		printf("删除成功\n");
	}
	//if (ret!=-1)
	//{
	//	memmove(con->Contact + ret, con->Contact + ret + 1, (con->sz)*sizeof(PeoInfo) - (ret) * sizeof(PeoInfo));
	//	con->sz--;
	//	printf("删除成功\n");
	//}

}

 查找学生信息

void Search_Stu_message(const Info_System* con)
{
	assert(con);
	int i = 0;
	printf("1.Id\n2.Name\n选择查找方法:>");
	scanf("%d", &i);
	if (i == 1)
	{
		int input = 0;

		printf("输入学号进行查找:>");
		scanf("%d", &input);
		int ret = FindById(input, con);
		if (ret != -1)
		{
			printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");

			printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				con->Contact[ret].Score);
		}
	}
	else if (i == 2)
	{
		char name[20] = { 0 };
		printf("输入姓名进行查找:>");
		scanf("%s",name);
		int ret = FindByName(name, con);
		
		if (ret != -1)
		{
			printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");

			printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				con->Contact[ret].Score);
		}
	}

	else
	{
		printf("选择错误\n");
	}
	

}

查找学生的函数:

int FindByName(char * name,const Info_System* con)
{
	int t = con->sz;//不要改变sz,用t来代替需要查找的人
	while (t--)
	{
		if (strcmp(name, con->Contact[t].Name) == 0)//--ret 是因为ret表示的是总人数,而总人数-1才能找到最后一个人
		{
			return t;
		}

	}
	printf("找不到此人\n");

	return -1;//返回-1是因为区别于返回0(返回0表示查找的人的下标为0)
}
int FindById(int Id, const Info_System* con)
{
	int t = con->sz;//不要改变sz,用t来代替需要查找的人
	while (t--)
	{
		if (Id == con->Contact[t].ID)
		{
			return t;
		}
	}
	printf("找不到此人\n");
	return -1 ;//返回-1是因为区别于返回0(返回0表示查找的人的下标为0)
}

修改学生信息

void Modeifyh_Stu_message(Info_System* con)
{

	int i = 0;
	printf("1.Id\n2.Name\n选择查找方法:>");
	scanf("%d", &i);
	if (i == 1)
	{
		int input = 0;

		printf("输入要修改的学生信息的学号:>");
		scanf("%d", &input);
		int ret = FindById(input, con);
		if (ret != -1)
		{
			printf("原信息:\n%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");

			printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				con->Contact[ret].Score);
			

			printf("修改:>\n");
			printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");
			scanf("%d %s %s %s %s %d", &con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				&con->Contact[ret].Score
			);


		}
	}
	else if (i == 2)
	{
		char name[20] = { 0 };
		printf("输入要修改的学生信息的姓名:>");
		scanf("%s", name);
		int ret = FindByName(name, con);

		if (ret != -1)
		{
			printf("原信息:\n%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");

			printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				con->Contact[ret].Score);


			printf("修改:>\n");
			printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");
			scanf("%d %s %s %s %s %d", &con->Contact[ret].ID,
				con->Contact[ret].Name,
				con->Contact[ret].Class,
				con->Contact[ret].Sex,
				con->Contact[ret].Room,
				&con->Contact[ret].Score
			);
		}
	}

	else
	{
		printf("选择错误\n");
	}
}

 排序学生信息

int Sort_Name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->Name, ((PeoInfo*)e2)->Name);
	//注意强转要写成 PeoInfo* 结构体类型
	//返回大于0的数才交换,即是升序形式
}

int Sort_age(const void* e1, const void* e2)
{
	return ((PeoInfo*)e1)->ID  - ((PeoInfo*)e2)->ID;
}
void Sort_Stu_message(Info_System* con)
{
	assert(con);
	int input = 0;
	printf("1.以名字排序\n2.以学号排序\n");
	scanf("%d", &input);
	switch (input)
	{
	case 1:
		//ASCII升序
		qsort(con->Contact, con->sz, sizeof(con->Contact[0]), Sort_Name);//头文件stdlib,比较函数int compare(const void *elem1, const void *elem2)
		//此处con->Contact 直接找到了数组名传进去,所以qsort内所接受到的结构体时PeoInfo类型的

		printf("排序成功\n");

		break;
	case 2:
		//升序
		qsort(con->Contact, con->sz, sizeof(con->Contact[0]), Sort_age);
		printf("排序成功\n");
		break;
	default:
		printf("输入错误\n");
		break;
	}
}

刷新学生信息

void Refresh_Stu_message(Info_System* con)
{
	InitCon(con);//直接再次调用初始化函数
	printf("刷新成功\n");
}

动态内存管理:

对于动态内存来说,他所要修改的地方是空间的开辟问题,对此我们

1. 首先需要重新定义一下结构体:来知道容量的大小来确保容量的够用

//静态的
//typedef struct management_System
//{
//
//	PeoInfo Contact[PeoMax];//存放人的信息
//	int sz;//已近存放了多少个人
//}Info_System;

//动态的
typedef struct management_System
{

	PeoInfo* Contact;//存放人的信息
	int sz;//已近存放了多少个人
	int capacity;//容量大小

}Info_System;

2. 对此还需要再定义两个常量,来定义起始人数和后面容量不够时每次增加的容量

#define InitPeo 3
#define AddCap 2

(用#define定义是因为这样当你需要对程序进行修改时就可以直接在此处修改,而不要跑到代码内一处处的修改)

3. 因为是动态的所以我们还要修改一下Add函数当进行增加人数时应该判断一下所开辟的空间是否够(通过AddCapacity函数来增容)

void AddCapacity(Info_System* con)
{
	assert(con);
	PeoInfo* ptr = (PeoInfo*)realloc(con->Contact,sizeof(PeoInfo) * (AddCap+ con->capacity));
	if (ptr == NULL)
	{
		perror("realloc");

		return ;
	}
	con->Contact = ptr;
	con->capacity += AddCap;

	ptr = NULL;

}

void Add_Stu_message(Info_System* con)
{
	assert(con);
	if (con->sz == con->capacity)
	{
		AddCapacity(con);
	}
    printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");
	scanf("%d %s %s %s %s %d", &con->Contact[con->sz].ID,
		con->Contact[con->sz].Name,
		con->Contact[con->sz].Class,
		con->Contact[con->sz].Sex,
		con->Contact[con->sz].Room,
		&con->Contact[con->sz].Score
	);
	con->sz += 1;
	//con->sz++;
	printf("添加完成\n");
}

4. 当我们退出程序时还应该将所借的空间归还给操作系统

//contact.c

void DestroyContact(Info_System* con)
{
	free(con->Contact);
	con->Contact = NULL;

	con->capacity = 0;
	con->sz = 0;
	con = NULL;

}

//contact.h

void DestroyContact(Info_System* con);

//test.c
...
case Exit:
	DestroyContact(&con);
	printf("退出\n");
    break;
...

3.文件的保存、和文件的调用

所要修改的地方:

1. 我们需要把学生信息管理系统的初始化(InitCon),此时我们需要把原本(改变学生人数、对信息初始化)换成文件版,此时我们可以先进行加载把之前写过的信息加载进来、以及初始化一些基础信息,具体如下:


void LoadContact(Info_System* pc)
{
	//读数据
	//1. 打开文件
	FILE* pf = fopen("contact.txt", "rb");//以二进制的方式读入、后面存同样也是二进制
	if (pf == NULL)
	{
		perror("LoadContact");
	}
	else
	{
		//2. 读数据
		PeoInfo tmp = { 0 };
		int i = 0;
		while (fread(&tmp, sizeof(PeoInfo), 1, pf))//用fread先读到临时变量tmp内
		{
			//增容
			Check_Capacity(pc);
			pc->Contact[i] = tmp;//把tmp内的文件取进来
			pc->sz++;//增加人数
			i++;
		}
		fclose(pf);//关闭文件
		pf = NULL;
	}
}

void InitCon(Info_System* con)
{
	Refresh_Stu_message(con);

	LoadContact(con);
}

void Refresh_Stu_message(Info_System* con)
{
	assert(con);
	con->sz = 0;
	con->capacity = InitPeo;
	PeoInfo* ptr = (PeoInfo*)malloc(sizeof(PeoInfo) * InitPeo);//为学生信息先开辟一定大小的空间
	if (ptr == NULL)
	{
		perror("malloc");
		return;
	}
	con->Contact = ptr;
	ptr = NULL;
	memset(con->Contact, 0, sizeof(PeoInfo) * InitPeo);
}

2.  当我们写完数据后我们需要将这些数据进行保存,并且保存到文件中


void SaveContact(Info_System* con)
{
	FILE* pf = fopen("contact.txt","wb");//以写的方法
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	int i = 0;
	for (i = 0; i < con->sz; i++)
	{
		fwrite(con->Contact + i, sizeof(PeoInfo), 1, pf);//将数据一一的从con->contact+i中获取后存进文件pf中
	}
	
	fclose(pf);//关闭
	pf = NULL;

}

持续更新大量C语言知识,关注喔老铁!
 

设计一个《学生通讯录管理系统》,在动态链表程序的基础上,设计要求如下 (必须使用结构体和链表等数据结构) 1建立文件 存储文件使用指定文件名或默认文件名; 可以不保存输入记录,但需要确认是否保存输入记录 如果已有文件,只能在其后追加; 新增记录可以不存入原文件中,以可以用原来的文件覆盖内存的内容; 可以将多个个文件记录合并到一个文件中; 2文件的存取和显示 可以单独存取文件; 可以随时显示内存中记录的全部内容; 可以直接存取默认文件或指定文件; 3删除记录 可以按“姓名”或“电话”方式删除记录并更新内存链表内容; 能给出被删除的信息,输出没有找到的信息; 如果已经是空表,上出时应给出信息并返回主菜单; 如果没有要删除的信息,输出没有找到的信息; 删除操作仅限于内存,只有执行记录时,才能覆盖原记录; 4查询记录 可以按“姓名”或“电话”或“宿舍”方式查询记录 能给出查询记录的信息; 如果查询的信息不存在,输出没有找到的信息; 5 整体功能 a可以随时检索、删除、或增加新记录,保存或取消新的记录 b使姓名可由16位字符和数字的混合编码组成 c使电话号码可由18位字符和数字组成 d将输出信息加上输出信息信息栏,例如 姓名 电话 性别 年龄 生日 宿舍 李四 1234 男 21 7月1日 东二333 e使用菜单实现功能的正确的选择 f 所有节点信息都是动态生成。 6测试程序 应列出测试大纲对程序进行测试; 应保证测试用例测试到程序的各种边缘情况
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溟洵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值