Southwest Jiaotong University Data Structure C Course Design: Student Data Management System

(file content now added)

(version: 2.0, modified: sort, store, load)

 

 

Require:8286c1f1e26545918fc81bd448384471.jpeg

         First, a simple analysis of the topic: data management, only need a simple linked list to complete. The management methods include entry (adding the data typed from the keyboard to the end of the linked list), storage (storing the student data of the program into a file), loading (loading the student data in the file into the program), modification ( Modify an item in the student data), insert (insert the student data into the linked list), delete (delete the student data), search (find the student's data through the student number), sort (student number from small to large sort), show (display all student data).

        The difficulty is very clear: 1. The data of files and programs are transferred to each other. 2. Sorting of linked lists.

1. Modular programming.

        In order to make the modification and understanding of the code easier, I recommend modular programming in this course design.

        This kind of large program has at least 500 lines. If it is only placed in one file, the depth will be too deep, and the code will be long and smelly.

        In order to achieve modular programming, here I will talk about the simple implementation of modular programming.

A. Create the header file

        Many college students ignore the importance of header files. Through one header file, we can use one structure in two c files (fully reflected in this course design). With the header file, if you need to use the code you have written so far, you can quickly call it through the header file. The header file is written as follows:

        0130c1bdb7554685ab171139dd3657ac.png

        The most important of these is the part circled by the red box. This is an indispensable content of each header file. The content after ifndef and define is the name of the header file. The format is entered. Note that there are two underscores in front.

        Declare the functions in the c file in the header file, and use the structure in the header file, which will greatly reduce the amount of writing the c file.

B. References in c files

        The reference method is as follows

8cad1f860e2040f3b743ad4d45b6fd5e.png

 62ee403ac5f749f89b07bfbfb5e51f92.png

 Use this format to reference header files.

2. Overall code display

        The overall code is put here first, and will be explained one by one later.

main.cpp file code

#include <stdio.h>		
#include "line_list.h"	//线性表操作头文件
#include <stdlib.h>

extern struct Student;
//名称:学生数据管理。
//内容:录入,存储,装入,修改,插入,删除,查找,排序,显示。
//数据结构:线性表。
//数据对象:班或系的学生记录。
//学生记录:学号,姓名,年龄,性别,家庭住址,入学时间,家庭电话号码。

int main()
{
	struct Student* head;		//学生数据的头指针。
	int state= -1;	//初始状态,以进入和在选择操作中使用。
	head = (struct Student* )malloc(150);
	head->pNextNode=NULL;
	printf("欢迎使用本学生数据管理系统");
	while(state!=0)
	{
		printf("请输入您想要进行的操作的数字序号:0.退出  1.录入  2.修改  3.插入  4.删除  5.查找  6.排序  7.显示 8.装入 9.存储\n");
		scanf("%d",&state);
		getchar();	//吃回车
		while(state==1)
		{
			List_LuRu(head);				//将尾指针放进去,新建链表来改变尾指针,最后将尾指针赋值回去。
			printf("如果需要继续录入,则输入1;退出录入,则输入-1。\n");
			scanf("%d",&state);
			getchar();
		}
		while(state==2)
		{
			int lin,col;		//输入序号和列数以修改
			List_XianShi(head);	//显示帮助输入
			printf("请问您要修改序号几的第几列内容?(一次修改一个内容,空格隔开输入)\n");
			scanf("%d %d",&lin,&col);
			List_XiuGai(head,lin,col);	//修改函数
			printf("如果需要继续修改,则输入2;退出修改,则输入-1。\n");
			scanf("%d",&state);	
		}
		while(state==3)
		{
			int lin;	//输入序号
			List_XianShi(head);	//显示帮助输入
			printf("请问您要插入到第几序号后:\n");
			scanf("%d",&lin);
			List_ChaRu(head,lin);	//插入函数
			printf("如果需要继续插入,则输入3;退出插入,则输入-1。\n");
			scanf("%d",&state);
		}
		while(state==4)
		{
			int lin;
			List_XianShi(head);
			printf("请问您要删除第几序号的学生数据:");
			scanf("%d",&lin);
			List_ShanChu(head,lin);	//删除函数
			printf("如果需要继续删除,则输入4;退出删除,则输入-1。\n");
			scanf("%d",&state);
		}
		while(state==5)	//查找
		{
			int aim;	//查找方式
			printf("请问您是要什么方式查找数据?\n");
			printf("1.学号	2.序号\n");
			scanf("%d",&aim);
			List_ChaZhao(head,aim);	//查找函数,输入为查找方式
			printf("如果需要继续查找,则输入5;退出查找,则输入-1。\n");
			scanf("%d",&state);
		}
		while(state==6)	//排序
		{
			printf("正在进行学号排序in....(若数据过多,则缓冲时间会比较长)\n");
			List_PaiXv(head);
			printf("如果需要继续排序,则输入6;退出排序,则输入-1。\n");
			scanf("%d",&state);
		}
		while(state==7)
		{
			List_XianShi(head);				//将头指针放进去,以获得整个链表的所有信息。
			printf("如果需要继续显示,则输入7;退出显示,则输入-1。\n");
			scanf("%d",&state);
		}
		while(state==8)
		{
			printf("正在装入data中。。。。。\n");
			List_fLuRu(head);
			printf("录入成功!\n");
			state=-1;
		}
		while(state==9)
		{
			printf("正在储存数据到sum中。。。。\n");
			List_fCunChu(head);
			printf("存储成功!\n");
			state=-1;
		}
	}
}

line_list.cpp code

 

#include <stdio.h>
#include <stdlib.h>
#include "line_list.h"
#include <string.h>

void List_LuRu(struct Student *head)
{
	struct Student* Temp;
	struct Student* Temp2;
	Temp2 = head;
	while(Temp2->pNextNode!=NULL)
	{
		Temp2=Temp2->pNextNode;
	}
	printf("请输入学生的学号 ,姓名 ,年龄 ,性别(b/g) ,家庭住址 ,入学时间(xx/xx/xx)  家庭电话号码。(中间空格隔开)\n");
	Temp = (struct Student*)malloc(150);	//新建一个动态链表
	scanf("%s %s %s %s %s %s %s",Temp->ID,Temp->name,Temp->age,Temp->sex,Temp->address,Temp->Time,Temp->number);//该表内容的输入
	Temp2->pNextNode=Temp;	//将目前尾指针的指向该链表
	Temp2=Temp;
	Temp2->pNextNode=NULL;	//尾指针的下一项指向NULL
}
void List_XianShi(struct Student *head)	//显示函数
{
	int temp=0;
	struct Student* List;
	List = head->pNextNode;	//初始指向头指针下一个链表。头指针是空的
	while(List!=NULL)	//只要List不是空的,就执行
	{
		temp=temp+1;
		printf("序号%d:  ",temp);
		printf("%s %s %s %s %s %s %s\n",List->ID,List->name,List->age,List->sex,List->address,List->Time,List->number);
		List=List->pNextNode;	//指向下一个List
	}
}
void List_XiuGai(struct Student *head,int lin,int col)	//修改函数	
{
	struct Student* List;
	List=head->pNextNode;
	int Temp=lin;
	while(lin>1)	//指针不断指向下一个,直到找到目标指针
	{
		lin=lin-1;
		List=List->pNextNode;
	}
	if(lin==1)	//找到了
	{
		if(List==NULL)		//如果是空指针,报错
		{
			printf("请输入合法的序号。\n");
		}
		else if(col==1)
		{
			printf("定位到%d号的学号\n",Temp);
			printf("请输入您的修改后的内容:");
			scanf("%s",List->ID);
		}
		else if(col==2)
		{
			printf("定位到%d号的姓名\n",Temp);
			printf("请输入您的修改后的内容:");
			scanf("%s",List->name);
		}
		else if(col==3)
		{
			printf("定位到%d号的年龄\n",Temp);
			printf("请输入您的修改后的内容:");
			scanf("%s",List->age);
		}
		else if(col==4)
		{
			printf("定位到%d号的性别\n",Temp);
			printf("请输入您的修改后的内容:");
			scanf("%s",List->sex);
		}
		else if(col==5)
		{
			printf("定位到%d号的地址\n",Temp);
			printf("请输入您的修改后的内容:");
			scanf("%s",List->address);
		}
		else if(col==6)
		{
			printf("定位到%d号的入学时间\n",Temp);
			printf("请输入您的修改后的内容:");
			scanf("%s",List->Time);
		}
		else if(col==7)
		{
			printf("定位到%d号的电话号码\n",Temp);
			printf("请输入您的修改后的内容:");
			scanf("%s",List->number);
		}
		else	//若col不在范围内,报错
		{	
			printf("请输入合法的列号\n");
		}
	}
	else		//如果是负或0的序号
	{
		printf("请输入合法的序号\n");
	}
}
void List_ChaRu(struct Student *head,int lin)	//插入函数
{
	struct Student* List_begin;	//前一个
	struct Student* List_end;	//后一个
	struct Student* Temp;		//中间插的
	List_begin=head->pNextNode;	
	List_end=List_begin->pNextNode;//将后一个指针接于前一个指针后
	while(lin>1)	//寻找目标位置
	{
		lin=lin-1;
		List_begin=List_begin->pNextNode;
		List_end=List_begin->pNextNode;
	}
	if(lin==1)		//找到了
	{
		Temp=(struct Student*)malloc(150);	//创建新链表
		printf("请输入学生的学号 ,姓名 ,年龄 ,性别(b/g) ,家庭住址 ,入学时间(xx/xx/xx)  家庭电话号码。(中间空格隔开)\n");
		scanf("%s %s %s %s %s %s %s",Temp->ID,Temp->name,Temp->age,Temp->sex,Temp->address,Temp->Time,Temp->number);
		List_begin->pNextNode=Temp;//插在目标位置
		Temp->pNextNode=List_end;
	}
	else	//序号为0或负,报错
	{
		printf("输入不合法!\n");
	}
}
void List_ShanChu(struct Student* head,int lin)
{
	struct Student* List_begin;	//前一个
	struct Student* Temp;		//删除目标
	Temp=head->pNextNode;
	List_begin=head;
	while(lin>1)		//寻找
	{
		lin=lin-1;
		List_begin=Temp;
		Temp=Temp->pNextNode;
	}
	if(lin==1)		//找到了,删除
	{	
		List_begin->pNextNode=Temp->pNextNode;	//让前一个指针指向后一个指针
		printf("删除成功!\n");
	}
	else	//序号错误
	{
		printf("输入非法序号\n");
	}
}
void List_ChaZhao(struct Student* head,int aim)	//目前只有两种查找方式
{
	struct Student* List;
	char ID[15];
	int sum;	//查找的序号或者学号
	int Temp;	//临时存储信息
	List=head->pNextNode;
	if(aim==0)
	{
		printf("请输入查找的序号:");
		scanf("%d",&sum);
		Temp=sum;
		while(sum>1)		//寻找查找序号目标
		{
			List=List->pNextNode;
			sum=sum-1;
		}
		if(sum==1)			//找到了
		{
			printf("序号%d:  ",Temp);
			printf("%s %s %s %s %s %s %s\n",List->ID,List->name,List->age,List->sex,List->address,List->Time,List->number);
		}
		else				//没找到
		{
			printf("输入序号不合法\n");
		}
	}
	else if(aim==1)			//寻找查找学号目标
	{
		printf("请输入查找的学号:");
		scanf("%s",ID);
		while(List!=NULL)
		{
			if(strcmp(List->ID,ID)!=0)
			{
				List=List->pNextNode;
			}
			else
			{
				break;
			}
		}
		if(strcmp(List->ID,ID)==0)		//找到了
		{
			printf("学号%s:  ",ID);
			printf("%s %s %s %s %s %s %s\n",List->ID,List->name,List->age,List->sex,List->address,List->Time,List->number);
		}
		else				//没找到
		{
			printf("没有该学号的数据!\n");
		}
	}
	else			//查找方式错误
	{
		printf("输入查找目标不合法\n");
	}
}
void List_PaiXv(struct Student* head)
{
	//本代码将采用简单的冒泡排序法.
	struct Student* List_begin_1;	//第一轮循环前一个
	struct Student* List_begin_2;	//第二轮循环前一个
	struct Student* List_in_2;	//第二轮循环中间一个
	struct Student* List_end_2;	//第二轮循环后一个
	List_begin_1 = head;
	while(List_begin_1->pNextNode->pNextNode!=NULL)		//以下为简单的冒泡排序法
	{
		List_begin_2 = head;
		List_in_2 = List_begin_2->pNextNode;
		List_end_2 = List_in_2->pNextNode;
		while(List_end_2!=NULL)
		{
			if(strcmp(List_in_2->ID,List_end_2->ID)>0)
			{
				List_begin_2->pNextNode=List_end_2;
				List_in_2->pNextNode=List_end_2->pNextNode;
				List_end_2->pNextNode=List_in_2;
				List_in_2 = List_begin_2->pNextNode;
				List_end_2 = List_in_2->pNextNode;
			}
				List_begin_2=List_begin_2->pNextNode;
				List_in_2=List_in_2->pNextNode;
				List_end_2=List_end_2->pNextNode;	
		}
		List_begin_1=List_begin_1->pNextNode;
	}
}
void List_fLuRu(struct Student* head)		//装入函数
{
	FILE* fp;	//文件指针
	int n=0;		//数组的位置
	int state=0;//链表的位置
	char ch;	//录入字符
	struct Student* List;//链表指针
	struct Student* Temp;
	List=(struct Student*)malloc(150);
	head->pNextNode=List;
	if((fp=fopen("C:\\Users\\池上桜\\Desktop\\学习\\课设\\Project\\data.txt","r+"))==NULL)	//打开文件
	{
		printf("No file!\n");
		exit(0);
	}
	while(!feof(fp))
	{
		ch=fgetc(fp);
		if(ch!='\n')//换行
		{
			if(ch!=' ')	//空格切换一次链表位置
			{
				if(state==0)	//链表在ID位置,以下同理
				{
					List->ID[n]=ch;
					List->ID[n+1]='\0';
				}
				else if(state==1)
				{
					List->name[n]=ch;
					List->name[n+1]='\0';
				}
				else if(state==2)
				{
					List->age[n]=ch;
					List->age[n+1]='\0';
				}
				else if(state==3)
				{
					List->sex[n]=ch;
					List->sex[n+1]='\0';
				}
				else if(state==4)
				{
					List->address[n]=ch;
					List->address[n+1]='\0';
				}
				else if(state==5)
				{
					List->Time[n]=ch;
					List->Time[n+1]='\0';
				}
				else if(state==6)
				{
					List->number[n]=ch;
					List->number[n+1]='\0';
				}
				else
				{
					printf("格式有误!");
					exit(0);
				}
				n++;
			}
			else
			{
				state=state+1;
				n=0;
			}
		}
		else
		{
			Temp = (struct Student*)malloc(150);
			List->pNextNode=Temp;
			List=Temp;
			List->pNextNode=NULL;
			n=0;
			state=0;
		}
	}
	fclose(fp);
}
void List_fCunChu(struct Student* head)
{
	FILE* fp;	//文件指针
	struct Student* List;//链表指针
	List=head->pNextNode;
	if((fp=fopen("C:\\Users\\池上桜\\Desktop\\学习\\课设\\Project\\sum.txt","w+"))==NULL)	//打开文件
	{
		printf("No file!\n");
		exit(0);
	}
	while(List->pNextNode!=NULL)
	{
		fputs(List->ID,fp);
		fputc('\0',fp);
		fputs(List->name,fp);
		fputc('\0',fp);
		fputs(List->age,fp);
		fputc('\0',fp);
		fputs(List->sex,fp);
		fputc('\0',fp);
		fputs(List->address,fp);
		fputc('\0',fp);
		fputs(List->Time,fp);
		fputc('\0',fp);
		fputs(List->number,fp);
		fputc('\n',fp);
		List=List->pNextNode;
	}
		fputs(List->ID,fp);
		fputc('\0',fp);
		fputs(List->name,fp);
		fputc('\0',fp);
		fputs(List->age,fp);
		fputc('\0',fp);
		fputs(List->sex,fp);
		fputc('\0',fp);
		fputs(List->address,fp);
		fputc('\0',fp);
		fputs(List->Time,fp);
		fputc('\0',fp);
		fputs(List->number,fp);
		fclose(fp);
}

 line_list.h code

#ifndef __LINE_LIST_H
#define __LINE_LIST_H

struct Student {
    char ID[15];          	//学生学号
    char name[10];     	//学生姓名
    char age[3];			//学生年龄
	char sex[5];			//性别
	char address[30];	//住址
	char Time[15];		//入学时间
	char number[15];		//电话号码
    struct Student * pNextNode;
};

void List_LuRu(struct Student *head);
void List_XianShi(struct Student *head);
void List_XiuGai(struct Student *head,int lin,int col);
void List_ChaRu(struct Student *head,int lin);
void List_ShanChu(struct Student* head,int lin);
void List_ChaZhao(struct Student* head,int aim);
void List_PaiXv(struct Student* head);
void List_fLuRu(struct Student *head);	//装入
void List_fCunChu(struct Student* head); //存储
#endif

Note that in the last line of the header file, leave a blank line to prevent some metaphysical errors.

3. Full code analysis

A. The code in the main function main.cpp:

        Since the logic of the code in main.cpp is simple, only one column is needed to explain it clearly.

        First, create an empty linked list as the head node. This creation method is the standard linear list creation method in the official data structure book, which can facilitate many operations in the future (such as sorting). Then let the next item of the linked list point to NULL, as At the end of the judgment, this linked list is where all the data is stored.

        Then use scanf to receive the operation that the user wants to perform, and continuously ask the user's needs in the while loop to achieve the purpose of managing the system. A second scanf needs to be added to each second-level while to receive the user after using a function intention.

        This is roughly the content of the main function.

B. The code of the header file line_list.h:

        line_list.h is a simple header file. What needs to be said here is the structure inside. Here, the structure cannot be renamed as Student, otherwise an error will be reported. Although I don’t know why, just follow the above The practice of code will not be disturbed by metaphysics.

C. The code of the function library line_list.cpp:

        Analyze from top to bottom

a. Input function

        Input is to connect the data to the next bit of the current linked list. Therefore, it needs to be input as the head node, and the last node of the current linked list is found by the while loop, and then the linked list is created, the content is entered, and the linked list is connected to the last one. node, and then point the next bit of the last node to NULL.       

        NULL is used to judge the tail of the linked list, which undoubtedly reflects its excellent functionality here.

       code:d8d7579564384e8dba5d0a5d0ab43335.png

 b. Display function

        Why put the display function in such a top position? This is of course because only with display can you know whether there is any problem with your writing.

        The display function starts after the head node and displays the data in each table until NULL.

        d69dfa6fc18d48f3b070ae3808cb901a.png

c. Modify function

        The modification requires the user to choose the content to be modified, so the input is a serial number and a column number. The serial number refers to the serial number of the data in the current linked list displayed through display, and the column number is the target of modification (for example, the student number is 1)

        Also first use while to find the data that needs to be modified, and then use the if statement to determine the column number, which can be accurately modified.

     da99426d2bac45f6a67f4e984577251f.png

(part) 

d. Insert function

        Display the linked list first, and ask how much it needs to be inserted after the serial number. Define the pointers of the front, middle and back three linked lists in the function, and connect the three pointers after finding the position.

9afcfb747a0c4914b9772a30e00eb7c2.png

e. Delete function

        The deletion operation also requires multiple pointers. After finding the position, change the last one of the previous pointer to the next one of the deletion target, you can directly skip the deletion target, and finally free

b4aae42c65c6464bb7ef91134cf056dd.png

 f. Find function

        The search function is the simplest logically, and it only needs to judge whether it is consistent with the search target. Therefore, I will not repeat it here.

g. Sorting function

        In the sorting function, the bubble sorting method is used. The specific implementation is as follows. In this function, the advantage of turning the head pointer into empty is reflected. One more pointer avoids if to judge whether it is a head pointer.

        

void List_PaiXv(struct Student* head)
{
	//本代码将采用简单的冒泡排序法.
	struct Student* List_begin_1;	//第一轮循环前一个
	struct Student* List_begin_2;	//第二轮循环前一个
	struct Student* List_in_2;	//第二轮循环中间一个
	struct Student* List_end_2;	//第二轮循环后一个
	List_begin_1 = head;
	while(List_begin_1->pNextNode->pNextNode!=NULL)		//以下为简单的冒泡排序法
	{
		List_begin_2 = head;
		List_in_2 = List_begin_2->pNextNode;
		List_end_2 = List_in_2->pNextNode;
		while(List_end_2!=NULL)
		{
			if(strcmp(List_in_2->ID,List_end_2->ID)>0)
			{
				List_begin_2->pNextNode=List_end_2;
				List_in_2->pNextNode=List_end_2->pNextNode;
				List_end_2->pNextNode=List_in_2;
				List_in_2 = List_begin_2->pNextNode;
				List_end_2 = List_in_2->pNextNode;
			}
				List_begin_2=List_begin_2->pNextNode;
				List_in_2=List_in_2->pNextNode;
				List_end_2=List_end_2->pNextNode;	
		}
		List_begin_1=List_begin_1->pNextNode;
	}
}

h. Load function

        Flexible use of file functions. In this code, fgetc is used to obtain data from files one by one, which is convenient for judging \n and other content. It should be noted that the last line cannot be hit with the Enter key.

void List_fLuRu(struct Student* head)		//装入函数
{
	FILE* fp;	//文件指针
	int n=0;		//数组的位置
	int state=0;//链表的位置
	char ch;	//录入字符
	struct Student* List;//链表指针
	struct Student* Temp;
	List=(struct Student*)malloc(150);
	head->pNextNode=List;
	if((fp=fopen("C:\\Users\\池上桜\\Desktop\\学习\\课设\\Project\\data.txt","r+"))==NULL)	//打开文件
	{
		printf("No file!\n");
		exit(0);
	}
	while(!feof(fp))
	{
		ch=fgetc(fp);
		if(ch!='\n')//换行
		{
			if(ch!=' ')	//空格切换一次链表位置
			{
				if(state==0)	//链表在ID位置,以下同理
				{
					List->ID[n]=ch;
					List->ID[n+1]='\0';
				}
				else if(state==1)
				{
					List->name[n]=ch;
					List->name[n+1]='\0';
				}
				else if(state==2)
				{
					List->age[n]=ch;
					List->age[n+1]='\0';
				}
				else if(state==3)
				{
					List->sex[n]=ch;
					List->sex[n+1]='\0';
				}
				else if(state==4)
				{
					List->address[n]=ch;
					List->address[n+1]='\0';
				}
				else if(state==5)
				{
					List->Time[n]=ch;
					List->Time[n+1]='\0';
				}
				else if(state==6)
				{
					List->number[n]=ch;
					List->number[n+1]='\0';
				}
				else
				{
					printf("格式有误!");
					exit(0);
				}
				n++;
			}
			else
			{
				state=state+1;
				n=0;
			}
		}
		else
		{
			Temp = (struct Student*)malloc(150);
			List->pNextNode=Temp;
			List=Temp;
			List->pNextNode=NULL;
			n=0;
			state=0;
		}
	}
	fclose(fp);
}

i. Storage function

        Use fputs to store all the content of the linked list into a file. Remember, add '\0' after each one to indicate the end.

void List_fCunChu(struct Student* head)
{
	FILE* fp;	//文件指针
	struct Student* List;//链表指针
	List=head->pNextNode;
	if((fp=fopen("C:\\Users\\池上桜\\Desktop\\学习\\课设\\Project\\sum.txt","w+"))==NULL)	//打开文件
	{
		printf("No file!\n");
		exit(0);
	}
	while(List->pNextNode!=NULL)
	{
		fputs(List->ID,fp);
		fputc('\0',fp);
		fputs(List->name,fp);
		fputc('\0',fp);
		fputs(List->age,fp);
		fputc('\0',fp);
		fputs(List->sex,fp);
		fputc('\0',fp);
		fputs(List->address,fp);
		fputc('\0',fp);
		fputs(List->Time,fp);
		fputc('\0',fp);
		fputs(List->number,fp);
		fputc('\n',fp);
		List=List->pNextNode;
	}
		fputs(List->ID,fp);
		fputc('\0',fp);
		fputs(List->name,fp);
		fputc('\0',fp);
		fputs(List->age,fp);
		fputc('\0',fp);
		fputs(List->sex,fp);
		fputc('\0',fp);
		fputs(List->address,fp);
		fputc('\0',fp);
		fputs(List->Time,fp);
		fputc('\0',fp);
		fputs(List->number,fp);
		fclose(fp);
}

Summarize:

        The difficulty is extremely low (if the file is not included), it is indeed too simple as a course setting.

        This course is designed to consolidate content such as sorting, searching, linked lists, structures, files, etc. It covers a wide range of topics and is rich in content. It is a good exercise for beginners.

        Carry forward the spirit of open source, starting from freshman~

 

Guess you like

Origin blog.csdn.net/ChiShangying/article/details/130815242