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

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

绪论:


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


思维导图

image.png

要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语言知识,关注喔老铁!

相关文章
|
4天前
|
存储 SQL 网络协议
C语言C/S架构PACS影像归档和通信系统源码 医院PACS系统源码
医院影像科PACS系统,意为影像归档和通信系统。它是应用在医院影像科室的系统,主要的任务是把日常产生的各种医学影像(包括核磁、CT、超声、各种X光机、各种红外仪、显微仪等设备产生的图像)通过各种接口(模拟、DICOM、网络)以数字化的方式海量保存起来,并在需要的时候在一定授权下能够快速地调回使用。同时,PACS系统还增加了一些辅助诊断管理功能。
40 11
|
4天前
|
C语言
用c语言实现一个通讯录
用c语言实现一个通讯录
12 0
|
4天前
|
存储 C语言
C语言详解【通讯录的实现】
C语言详解【通讯录的实现】
|
4天前
|
存储 XML JSON
【C语言-通讯录的分析与实现】
我们以手机里面的通讯录为例,说明通讯录主要有以下什么功能,我们先用一张简单的图来说明一下
24 0
|
4天前
|
C语言
【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化
动态内存管理的函数有:malloc,calloc,ralloc,free,本文讲解动态内存函数和使用,如何进行动态内存管理,实现通讯录联系人容量的动态化,对常见动态内存错误进行总结。
38 0
|
4天前
|
C语言
C语言进阶第八课 --------通讯录的实现
C语言进阶第八课 --------通讯录的实现
|
4天前
|
存储 算法 C语言
C语言进阶:顺序表(数据结构基础) (以通讯录项目为代码练习)
C语言进阶:顺序表(数据结构基础) (以通讯录项目为代码练习)
|
4天前
通讯录(C语言版)
通讯录(C语言版)
|
4天前
|
存储 人工智能 搜索推荐
【C语言/C++】电子元器件管理系统(C源码)【独一无二】
【C语言/C++】电子元器件管理系统(C源码)【独一无二】
|
4天前
|
存储 人工智能 机器人
【C/C++】C语言 学生信息管理系统(源码)【独一无二】
【C/C++】C语言 学生信息管理系统(源码)【独一无二】