学生信息管理系统(头哥适用版)(c语言)

Reborn Terran Emperor

由于最新pat不支持gets的使用,现在有两个解决思路

1.利用fgets,但fgets会保留换行符,需要对字符串修改,极其麻烦,不推荐

2.引入c++的cin.getline和gets一个作用,本篇是这样的,除了这个点,本文其他都是c语言

项目简介

考试报名工作给各高校报名工作带来了新的挑战,给教务管理部门增加了很大的工作量,报名数据手工录入既费时又会不可避免地出现错误。本项目是对考试报名管理的简单模拟,包括以下功能: 1.报名,输入考生信息:学号,姓名,报名科目; 2.列出全部报名信息:输出学号,姓名,报名科目; 3.查询某个科目的考生信息或者查询某个学号、姓名的报名信息; 4.修改信息:修改报名科目; 5.取消报名:删除某个考生的报名信息; 6.统计每个科目的报名人数

相关知识

本项目的数据是一组考生信息,每条考生信息由学号、姓名、报考科目信息组成,这组考生信息具有相同特性,属于同一数据对象,相邻数据元素之间存在序偶关系。由此可以看出,这些数据具有线性表中数据元素的性质,所以该系统的数据可以采用线性表来存储。 线性表的顺序存储结构的特点是:逻辑关系相邻的两个元素在物理位置上也相邻,因此可以随机存储表中任一元素,它的存储位置可用一个简单、直观的公式来表示。然而,从另一个方面来看,这个特点也铸成了这种存储结构的弱点:在做插入或删除操作时,需要移动大量元素。为克服这一缺点,有另一种存储形式――链式存储。链式存储是线性表的另一种表示方法,由于它不要求逻辑上相邻的元素在物理位置上也相邻,因此它没有顺序存储结构的弱点,但同时也失去了顺序表可随机存取的特点。 链式存储的优点是插入或删除元素时很方便,使用灵活。缺点是存储密度小,存储空间利用率低。事实上,链表插入、删除运算的快捷是以空间代价来换取时间。 顺序表适宜于做查找这样的静态操作;链表宜于做插入、删除这样的动态操作。若线性表的长度变化不大,且其主要操作是查找,则采用顺序表;若线性表的长度变化较大,且其主要操作是插入、删除操作,则采用链表。

编程要求

自定义数据结构(建议查阅vector,并使用vector实现),并完成必要的功能,可以使用C或者C++实现。 还必须自己实现主函数。 主函数接收输入,并调用相关接口或函数实现输出

测试说明

平台会对你编写的代码进行测试:

测试输入:(1 表示报名,5 表示5人 ,下面是5人的学号等信息) 1 5 001 lily math 002 nacy english 003 lulu math 004 kate operating system 005 bili math 2 //表示列出当前报名情况 预期输出: 001 lily math 002 nacy english 003 lulu math 004 kate operating system 005 bili math 3 math //查询math报名信息 预期输出: 001 lily math 003 lulu math 005 bili math 4 003 test//表示修改003 报名科目 为test 预期输出 001 lily math 002 nacy english 003 lulu test 004 kate operating system 005 bili math 5 004 //表示删除004的报名信息 预期输出 001 lily math 002 nacy english 003 lulu test 005 bili math 6 //按报名科目统计输出 预期输出 //按遇到的报名科目先后输出统计结果 math 2 english 1 test 1

#include <stdlib.h>
#include <stdio.h>
#include<string.h>
#include <bits/stdc++.h>//c++的万能头文件,用来引入cin.getline 
using namespace std;//同样是c++的固定语句 

/*1.报名,输入考生信息:学号,姓名,报名科目;
2.列出全部报名信息:输出学号,姓名,报名科目;
3.查询某个科目的考生信息或者查询某个学号、姓名的报名信息;
4.修改信息:修改报名科目;
5.取消报名:删除某个考生的报名信息;
6.统计每个科目的报名人数 */
 
//定义一个学生信息结构体 
struct node
{
  char num[20];  // 表示学号 
  char name[20] ; //表示姓名
  char subj[20] ;//表示科目 
  int number;//最后一个函数才会使用 
  struct node *next;  //指向下一个结点的指针 
};
 
//输出链表的函数 
void printlist(struct node *head)
{
	struct node *p;
	p=head->next;
	while(p!=NULL)
	{
		printf("%s %s %s",p->num,p->name,p->subj);
		printf("\n");
		p=p->next;
	 } 
}
//查找 
void findlist(struct node *head,char s[])
{
	struct node *p;
	p=head->next;
	while(p!=NULL)
	{
		if(!strcmp(p->subj,s))//这是一个字符串函数,比较asclla码,如果一样返回0 
		{
			printf("%s %s %s",p->num,p->name,p->subj);
			printf("\n");
		}
		p=p->next;
	 } 
}
//修改
struct node* changelist(struct node *head,char s[],char str[])
{
	struct node *p;
	p=head->next;
	while(p!=NULL)
	{
		if(!strcmp(p->num,s))//这是一个字符串函数,比较asclla码,如果一样返回0 
		{
			strcpy(p->subj,str);//复制 
			break;
		}
		p=p->next;
	 } 
	 return head;
 } 
 //删除 
 struct node* deletelist(struct node *head,char s[])
{
	struct node *p,*q;
	q=head;
	p=head->next;
	while(p!=NULL)
	{
		if(!strcmp(p->num,s))//这是一个字符串函数,比较asclla码,如果一样返回0 
		{
			q->next=p->next;
			free(p);
			p=p->next;
			break;
		}
		else{
			q=p;
			p=p->next;
		}
		
	 } 
	 return head;
 } 
 //最后一个函数 
 //再建立一个链表,和一个结构体(为了方便我直接利用第一个链表了,在里面加个int number) 
 //将遇到的第一个科目放在二链表的第一个结点,以此类推 
void fprint_list(struct node *head)
{
	struct node *p;
	p=head->next;
	
	struct node* head2=(struct node*)malloc(sizeof(struct node));//头结点
 	head2->next=NULL;
 	struct node* tail2;
 	tail2=head2;
 
 	struct node *q;
 	struct node* temp;//存放科目
	  
	while(p!=NULL)
	{
		//判断当前科目是否已经在二表,在的话就跳过 
		int sign=0;
		q=head2->next;
		while(q!=NULL)
		{
			if(!strcmp(p->subj,q->subj))
			{
				sign=1;//判断是否在的一个标志 
				break;
			}
			q=q->next;
		}
		if(sign==1)
		{
			p=p->next;
			continue;
		}
	
		struct node* newnode=(struct node*)malloc(sizeof(struct node));
	
		strcpy(newnode->subj,p->subj);//复制 ,将科目复制给新节点 
		newnode->number=1;//数目是1 
		temp=p;
		p=p->next;//从下一个结点开始比较 
		while(p!=NULL)
		{
			if(!strcmp(p->subj,newnode->subj))	//如果后面结点与现在的结点相同,就数量加1 
			{
			newnode->number++;
			}
			p=p->next;
		}
 		//尾插法创建链表
		newnode->next=tail2->next;
		tail2->next=newnode;
		tail2=newnode; 
		p=temp->next;
	} 
	 //开始打印 
	q=head2->next;
	while(q!=NULL)
	{
		printf("%s %d",q->subj,q->number);
//		puts(q->subj);
//		printf("%d",q->number);
		printf("\n");
		q=q->next;
	 } 
 
}
 
int main()
{
/*测试输入:(1 表示报名,5 表示5人 ,下面是5人的学号等信息)
1 5 
001 lily math
002 nacy english
003 lulu math
004 kate operating system
005 bili math*/
int a,n;
scanf("%d %d",&a,&n);
//建立链表并赋值
 struct node* head=(struct node*)malloc(sizeof(struct node));//头结点
 head->next=NULL;
 struct node* tail;
 tail=head;
 int i=1;
 while(i<=n)
 {	//建立新节点 
 	struct node* newnode=(struct node*)malloc(sizeof(struct node));
//	scanf("%s %s %s",&newnode->num,&newnode->name,&newnode->subj);
	scanf("%s %s ",&newnode->num,&newnode->name);//末尾多一个空格是为了吸收回车,否则回车会在缓冲区内,影响cin.getline的读取,导致多读一个回车 
//	gets(newnode->subj);//只能用gets,因为有的有空格 ,但最新的pat已经不支持gets 
	cin.getline(newnode->subj,sizeof(newnode->subj));
 	//尾插法创建链表
	 newnode->next=tail->next;
	 tail->next=newnode;
	 tail=newnode; 
	 i++;
 }
 
//2  //表示列出当前报名情况
//预期输出:
//001 lily math
//002 nacy english
//003 lulu math
//004 kate operating system
//005 bili math
int b;
scanf("%d",&b);
printlist(head);
//3 math //查询math报名信息
//预期输出:
//001 lily math
//003 lulu math
//005 bili math
int c;
char find[20]; 
scanf("%d ",&c);//末尾多一个空格是为了吸收回车,否则回车会在缓冲区内,影响cin.getline的读取,导致多读一个回车 
//gets(find); 
cin.getline(find,sizeof(find));
findlist(head,find);
 
//4  003 test//表示修改003 报名科目 为test
//预期输出
//001 lily math
//002 nacy english
//003 lulu test
//004 kate operating system
//005 bili math
int d;
scanf("%d",&d); 
char find2[20],change[20]; 
scanf("%s %s",&find2,&change);
head=changelist(head,find2,change);
printlist(head);
//5 004 //表示删除004的报名信息
//预期输出
//001 lily math
//002 nacy english
//003 lulu test
//005 bili math
int e;
scanf("%d",&e); 
char find3[20]; 
scanf("%s",&find3);
head=deletelist(head,find3);
printlist(head);
//6  //按报名科目统计输出
//预期输出  //按遇到的报名科目先后输出统计结果
//math 2
//english 1
//test 1
int f;
scanf("%d",&f); 
fprint_list(head);
 
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值