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);
}