成绩分析系统(数据结构)

成绩分析系统(数据结构)作业记录

1. 题目说明
成绩分析系统
建立一个学生链表,每个结点包括学号、姓名、班级、语文数学英语三门课程成绩等数据项。实现如下功能(设计菜单):
(1)成绩录入。学生的基本信息(学号、姓名、班级)应通过其他文件成批导入;学生的成绩通过键盘输入和修改,最终的完整数据应能保存到数据文件中input.dat,并能从文件中导入已有数据。
(2)按指定的课程成绩排序。 
输入指定的课程名,按指定课程的成绩进行排序,生成相应的文件并输出。
(3)按学生的平均成绩排序。 
按学生的平均成绩进行排序,生成相应的文件并输出。     
(4)成绩分析与统计。
统计每门课程的平均成绩、最高分、最低分、不及格人数、60~69分人数、70~79分人数、80~89分人数、90分以上人数,输出上述统计结果。     
(5)按学号查询。输入学生的学号,查询并输出该学生的各科成绩、平均成绩和总分的名次。     
(6)按姓名查询。输入学生的姓名,查询并输出该学生的各科成绩、平均成绩和总分的名次。若有重名的学生,则要求输入学号进行查询。
2. 设计方案

  1. 数据结构设计(线性表?树?图?要将数据结构设计结果描述清楚)
    利用链式线性结构体Stu数据域存储学生信息,学生姓名、班级、年级、学生各科成绩为字符串型,学生编号为整型,指针域存储下一个指针地址。
  2. 程序功能框架概要设计(菜单、函数调用关系图、主要函数的功能说明等)
    (1)功能菜单
    功能菜单图

(2)函数调用关系图
函数调用关系图

(3)主要函数功能说明
//链表操作函数
Stu *InitList(int num)初始化链表 ,返回头指针
Stu *NextItem(Stu *plist)传入当前结点,返回下一结点
void AddItem(Stu *plist)尾插结点,传入头结点,遍历到NULL,将尾部的指针域指向尾部新结点
void InitItem(Stu *plist)初始化结点,将plist指向一个空链表,并初始化数据域
Stu *SearchItem(int num,Stu *phead)传入头指针,返回编号为num的结点位置
//功能函数
void Display(Stu *p_head)输出学生信息
void InitSys(Stu *p_head)输入学生信息(初始化系统)
void SaveFile(Stu *p_head)保存文件
int Sort(Stu *p_head,int n_ID,int n_subject)年级排名,传入头指针、学生编号、所要排名的数据类型
int ClassSort(Stu *p_head,int n_ID,int n_subject)班级排名,传入头指针、学生编号、所要排名的数据类型
void Search(Stu *p_head,char *name)搜索学生信息,传入头指针,传入学生姓名
void Del(Stu *p_head,int n_ID)删除表,传入头指针,传入删除学生编号
void Del2(Stu *p_head,int n_ID)删除表,传入头指针,传入删除学生编号
double Strtodouble(char *str)传入符串返回double型函数,若传入其他字符串,则返回-1
double Average(Stu *p_head,int n_ID)计算平均分
void AddList(Stu *p_head)尾部添加新同学
void Change(Stu *p_head)修改
void InputScore(Stu *start , Stu *end , Stu *p_head ,char *subject)单科学习成绩录入,传入开始录入位置和结束录入位置,传入头指针 ,传入需要录入的学科
void ShowItem(Stu *p_list,Stu *p_head)传入指针,输出其学生信息
void Fprint(Stu *p_head)将数据导出到当前路径下的StudentInformation.txt
void Fprint2(Stu *p_head)将数据导出到input.dat
void ClassSortOutput(Stu *p_head,char *str_class,int subject)传入头指针,传入班级,传入学科
void SubjectSort(Stu *p_head,int subject)年级学科排名
void AverageSort(Stu *p_head)平均分排序
void Insert(Stu *p_head)在中间插入一个表
void Statistics(Stu *p_head)统计成绩
void Most(Stu *p_head,int subject)最高分最低分
void Averagesubject(Stu *p_head,int subject)各科平均成绩

  1. 具体算法详细设计
    (1) 遍历并输出列表
    传入头指针,传入当前结点,传出下一节点。如此循环调用输出学生信息的函数。
    (2) 查找学生
    根据姓名查找学生:获取输入的姓名,传入头指针和姓名,定义sign== 0, 在链表中查找是否有姓名与传入的姓名相等的结点,当有此结点时,sign== 1,并且输出该结点学生信息,如果sign==0,则提示“无此学生”。
    根据编号查找学生:获取输入的编号,传入头指针和编号,在链表中查找是否有此编号,如果没有此编号,则提示“未找到这个编号”,如果有此编号则输出该编号学生信息。
    (3) 删除学生
    输入学生编号,如果输入的编号不正确会提示“没有输入正确的编号”,如果输入编号正确,则传入头指针和被删除学生编号,删除函数先释放内存空间,然后删除结点的前后关联,将指针域指向被删除结点的后继结点。
    (4) 尾部添加学生
    将指针移至链表末尾,调用尾插结点的方法,传入前置结点,遍历到null,将将尾部的指针域指向尾部新结点 ,完成添加,然后对结点写入学生姓名、学生班级等数据。
    (5) 修改学生信息
    输入被修改学生编号,通过编号搜索结点位置,如果未找到则提示“未找到编号”,如果找到则输出该学生信息,并提示用户选择要修改的信息(A:姓名,B:班级,C:数学成绩,D:语文成绩,E:英语成绩),选择后输入修改内容,将要修改内容插入结点中,如果输入的格式不正确,系统会提示“请输入正确格式”。
    (6) 输出年级平均分排序,并将排序内容保存在averagesort.dat文件中。
    传入头指针,对平均分进行排序,将数据存储到list数组中,如果排序成功则num加一,最后根据num循环输出list中的学生信息和平均分,并将数据插入到文件averagesort.dat中。
    (7) 录入学生单科成绩
    输入起始位置编号和终点位置编号,输入要录入的学科(A:数学B:语文C:英语),找到要录入成绩结点编号的开始循环,依次插入要录入的成绩,直到终点。
    (8) 将数据导出到文件
    打开指定文件,将链表循环将各个结点信息写入打开文件,最后循环结束,关闭文件。
    (9) 根据班级对成绩进行排序
    输入班级,传入头指针,传入班级,传入学科,循环链表,如果传入班级与链表中的班级相同,则开始排序,将数据保存到list中,最后循环输出排序结果。
    (10) 成绩年级排序,并将相关数据写入相关文件。
    输入排序学科,传入头指针,传入学科,循环链表,对传入学科进行排序,最后循环输出成绩并写入文件。
    (11) 成绩分析
    对链表进行循环,用if else 方法进行判断,如果满足条件则相应数值加一,循环完成后输出所有统计数值。对所有各科成绩进行排序,输出最高分和最低分。计算所有科目的平均分,并将它们输出。
    (12) 插入学生
    在表中插入一个结点,输入想添加的位置,分配新结点,依次输入学生姓名、班级各科成绩等数据,搜索新结点插入位置的前后结点,对后续结点编号加一,将新增结点前一结点指向新结点,将新结点指向后一结点,完成关联。

3 运行截图

  1. 程序开始时,如果目录下有文件会读取文件并显示菜单,没有就会创建新文件并要求输入学生数据。以下是有文件的情况:
    菜单
  2. 输出所有学生信息,显示列出所有学生的所有信息,以下测试20条数据,接下来的操作基于这20条数据进行。
    学生数据
    3 增、删、查、改
    增加学生数据
    删除学生操作
    查找学生操作
    修改学生操作
    4 其他操作不做说明

4. 源代码
main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include "list.h"
#include "list.cpp"
#include "menu.h"
#include "menu.cpp"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) 
{
      SetConsoleTitle("学生管理系统"); 
    printf("当前运行目录%s\n",argv[0]); 
    Stu *p_head = NULL;
//文件读取层 
    FILE *pf; 
    int i,num;
	int sign=0; 
	  //未找到文件需要初始化文件
	if((pf = fopen("data.wwy","r")) == NULL)
	    {
   
	      sign=1; //标记
	    }
	fclose(pf);   
	if(sign == 1)
	{
   
	printf("首次使用未找到历史文件,请初始化文件,请输入学生数量(输入0,则不录入任何数据):");
	    while(scanf("%d",&num)!=1 || num<0)
		{
   
		printf("提示:你没有输入正确值,请重新输入:");
		fflush(stdin);//while(getchar()!='\n');
	    }
	    fflush(stdin);
	     p_head = InitList(num);  //开num个空间的链表 
	     InitSys(p_head);      //输入数据域 
	     SaveFile(p_head);   //保存文件 
	     printf("欢迎来到学生管理系统\n");
     }
     else
	{
      
    if((pf = fopen("data.wwy","rb")) == NULL) 
	{
      
	   exit(1);   
	}
         //找到文件,将文件读入链表 
	    p_head = InitList(0);
	    Stu *p_temp = p_head;
        while(fread(p_temp,sizeof(struct Stu),1,pf) == 1)
		{
       
			AddItem(p_temp); 
		    p_temp = NextItem(p_temp);
		}
		Del(p_head,p_temp->m_nSign);
		printf("提示:读取成功\n欢迎来到学生管理系统\n");
		fclose(pf);
	}

//工作层 
	while(1)
	{
   
		Mainmenu(p_head);
	}
	
	return 0;
}	

list.cpp

#include "list.h" 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void InitItem(Stu *plist) //初始化结点,将plist指向一个空链表
{
        
      strcpy(plist->m_nChinese,"0");
      strcpy(plist->m_nEnglish,"0");
      strcpy(plist->m_nMath,"0");
      plist->m_pNext = NULL;
} 

void AddItem(Stu *plist)  //尾插结点,传入前置结点,遍历到NULL,将尾部的指针域指向尾部新结点 ,完成添加 
{
      
	struct Stu *temp = (struct Stu*)malloc(sizeof(struct Stu));
	if(temp == NULL)
    {
   
    	printf("空间分配失败\n");
    	exit(-1);	 
    }
	InitItem(temp); 
	temp->m_nSign=plist->m_nSign+1;
	plist->m_pNext=temp;
	temp->m_pNext=NULL;
}
Stu *NextItem(Stu *plist) //传入当前结点,传出下一结点 
{
      if(plist==NULL)
	return NULL;
	else
	return plist->m_pNext;
}

Stu *InitList(int num) //初始化链表 
{
      int i;
	struct Stu *phead = (struct Stu*)malloc(sizeof(struct Stu)); //创建头结点,编号为0,不存任何数据 
	struct Stu *temp = phead;
	if(phead == NULL)
    {
   
    	printf("空间分配失败\n");
    	exit(-1);	 
    }
    phead->m_pNext = NULL;
    InitItem(phead);
	phead->m_nSign = 0;
	for(i=1;i<=num;i++)
	{
   
		AddItem(temp);
		temp=NextItem(temp); 
		temp->m_nSign = i; 
	}
	return phead;
}

Stu *SearchItem(int num,Stu *phead)  //传入头指针,返回编号为num的结点位置 
{
      struct Stu *temp = phead;
    while(temp)
    {
   
		if(num == temp->m_nSign)
    	{
   
    		return temp;
		}
		else
		{
   
			temp = NextItem(temp); 
		}
	}
	return NULL;
} 

list.h

#ifndef _LIST_H_
#define _LIST_H_
//构造数据域和结点 
struct Stu
{
      //数据域 
    int  m_nSign;
	char m_strName[999]; //学生基本信息 
	char m_strClass[999];
	char  m_nMath[999]; //各科成绩及对应排名
	char  m_nChinese[999];
	char  m_nEnglish[999];
	char  m_nComputer[999];
	//结点 
	Stu *m_pNext;
};
//链表操作函数 
Stu *InitList(int num); //初始化链表 ,返回头指针 
Stu *NextItem(Stu *plist);//传入当前结点,返回下一结点 
void AddItem(Stu *plist);  //尾插结点,传入头结点,遍历到NULL,将尾部的指针域指向尾部新结点
void InitItem(Stu *plist); //初始化结点,将plist指向一个空链表,并初始化数据域
Stu *SearchItem(int num,Stu *phead);  //传入头指针,返回编号为num的结点位置

menu.cpp

//函数定义
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "menu.h"
//系统操作函数 
void Mainmenu(Stu *p_head)  //主菜单显示函数 
{
       if(p_head == NULL)
     {
   
	    printf("提示:空间分配错误,请重新打开程序尝试") ; 
	    return; 
     } 
	 Adminmenu(p_head);
} 



void Adminmenu(Stu *p_head)  //管理员菜单显示函数 
{
      while(1)
    {
    
    printf("****************************************************\n");
	printf(" \t  功能菜单\n"); 
	printf(" \tA:输出所有学生信息 \n \tB:查找学生 \n \tC:删除学生 \n \tD:添加学生 \n \tE:修改学生信息 \n \tF:输出平均分排序 \n");
	printf(" \tG:学生单科成绩录入 \n \tH:保存为文件 \n \tI:输出班级单科排名 \n \tJ:输出年级单科排名 \n \tK:成绩分析与统计 \n \tL:插入学生 \n");
	printf("****************************************************\n");
	printf("请输入你要进行的操作:");
	Admininput(p_head);
	}	
}
 

void Admininput(Stu *p_head)   //管理员菜单输入函数
{
      char choice[999]="\0";
	gets(choice);
	if(strcmp(choice,"A")==0)
	{
   
		Display(p_head);
	}
	else if(strcmp(choice,"B")==0)
	{
     
		
		printf("选择查找方式(A:姓名查找 B:编号查找):");
		char cho[999]="\0"; 
		gets(cho);
		if(strcmp(cho,"A")==0){
   
			char name[999]="\0"; 
	   		printf("请输入你要查找学生姓名:");
	    	gets(name);
			Search(p_head,name);
		} 
		else if(strcmp(cho,"B")==0){
   
		int n_id;
		printf("请输入你要查找的学生编号:");
		 if(scanf("%d",&n_id)!=1)
		{
   
		printf("提示:你没有输入正确编号\n");
		fflush(stdin);//while(getchar()!='\n');
		}else{
   
			fflush(stdin);
			Search(p_head,n_id);
		}
		
		}
		
		
	}
	else if(strcmp(choice,"C")==0)
	{
      int n_ID ;
	    printf("请输入你要删除的学生的编号:");
	    if(scanf("%d",&n_ID)!=1)
		{
   
		printf("提示:你没有输入正确编号\n");
		fflush(stdin);//while(getchar()!='\n');
	    }
		else 
		{
   
		fflush(stdin);
		Del2(p_head,n_ID);
	    //printf("提示:删除成功\n"); 
	    
	    SaveFile(p_head); 
	    }
	}
	else if(strcmp(choice,"D")==0)
	{
      int num,num1;
	    printf("请输入你要添加学生的数量:");
	    if(scanf("%d",&num)!=1)
		{
   
		printf("提示:你没有输入正确数量\n");
		fflush(stdin);
	    } 
	    fflush(stdin);
	    num1=num; 
	    while(num)
	    {
   
	    printf("提示:你当前正在添加第%d个学生\n",num1-num+1);
		AddList(p_head); 
		num--;
		}  
	    SaveFile(p_head);
	}
	else if(strcmp(choice,"E")==0)
	{
      
	    Change(p_head);
		SaveFile(p_head); 
	}
	else if(strcmp(choice,"F")==0)
	{
      
		AverageSort(p_head);
	}
	else if(strcmp(choice,"G")==0)
	{
      int start;
	    int end;
	    char subject[999];
	    printf("请输入起始位置编号:");
	    if(scanf("%d",&start)!=1)
		{
   
		printf("提示:你没有输入正确编号\n");
		fflush(stdin);
		return;
	    }
	    fflush(stdin);
	    Stu *temp1=SearchItem(start , p_head);
        if(temp1==NULL || temp1->m_nSign==0)
        {
   
   	    	printf("提示:起始位置错误\n");
   	  		return;	
   		}
	    printf("请输入终点位置编号:");
	    if(scanf("%d",&end)!=1)
		{
   
		printf("提示:你没有输入正确编号\n");
		
  • 11
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值