学生信息管理系统(通讯录)----------通俗易懂、附源码、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语言知识,关注喔老铁!

相关文章
|
2月前
|
C语言
C语言——通讯录系统—基于 VS2022
C语言——通讯录系统—基于 VS2022
|
10天前
|
存储 定位技术 API
C语言实战 -- 经典贪吃蛇游戏(含完整源码)
C语言实战 -- 经典贪吃蛇游戏(含完整源码)
10 1
|
21天前
|
机器学习/深度学习 搜索推荐 程序员
C语言实现个人通讯录(功能优化)-2
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-2
|
21天前
|
存储 C语言 索引
C语言实现个人通讯录(功能优化)-1
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-1
|
2天前
|
存储 SQL 网络协议
什么是PACS系统?一套C语言C/S架构PACS影像归档和通信系统源码
PACS系统是基于C/S架构的医学影像归档和通信系统,遵循IHE和DICOM3.0标准,采用Wintel平台与品牌服务器,配备SQL Server数据库,支持双机热备。它确保图像质量和高效传输,兼容多种医学设备,允许历史胶片扫描存储,并有严格的权限管理与安全机制,包括数据备份和故障恢复功能,旨在实现资源共享和效率提升。系统设计考虑了与医院HIS集成及未来扩展。
10 0
|
28天前
|
C语言
C语言学习记录——通讯录(静态内存)
C语言学习记录——通讯录(静态内存)
16 2
|
9天前
|
存储 C语言
详细解读C语言学生信息管理系统
详细解读C语言学生信息管理系统
15 0
|
9天前
|
存储 人机交互 C语言
【C语言项目实战】使用单链表实现通讯录
【C语言项目实战】使用单链表实现通讯录
|
10天前
|
编译器 程序员 Linux
C语言编程的各种源码文件
C编程的各种源码文件
|
2月前
|
存储 C语言
C语言实现通讯录
C语言实现通讯录
23 2