赶紧进来看看---C语言实现学生信息管理系统(3.0文件存储版)

这篇具有很好参考价值的文章主要介绍了赶紧进来看看---C语言实现学生信息管理系统(3.0文件存储版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文主要介绍了将学生信息管理系统改造为文件存储版本…
主要涉及文件操作函数–将学生信息导入文件和从文件读取学生信息到程序中,从而达到数据持久化的效果
文章最后有源码展示

学生信息管理系统1.0静态版->学生信息管理系统2.0动态内存增长版->学生信息管理系统3.0文件存储版

一.文件存储版本的介绍

之前的博客中介绍用C实现了学生信息管理系统1.0静态版本和优化后的2.0动态版本.这两个版本都有一个弊端:两个版本对学生信息的操作都是在程序运行中存在的.而当程序结束后,其产生的有用的学生信息都会丢失…

而在学了C语言文件操作后,就可以实现将程序运行时产生的学生信息通过文件函数导入到本地文件中,而在下一次再次运行程序时可以从本地文件中读取之前保留的学生信息…能够实现数据的持久化,
而此篇博客就是将之前学生信息管理系统2.0版本改造为可文件存储的3.0版本
而前提要对文件的常用操作能够熟练运用 - - - 文件常用操作

二.学生信息管理系统文件版本3.0改造过程

改造主要设计 :增加三个菜单选项–将学生信息导入文件 和从文件里读取学生信息 以及增加和修改相关的函数

1.增加菜单选择选项

主要增加了三个选项 :清空现有学生信息 读取已有学生信息 保存当前学生信息
增加菜单选项前↓
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构

增加菜单选项后↓
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构
对应的枚举选项和增加分支 前↓
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构
对应的枚举选项和增加分支 后↓
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构

c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构

2.实现将学生信息导入文件

将学生信息导入到文件中使用的是fprintf 以文件形式格式化输出函数

void writestu(stumgt* pstus)   // 往文件里写入学生信息
{
	FILE* pf = fopen("学生信息.txt", "w");
	if (pf == NULL)
	{
		printf("存储学生信息失败!!!\n");
		return;
	}
	assert(pstus != NULL);
	for (int i = 0; i < pstus->sz; i++) //从第一个学生记录到第sz-1个 即所有学生记录
	{
		fprintf(pf, "%s %s %s %d %s %s %s\n", pstus->stu[i].sno, pstus->stu[i].name, pstus->stu[i].sex, pstus->stu[i].age, pstus->stu[i].roomnum, pstus->stu[i].number, pstus->stu[i].add);
	}  //用fprintf函数按指定字符串格式输出每一个学生对应的信息输出到文件中 注意每个之间用空格分开 这样在读取的时候也会以空格形式作为分隔读取
	printf("已保存当前已有学生信息\n");
	fclose(pf);
}

具体实现思路为:
首先先以只读形式打开"学生信息.txt"文件,判断一下pf是否为空 来确认文件是否打开成功,
打开成功后用一个for循环从第一个学生信息开始直到当前学生信息最大有效个数往文件里写入信息,每次写入一个学生信息,
根据fprintf函数使用方法第一个是指向文件信息区的指针
第二个参数对应着学生信息结构体所有成员变量的格式输出形式 (注意:中间要用空格隔开成员信息每项属性…视觉上更对齐也能给读取学生信息时留下空格分隔符…)
而第三个参数对应着学生信息成员变量每个属性的输出项(注意除了年龄外其他的都是字符串形式 )

=========================================================
设计完后来测试下往文件里写入学生信息的效果:

先通过1选项添加三个测试用例↓
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构
当选择10后最后可以看到程序已经成功打开一个"学生信息.txt"文件,并按照设计的格式向文件内部写入了三个学生信息↓
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构

3.实现从文件中读取学生信息

从文件中读取学生信息的使用的是fscanf以文件形式格式化输入函数

void readstu(stumgt** pstus)    //往程序内部读取学生信息
{
	FILE* pf = fopen("学生信息.txt", "r");
	if (pf == NULL)
	{
		printf("当前程序内没有存储学生信息...\n");
		return;
	}
	else
	{
		assert(pstus != NULL);
		if ((*pstus)->sz == ( * pstus)->capcity)             //
		{
			addcapcity(pstus);                 //
			printf("存储空间已满..增容中...\n");   //
			Sleep(3000);

		}
		if ((*pstus)->sz ==( *pstus)->capcity)          //
		{
			printf("容量已满,无法再添加学生信息\n");
			fclose(pf);
			return;

		}
		studata tmp = { 0 };
		while (fscanf(pf, "%s%s%s%d%s%s%s", tmp.sno, tmp.name, tmp.sex, &tmp.age, tmp.roomnum, tmp.number, tmp.add) == 7)
		{    //通过fscanf 以对应的格式往文件里读取字符串输入到指定的成员变量中
			

			(* pstus)->stu[(*pstus)->sz] = tmp;   //进入循环则表示已读取到信息 此时直接将tmp这个结构体变量信息传给 管理系统里的sz下标对应的学生信息
			(*pstus)->sz++;		
			if ((*pstus)->sz == (*pstus)->capcity)             //判断当前容量是否满
			{
				addcapcity(pstus);                 //
				printf("存储空间不足..正在增容中...\n");   //
				Sleep(3000);

			}
			if ((*pstus)->sz == (*pstus)->capcity)          //
			{
				printf("容量已满,无法再添加学生信息\n");
				fclose(pf);
				return;
			}
		}
		printf("已读取完成\n");
	}
}

具体实现思路为:
1.先以只读形式打开"学生信息.txt"文件,判断pf是否为NULL来确认文件是否存在且已打开成功

2.打开成功后开始读取信息,首先判断当前学生管理系统容量是否足够,如果不够此时调用增容函数…
(注意此函数接受的是二级指针,调用增容函数传参也是二级指针,因为增容最后要改变main内部的存放指向学生信息动态空间的指针,通过二级指针可以得到其指针空间对指向的空间扩容或者无法扩容时会重新开辟一块新的空间将其地址给 学生信息结构体指针空间)
经过最后判断增容成功后进行读取学生信息…

3.fscanf第一个参数是指向文件信息区的指针,
第二个参数是对应读取的每个学生信息属性的格式输入字符
第三个参数对应的是输入格式符的输入项即将文件里的学生信息的每个属性输入到结构体成员的哪个属性变量中
(注意:除年龄外其他都是字符数组形式只需要得到数组名不需要取地址,而年龄是整形变量需要取地址)

4.通过fscanf读取数据返回值的特点:创建一个存放学生信息的临时结构体变量用while语句将其表达式里直接读取学生信息存放到临时结构体变量中
每读取成功一个学生信息会返回7 进入循环,将临时变量里的学生信息赋给学生信息结构变量然后有效学生信息个数sz++并判断一下容量是否已满增容

5.最后如果读取的学生信息返回值不为7则读取完了学生信息 出while循环此时文件里的学生信息已读取完成…

=========================================================
这里来测试一下从文件中读取学生信息的效果:
先打开之前保存的三个学生信息的文件,在最后一行再用键盘添加一组测试信息↓
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构
此时测试选择9读取信息的效果↓
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构
可以看到程序读取信息时空间不够自动扩容存储学生信息
此时选择显示学生信息看看效果↓:
c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构
发现此时存储在文件中的所有学生信息都被读取到了程序中…

4.实现清空现有学生信息

在使用学生信息管理系统过程中需要删除所有学生信息操作时,此时学生数量多使用删除操作一条条删除很满,此时增加一项清空所有学生信息功能

void emptystu(stumgt* pstus)  //清空学生信息记录
{
	assert(pstus != NULL);
	pstus->sz = 0;
	printf("学生信息已清空\n");
}

此功能实现很简单即将sz置为0即可

三.学生信息管理系统–3.0文件存储版源码展示

1.stu.h头文件


#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<windows.h>
#define SZ 3          //每次增加的容量个数
#define CAPCITY 3    //一开始设置的容量
typedef struct studentdata
{
	char sno[20];  //学号
	char name[20]; //名字
	char sex[5]; //性别
	int age;  //年龄
	char roomnum[20];// 寝室号
	char number[12];// 电话号码
	char add[50];  //地址
}studata;

typedef struct studentmanagement
{

	int sz;       //记录当前有效的学生信息个数
	int capcity;   //记录存放学生信息的最大容量
	studata stu[]; //柔性数组 用于不确定数组元素个数 实现动态增长
}stumgt;
enum option //声明 枚举类型 option 对应的枚举常量为实现 管理系统 菜单功能的选项名称  枚举常量不能同名
{
	EXIT,  //退出
	ADD,   //添加
	DROP,   //删除
	FIND,   //查找
	MODIFY, //修改
	TOTAL, //统计
	PRINT, //打印
	SORT,  //排序
	EMPTY, //清空
	READ,  //读取
	WRITE //写入
	
};
enum option1   // 修改菜单的选择项
{
	END,   //结束修改
	MODALL, //修改整条信息
	MODONE  //修改某一项信息
};
enum option2  //修改单项的菜单选择项
{
	RETURN,   //返回上一层
	MODSNO, //修改学号
	MODNAME, //修改姓名
	MODSEX,  //修改性别
	MODAGE, //修改年龄
	MODROOM, //修改寝室号
	MODNUMBER, //修改电话号码
	MODADDRESS //修改地址
};
enum option3 //统计学生个数菜单 选择项
{
	ENDCOUNT,  //结束统计
	COUNTALL,  //统计所有学生信息
	COUNTAGE, // 按年龄统计
	COUNTROOM, //统计寝室号
	COUNTSEX //按性别统计
};
void menu();
//void initstus(stumgt* pstus);
void addstu(stumgt** pstus);
void pritstus(stumgt* pstus);
void dropstu(stumgt* pstus);
void search(stumgt* pstus);
void modifystu(stumgt* pstus);
void countstu(stumgt* pstus);
void sortstu(stumgt* pstus);
void readstu(stumgt** pstus);
void writestu(stumgt* pstus);
void emptystu(stumgt* pstus);

2.stu.c源文件

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS  
#pragma warning(disable : 6031) //忽略返回值
#include"stu.h"

void menu()
{
	printf("           欢迎使用学生信息管理系统              \n");
	printf("*************************************************\n");
	printf("#  1.添加新的学生信息    2.删除指定学生信息     #\n");
	printf("#  3.查找指定学生信息    4.修改指定学生信息     #\n");
	printf("#  5.分类统计学生个数    6.显示所有学生信息     #\n");
	printf("#  7.排序所有学生信息    8.清空现有学生信息     #\n");
	printf("#  9.读取已有学生信息    10.保存当前学生信息    #\n");
	printf("*           0.退出学生信息管理系统              *\n");
	printf("*************************************************\n");
}
static void modifymenu1()
{
	printf("*************************************************\n");
	printf("#  1.修改整条学生信息    2.修改某项学生信息     #\n");
	printf("#               0.退出修改菜单                  #\n");
	printf("*************************************************\n");
}

static void modifymenu2()
{
	printf("*************************************************\n");
	printf("#       1.修改学生学号    2.修改学生姓名        #\n");
	printf("#       3.修改学生性别    4.修改学生年龄        #\n");
	printf("#       5,修改学生寝室号  6.修改学生电话号码    #\n");
	printf("#       7.修改学生家庭住址 0.返回上一步修改     #\n");
	printf("*************************************************\n");
}
static void countmenu()
{
	printf("*************************************************\n");
	printf("#  1.统计所有学生个数    2.按年龄统计学生个数   #\n");
	printf("#  3.按寝室号统计学生个数4.按性别统计学生个数   #\n");
	printf("#                  0.结束统计                   #\n");
	printf("*************************************************\n");
}

void initstus(stumgt* pstus)//初始化学生管理系统这个结果体变量
{
	assert(pstus != NULL);
	pstus->capcity = CAPCITY;        // 初始化给capcity赋最大值
}
static void addcapcity(stumgt** pstus)
{
	stumgt* tmp = (stumgt*)realloc(*pstus, sizeof(stumgt) + sizeof(studata) * ((*pstus)->capcity + SZ)  );    //每次增容给原来空间扩大SZ个 存放学生信息空间
	if (tmp == NULL)    //  判断是否增容失败
	{
		perror("realloc");
		return;
	}
	else
	{
		*pstus = tmp;     //  将扩大的空间的地址 通过解引用传给 main函数stus这个指针变量 
		(*pstus)->capcity += SZ;             //最大容量增容 SZ 个
	}


}
static int is_repeat(stumgt* pstus, char tmp[]) //判断学号信息是否重复
{
	int i = 0;
	for (i = 0; i < pstus->sz; i++)
	{
		if (strcmp(tmp, pstus->stu[i].sno) == 0)
		{
			return 1;
		}
	}
	return 0;
}
void addstu(stumgt** pstus)
{
	assert(pstus != NULL);
	if ((* pstus) ->sz == ( * pstus)->capcity)             //判断当前是否容量满
	{
		addcapcity(pstus);                 //
		printf("存储空间已满..增容中...\n");   //
		Sleep(3000);

	}
	if (( * pstus)->sz == (*pstus)->capcity)          //如果增容完容量还是满此时表示增容失败
	{
		printf("容量已满,无法再添加学生信息\n");
		return;

	}
	else
	{
		system("cls"); //输入学生信息前清屏一次
		printf("请输入学生学号:");
		char tmp[20] = { 0 };
		scanf("%s", tmp);
		if (is_repeat((*pstus), tmp))   //学生学号为主要属性  应是唯一的且不能为空
		{
			printf("输入失败!!!已存在学号信息为%s的学生,不同学生信息不允许设置相同学号\n", tmp);
			return;
		}

		strcpy((*pstus)->stu[(*pstus)->sz].sno, tmp);  //不存在重复时将当前信息拷贝作为学生学号信息
		printf("请输入学生名字:");
		scanf("%s", (*pstus)->stu[(*pstus)->sz].name);
		printf("请输入学生性别:");
		scanf("%s", (*pstus)->stu[(*pstus)->sz].sex);
		printf("请输入学生年龄:");
		scanf("%d", &(*pstus)->stu[(*pstus)->sz].age); //注意年龄这里要&其他的都是地址
		printf("请输入学生寝室号:");
		scanf("%s", (*pstus)->stu[(*pstus)->sz].roomnum);
		printf("请输入学生电话号码:");
		scanf("%s", (*pstus)->stu[(*pstus)->sz].number);
		printf("请输入学生家庭住址:");
		scanf("%s", (*pstus)->stu[(*pstus)->sz].add);
		(*pstus)->sz++;
		system("cls");
		printf("添加成功\n");
	}
}

void pritstus(stumgt* pstus)   //打印所有信息
{
	assert(pstus != NULL);
	system("cls");   //输出所有信息前先清屏一次
	printf("%-10s\t%-10s\t%-5s\t%-10s\t%-10s\t%-12s\t%-20s\t\n", "学号", "姓名", "性别", "年龄", "寝室号", "电话号码", "家庭住址");//先设置好对应字段格式
	int i = 0;
	for (i = 0; i < pstus->sz; i++)
	{
		printf("%-10s\t%-10s\t%-5s\t%-10d\t%-10s\t%-12s\t%-20s\t\n",  //按设置好的格式对其打印数据
			pstus->stu[i].sno,
			pstus->stu[i].name,
			pstus->stu[i].sex,
			pstus->stu[i].age,
			pstus->stu[i].roomnum,
			pstus->stu[i].number,
			pstus->stu[i].add);
	}
}
static int findstu(stumgt* pstus, char tmp[])  //封装的内部 查找学生学号信息的函数 找到返回对应的数组元素下标 没找到返回-1
{
	assert(pstus != NULL);
	int i = 0;
	for (i = 0; i < pstus->sz; i++)
	{
		if (strcmp(tmp, pstus->stu[i].sno) == 0)
			return i;
	}
	return -1;
}
void dropstu(stumgt* pstus)  //删除学生信息
{
	assert(pstus != NULL);
	if (pstus->sz == 0)   //判断学生记录是否为空
	{
		printf("当前没有学生信息,无法删除\n");
		return;
	}
	char tmp[20] = { 0 };
	printf("输入要删除的学生的学号信息:");
	scanf("%s", tmp);
	int num = findstu(pstus, tmp);  //使用内部封装的查找函数
	if (num == -1)
	{
		printf("没有找到要删除的学生信息\n");
		return;
	}
	else
	{
		int i = 0;
		for (i = num + 1; i < pstus->sz; i++)
		{
			pstus->stu[i - 1] = pstus->stu[i];
		}
		pstus->sz--;
		printf("已删除学号为%s的学生成员\n", tmp);
	}
}
void search(stumgt* pstus)  //查找学生信息的函数  以名字作为查找标准
{
	assert(pstus != NULL);
	char tmp[20] = { 0 };
	printf("请输入要查找的学生姓名:");
	scanf("%s", tmp);
	system("cls");
	printf("已查询到以下姓名为%s的学生信息↓↓↓\n", tmp);  //找到后按设置的对齐格式输出查找的信息
	printf("%-10s\t%-10s\t%-5s\t%-10s\t%-10s\t%-12s\t%-20s\t\n", "学号", "姓名", "性别", "年龄", "寝室号", "电话号码", "家庭住址");
	int i = 0;
	for (i = 0; i < pstus->sz; i++)
	{
		if (strcmp(tmp, pstus->stu[i].name) == 0)
		{
			printf("%-10s\t%-10s\t%-5s\t%-10d\t%-10s\t%-12s\t%-20s\t\n",
				pstus->stu[i].sno,
				pstus->stu[i].name,
				pstus->stu[i].sex,
				pstus->stu[i].age,
				pstus->stu[i].roomnum,
				pstus->stu[i].number,
				pstus->stu[i].add);
		}
	}
}
static void modifyall(stumgt* pstus)  //内部封装的修改整条学生信息的函数
{
	char tmp[20] = { 0 };
	printf("请输入要修改的学生学号信息:");
	scanf("%s", tmp);

	int num = findstu(pstus, tmp);  //先判断是否存在要修改的学生信息
	if (num == -1)
	{
		printf("未找到要修改的学生信息\n");
		return;
	}
	else
	{
		system("cls"); //输入学生信息前清屏一次
		printf("请输入学生学号:");
		char tmp[20] = { 0 };
		scanf("%s", tmp);
		if (is_repeat(pstus, tmp))   //学生学号为主要属性  应是唯一的且不能为空
		{
			printf("输入失败!!!已存在学号信息为%s的学生,不同学生信息不允许设置相同学号\n", tmp);
			return;
		}

		strcpy(pstus->stu[num].sno, tmp);  //修改后的学号在之前学生信息里没有重复的则将tmp的拷贝修改当前学生信息学号
		printf("请输入学生名字:");
		scanf("%s", pstus->stu[num].name);
		printf("请输入学生性别:");
		scanf("%s", pstus->stu[num].sex);
		printf("请输入学生年龄:");
		scanf("%d", &pstus->stu[num].age);
		printf("请输入学生寝室号:");
		scanf("%s", pstus->stu[num].roomnum);
		printf("请输入学生电话号码:");
		scanf("%s", pstus->stu[num].number);
		printf("请输入学生家庭住址:");
		scanf("%s", pstus->stu[num].add);
		printf("修改成功\n");
	}
}
static void modifysno(stumgt* pstus, int num) //内部封装的单独修改学号的函数
{
	printf("你要将学号修改为:");
	char tmp[20] = { 0 };
	scanf("%s", tmp);
	if (is_repeat(pstus, tmp))
	{
		printf("修改失败,不能输入已有的学号\n");
		return;
	}
	else
	{
		strcpy(pstus->stu[num].sno, tmp);
		printf("修改成功\n");
	}

}
static void modifyname(stumgt* pstus, int num)//内部封装的单独修改名字的函数
{
	printf("你要将名字修改为:");
	scanf("%s", pstus->stu[num].name);
	printf("修改成功\n");
}
static void modifysex(stumgt* pstus, int num)//内部封装的单独修改性别的函数
{
	printf("你要将性别修改为:");
	scanf("%s", pstus->stu[num].sex);
	printf("修改成功\n");
}
static void modifyage(stumgt* pstus, int num)//内部封装的单独修改年龄的函数
{
	printf("你要将年龄修改为:");
	scanf("%d", &pstus->stu[num].age);
	printf("修改成功\n");
}
static void modifyroomnum(stumgt* pstus, int num)//内部封装的单独修改寝室号的函数
{
	printf("你要将寝室号修改为:");
	scanf("%s", pstus->stu[num].roomnum);
	printf("修改成功\n");
}
static void modifynumber(stumgt* pstus, int num)//内部封装的单独修改电话号码的函数
{
	printf("你要将电话号码修改为:");
	scanf("%s", pstus->stu[num].number);
	printf("修改成功\n");
}
static void modifyadd(stumgt* pstus, int num)//内部封装的单独修改地址的函数
{
	printf("你要将地址修改为:");
	scanf("%s", pstus->stu[num].add);
	printf("修改成功\n");
}

static void modifyone(stumgt* pstus)  //内部封装修改整条学生信息里的某项信息函数
{
	char tmp[20] = { 0 };
	printf("请输入要修改的学生学号信息:");
	scanf("%s", tmp);
	int num = findstu(pstus, tmp);  //先判断是否存在该学生信息
	if (num == -1)
	{
		printf("未找到要修改的学生信息\n");
		return;
	}
	else
	{
		int input = 0;
		modifymenu2();  //下面为函数指针数组将一个0和上面7个封装好的修改对应学生信息的函数指针作为数组初始化信息(0是为了方便下标对其选项)
		void(*mod[8])(stumgt*, int) = { 0,modifysno,modifyname,modifysex,modifyage,modifyroomnum,modifynumber,modifyadd };
		printf("请选择修改的内容:");
		do
		{
			scanf("%d", &input);
			if (input >= 8 || input < 0)
			{
				printf("非法输入,请重新选择\n");

			}
			else if (input == 0)
			{
				printf("退回上一层修改菜单\n");
			}
			else
				mod[input](pstus, num); //根据菜单对应input输入的值调用 数组里相对应的函数指针

		} while (input >= 8 || input < 0); //超出重新输入

	}
}
void modifystu(stumgt* pstus)  //修改学生信息的函数
{


	int input = 0;
	do
	{
		modifymenu1();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)//选择修改整条学生信息还是修改一条里某一项的学生信息
		{
		case 1:
			modifyall(pstus);
			break;
		case 2:
			modifyone(pstus);
			break;
		case 0:
			printf("已结束修改操作\n");
			break;
		default:
			printf("非法输入,请重新输入\n");
		}

	} while (input);

}
static void countall(stumgt* pstus)  //内部封装的统计当前所有学生信息记录函数
{
	printf("已统计当前系统中有%d个学生\n", pstus->sz);
	return;
}
static void countage(stumgt* pstus)  //统计年龄范围内学生记录的个数
{
	int age1 = 0;
	int age2 = 0;
	int age = 0;
	printf("请输入两个数字将统计其范围内的年龄个数(如果两个数字相同则统计这个数字年龄的学生个数)");
	scanf("%d%d", &age1, &age2);
	int count = 0;
	int i = 0;
	for (i = 0; i < pstus->sz; i++)
	{
		age = pstus->stu[i].age;
		if (age >= age1 && age <= age2)
		{
			count++;
		}
	}
	printf("在%d岁和%d岁之间的学生个数为%d\n", age1, age2, count);
	return;
}
static void countroom(stumgt* pstus) //统计 寝室号的个数
{
	char room[20] = { 0 };
	printf("请输入寝室号:");
	scanf("%s", room);
	int i = 0;
	int count = 0;
	for (i = 0; i < pstus->sz; i++)
	{
		if (strcmp(room, pstus->stu[i].roomnum) == 0)
		{
			count++;
		}
	}
	printf("寝室号为%s的寝室个数为%d个\n", room, count);
	return;
}
static countsex(stumgt* pstus)   //统计相同性别的学生个数
{
	char sex[5] = { 0 };
	printf("请输入要统计的性别:");
	scanf("%s", sex);
	int i = 0;
	int count = 0;
	for (i = 0; i < pstus->sz; i++)
	{
		if (strcmp(sex, pstus->stu[i].sex) == 0)
		{
			count++;
		}
	}
	printf("性别为%s的学生个数为:%d\n", sex, count);
}
void countstu(stumgt* pstus)  //统计学生信息的函数
{
	assert(pstus != NULL);
	system("cls");

	int input = 0;
	do
	{
		countmenu();
		printf("请选择统计方式:");
		scanf("%d", &input);
		switch (input)  //对应菜单输入input选择 跳转到上面封装的统计函数
		{
		case COUNTALL:
			countall(pstus);
			break;
		case COUNTAGE:
			countage(pstus);
			break;
		case COUNTROOM:
			countroom(pstus);
			break;
		case COUNTSEX:
			countsex(pstus);
			break;
		case ENDCOUNT:
			printf("已结束统计\n");
			break;
		default:
			printf("非法输入,请重新选择\n");
		}

	} while (input);
}
int cmp_sno(const studata stu1, const studata stu2) // 为qsort 函数设置的函数指针 用于比较两个元素的大小传给qsort
{
	return strcmp(stu1.sno, stu2.sno);    //比较两个学生里的学号大小 进行排序 这两个学生元素
}
void sortstu(stumgt* pstus) //  升序排序所有学生记录的函数
{
	if (pstus->sz == 0)   //判断排序时是否为空
	{
		printf("当前学生记录为空,无法排序\n");
		return;
	}
	qsort(pstus->stu, pstus->sz, sizeof(studata), cmp_sno);    //
	printf("已按学号完成升序排序\n");
}
void readstu(stumgt** pstus)    //往程序内部读取学生信息
{
	FILE* pf = fopen("学生信息.txt", "r");
	if (pf == NULL)
	{
		printf("当前程序内没有存储学生信息...\n");
		return;
	}
	else
	{
		assert(pstus != NULL);
		if ((*pstus)->sz == ( * pstus)->capcity)             //
		{
			addcapcity(pstus);                 //
			printf("存储空间已满..增容中...\n");   //
			Sleep(3000);

		}
		if ((*pstus)->sz ==( *pstus)->capcity)          //
		{
			printf("容量已满,无法再添加学生信息\n");
			fclose(pf);
			return;

		}
		studata tmp = { 0 };
		while (fscanf(pf, "%s%s%s%d%s%s%s", tmp.sno, tmp.name, tmp.sex, &tmp.age, tmp.roomnum, tmp.number, tmp.add) == 7)
		{    //通过fscanf 以对应的格式往文件里读取字符串输入到指定的成员变量中
			

			(* pstus)->stu[(*pstus)->sz] = tmp;   //进入循环则表示已读取到信息 此时直接将tmp这个结构体变量信息传给 管理系统里的sz下标对应的学生信息
			(*pstus)->sz++;		
			if ((*pstus)->sz == (*pstus)->capcity)             //判断当前容量是否满
			{
				addcapcity(pstus);                 //
				printf("存储空间不足..正在增容中...\n");   //
				Sleep(3000);

			}
			if ((*pstus)->sz == (*pstus)->capcity)          //
			{
				printf("容量已满,无法再添加学生信息\n");
				fclose(pf);
				return;
			}
		}
		printf("已读取完成\n");
	}
}
void writestu(stumgt* pstus)   // 往文件里写入学生信息
{
	FILE* pf = fopen("学生信息.txt", "w");
	if (pf == NULL)
	{
		printf("存储学生信息失败!!!\n");
		return;
	}
	assert(pstus != NULL);
	for (int i = 0; i < pstus->sz; i++) //从第一个学生记录到第sz-1个 即所有学生记录
	{
		fprintf(pf, "%s %s %s %d %s %s %s\n", pstus->stu[i].sno, pstus->stu[i].name, pstus->stu[i].sex, pstus->stu[i].age, pstus->stu[i].roomnum, pstus->stu[i].number, pstus->stu[i].add);
	}  //用fprintf函数按指定字符串格式输出每一个学生对应的信息输出到文件中 注意每个之间用空格分开 这样在读取的时候也会以空格形式作为分隔读取
	printf("已保存当前已有学生信息\n");
	fclose(pf);
}
void emptystu(stumgt* pstus)  //清空学生信息记录
{
	assert(pstus != NULL);
	pstus->sz = 0;
	printf("学生信息已清空\n");
}

3.text.c源文件

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable : 6031)
#include"stu.h"


int main()
{
	stumgt* stus = (stumgt*)calloc(1, sizeof(stumgt) + sizeof(studata) * CAPCITY);//在堆区创建stumgt类型大小的空间给柔性数组分配的空间 

	int i = 0;
	initstus(stus);
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &i);
		switch (i)
		{
		case ADD:
			addstu(&stus);  //因为要动态增容 stus内的指针可能改变 ,这里用二级指针传址调用
			break;
		case DROP:
			dropstu(stus);
			break;
		case FIND:
			search(stus);
			break;
		case MODIFY:
			modifystu(stus);
			break;
		case TOTAL:
			countstu(stus);
			break;
		case PRINT:
			pritstus(stus);
			break;
		case SORT:
			sortstu(stus);
			break;
		case EXIT:
			printf("已退出学生信息管理系统\n");
			break;
		case READ:
			readstu(&stus);
			break;
		case WRITE:
			writestu(stus);
			break;
		case EMPTY:
			emptystu(stus);
			break;
		default:
			printf("选择错误,请重新输入\n");
			break;
		}
	} while (i);
	return 0;
}

四.总结

学生信息管理系统三个版本已经全部写完, 而实现此系统也将学到的知识基本都串联了起来,
尽管写代码过程中构思时间久,写完寻找bug解决bug所花时间多.但是这都是让自己知识更牢固的一个过程,
学习本就是一个不断打磨的过程,愿每个人能坚持自己的目标,在每个阶段都能看到不一样的自己…

c语言学生信息管理系统数据保存,c语言(从0到1学习),#  c语言小程序设计,c语言,c++,算法,数据结构文章来源地址https://www.toymoban.com/news/detail-807894.html

到了这里,关于赶紧进来看看---C语言实现学生信息管理系统(3.0文件存储版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 学生信息管理系统(c语言版)

    大一下C语言要交课程设计,于是就写了一个学生信息管理系统,仅供参考 学生信息包括姓名,学号,性别,年龄和各科成绩,可根据需要自行修改添加 包括增、删、改查、查看所有、保存、清空7个功能,每个功能都封装成一个函数 保存功能是将所添加的信息保存到文件中

    2024年02月12日
    浏览(31)
  • C语言——学生信息管理系统(数组)

    因为最近是在赶进度总结,数组和指针的笔记已经更新,但是数组、指针的习题还未总结,数组的题已经开始总结,但是还没总结完,所以还没发出来,目前学习进度已经到了学生管理系统,趁热打铁将学生管理系统的数组篇更新,因为之后还有指针篇,怕到时候代码搞混了

    2023年04月15日
    浏览(36)
  • 基于C语言的学生信息管理系统开发

    软件功能描述 功能模块图 2.信息管理模块 功能说明:输入、增加、删除、修改学生信息同时返回上一级 查询模块 功能说明:根据性别民族等查找学生人数、按照课程最高分查询学生信息、按照课程统计学生的平均分数同时返回上一级 成绩排序模块 功能说明:根据课程对学

    2024年02月04日
    浏览(45)
  • C语言版----学生信息管理系统(分析+代码)

    一、分析系统功能设计 1. 初始化学生列表、教师列表 ·typedef struct student 先对学生结构体进行重定义,便于对相关数组取名 再初始化一个教室class,便于在后面的函数中调用学生信息 ·typedef struct teacher 先对教师结构体进行重定义,便于对相关数组取名 ·void inputtStu() 初始化三

    2024年02月09日
    浏览(38)
  • C语言学生成绩信息管理系统(超详细版)

    主题:一个简易成绩管理系统 功能介绍: 1.以文本形式存储学生信息 2.对以存信息进行   1. 插入 2. 修改3. 删除  4.查询  5.成绩数字特征 目录 一:分析 二:查询  三:菜单 四:初始化函数 五:插入函数 六:修改函数 七:删除函数 八:数字特征 九:显示函数 要进行 插入

    2024年02月12日
    浏览(29)
  • 学生信息管理系统——JAVA 语言版(主页面+增+删+改+查+退)

    学生管理系统要能够实现添加学生信息,删除,修改以及查看学生信息的功能。 你是否尝试过使用JAVA语言编写一个代码程序,使用该代码实现学生信息管理呢? 如果你还没有任何头绪,接下来推荐你看一下我的做法,我使用的编程工具是IDEA,以下给出了学生信息管理系统的程

    2024年02月03日
    浏览(30)
  • C语言课程设计:学生成绩信息管理系统(排序、平均分、总分)详解

    1、需求分析 利用C语言编写一个可以对学生成绩信息进行管理的系统 0、退出系统 1、录入学生信息和成绩 2、打印学生信息 3、统计学生人数 4、查找学生信息 5、修改学生信息 6、删除学生信息 7、排序学生成绩 8、生成学生信息文件 9、读取文件学生信息 10、输出各科成绩不

    2024年02月11日
    浏览(38)
  • C语言程序设计期末大作业(学生信息管理系统)(可自取源码)

    高校学生信息管理系统 (一)在高校学生管理系统中包含九个主要操作: 退出系统; 学生信息的录入; 学生信息的打印; 学生信息的保存; 学生信息的读取; 学生人数的统计; 学生信息的查找; 学生信息的修改; 学生信息的删除。 (二)设计流程 首先确认用switch ca

    2024年02月10日
    浏览(42)
  • 学生信息管理系统(Python实现)

    目录 1.功能介绍 2.代码模块 3.全局代码 摘剑!!! 采用列表+类的组合来实现对信息的增删改查,整体代码比较简单,只用了100余行 1)添加学生信息 2)查询学生信息 3)删除学生信息 4)修改学生信息 5)遍历学生信息 1)学生类 2)菜单menu 3)添加insert  4)查询search 5)删

    2024年02月13日
    浏览(45)
  • 定义学生信息结构体,包含学生的姓名、学号、年龄、成绩等信息。 建立学生信息管理系统的主菜单,包括录入学生信息、查询学生信息、修改学生信息、删除学生信息等功能。 实现录入学生信息的功能,可以根据用户输入...

    下面是关于学生信息结构体、学生信息管理系统主菜单以及其中的功能的 C 语言实现示例: ``` #include stdio.h #include string.h #define MAX_STUDENT_NUM 1000 // 学生信息结构体 struct Student { char name[100]; // 姓名 int id; // 学号 int age; // 年龄 float score; // 成绩 }; // 学生信息数组 struct Student stu

    2024年02月04日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包