(一) 需求和规格说明
对一次歌手比赛的成绩进行管理,功能要求:
1、输入每个选手的数据包括编号、姓名、十个评委的成绩,根据输入计算
出总成绩和平均成绩(去掉最高分,去掉最低分)。
2、显示主菜单如下:
1)输入选手数据
2)评委打分
3)成绩排序(按平均分)
4)数据查询
5)追加选手数据
6)写入数据文件
7)退出系统。
(二) 设计
根据上述需求,运用链表存储歌手的数据,
1.数据的生成
歌手比赛选手首先我们需要歌手的基本信息,将每一位用户的编号、姓名输入系统中,然后进行评委打分,之后我们对数据进行处理分析,计算出总分和平均值,并以.txt文件的格式储存起来。
2.数据的存储结构
考虑到一个宿舍的人员是有限的,所以可以用链表进行存储。宿舍的人员设计为结构体变量:struct singer{
long lNum;
char name[20];
float fScore[10];
float sum1, sum2, max, min, average;
struct singer *pNext;
};
其中包含选手编号、姓名、评委打分、总分(去除最高分和最低分)、最高分数、最低分数和平均分。然后我们在主函数当中定义一个结构指针struct singer *spHead,作为链表的头结点,然后依次创建下一个结构体对他们进行遍历输入存储。
3.功能的设计
函数功能的介绍
接收选手数据 :struct singer *CreatLiList(void);
评委打分:void score(struct singer *);
遍历输出数歌手数据:void TraverLiList(struct singer *);
追加选手数据:int AppendNode(struct singer *,long , char *, float*);
删除数据:int DeleteNode(struct singer *,long);
搜索数据:int SearchNode(struct singer *,long );
退出系统,删除链表数据:struct singer *ReleaseLiList(struct singer *);
链表数据根据平均分排序:struct singer* SortList(struct singer* );
将数据写入文件:将数据写入文件:void input(struct singer *);
- 输入选手数据
用户选择功能1之后,我们对输入的歌手的编号和姓名进行统计存储,直到用户输入-1时,我们默认接受数据完毕,返回主程序功能页面。
- 评委打分
用户选择功能1之后,我们要根据用户输入的歌手的编号先对链表进行查找,如果歌手编号输入错误,则提醒用户重新输入。找到该歌手之后,提醒用户输入的10评委的打分成绩,同时将他们存进结构体里面的数组,我们一边接受一边对成绩进行统计,将总分最高分和最低分计算出来,然后用总分减去最高分和最低分,然后除以8得到歌手的实际平均分数,这将作为我们下一步进行排序的重要依据。
(3)成绩排序(按平均分)
根据第二部统计出的平均分数,我们对链表数据进行插入排序。
思路: 插入排序,顾名思义就是在两个节点之间插入另一个节点,并且保持序列是有序的。如果当前要将节点cur插入到节点pre之后,我们只需要知道cur的前驱和插入位置(其实就是要插在哪个节点之后)就可以了。
(4)歌手数据查询
??????根据输入编号,对链表进行遍历循环,直到找到相应的歌手编号,并对他的成绩和个人信息进行输出。
- 追加选手数据
??????输入待追加的选手编号,我们将开辟在链表的最后开辟新的结构体变量内存单元,并对选手的姓名和评分进行录入。
(6)写入数据文件
??我们对歌手信息进行接受整理和排序之后将歌手的信息存入桌面下的txt文件中例如:C:\\Users\\fengling\\Desktop\\歌手比赛打分数据统计.txt。这样可以在桌面打开,然后查看歌手排序好的信息。
(7)遍历显示数据
考虑到对歌手的信息可能进行多次的修改,我们要检测程序运行的准确性。所以每一步操作之后,都可以选择功能7,对选手数据进行遍历输出。
- 删除选手数据
????考虑到对歌手可能退赛并没有参加比赛也没有相应的分数,所以我们可以从链表中删除该选手的编号和姓名信息,达到节约内存、方便显示管理的目的。
- 退出系统
?????退出系统时对链表内存进行释放,然后结束退出程序循环。
代码
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <fstream>
#include <string>
using namespace std;
struct singer{
long lNum;
char name[20];
float fScore[10];
float sum1, sum2, max, min, average;
struct singer *pNext;
};
const int SIZE = sizeof(struct singer);
//界面优化
class Interface
{
private:
int line;//操作数的行数
string *name;
static int nowline;
public:
void GetMessage(int line1,string *name1)
{
line=line1;
name=new string [line];
name=name1;
}
static void AddNowLine()
{
nowline++;
}
void ShowHead()
{
ShowSpace();
for(int i=0;i<50;i++)
{
if(i==0)
cout<<"╔";
else
{
if(i==49)
cout<<"╗";
else
cout<<"═";
}
}
cout<<endl;
AddNowLine();
}
void ShowSpace()
{
for(int x=0;x<12;x++)
cout<<" ";
}
void ShowOrderLine(int x)
{
int *number=new int[line];
for(int i=0,j=1;i<line;j++,i++)
number[i]=j;
int length;
length=name[x].length();
cout<<"║";
cout<<number[x]<<'.';
for(int temp=0;temp<46-length;temp++)//46-length==48-length-2
cout<<"-";
cout<<name[x];
cout<<"║";
}
void ShowSpaceLine()
{
cout<<"║";
for(int k=0;k<48;k++)
cout<<" ";
cout<<"║"<<endl;
}
void ShowEmptyLine()
{
if(nowline<14)
{
for(int i=nowline;i<=14;i++)
{
ShowSpace();
AddNowLine();
ShowSpaceLine();
AddNowLine();
}
}
}
void ShowBody()
{
for(int i=0,j=1;i<line;i++,j++)
{
ShowSpace();//前排的空格
AddNowLine();
ShowOrderLine(i);
cout<<endl;
ShowSpace();//前排的空格
AddNowLine();
ShowSpaceLine();
}
}
void ShowReturn()
{
ShowSpace();
AddNowLine();
cout<<"║9.";
for(int i=0;i<42;i++)
cout<<"-";
cout<<"退出║"<<endl;
}
void ShowEndLine()
{
ShowSpace();
for(int i=0;i<50;i++)
{
if(i==0)
cout<<"╚";
else
{
if(i==49)
cout<<"╝";
else
cout<<"═";
}
}
cout<<endl;
AddNowLine();
}
void ShowSurface()
{
ShowHead();
ShowBody();
ShowEmptyLine();
ShowReturn();
ShowEndLine();
}
};
int Interface::nowline=0;
//接收选手数据
struct singer *CreatLiList(void);
struct singer *CreatLiList(void)
{
struct singer *spHead,*spPre,*spCur;
long lv;
spPre = new struct singer;
//spPre = (struct singer *)malloc(SIZE);//头结点
if (spPre == NULL){
return NULL;
}
spHead = spPre;
spHead -> pNext = NULL;
do{
cout << "请输入歌手编号:";
cin >> lv;
if (lv != -1){
spCur = new struct singer;
//spCur = (struct singer *)malloc(SIZE);
spCur -> lNum = lv;
spCur -> sum1 = 0;
getchar();
cout << "请输入姓名:";
cin.getline(spCur -> name, 20);
spCur -> pNext = NULL;
spPre -> pNext = spCur;
spPre = spCur;
}
}while(lv != -1 );//以-1结束。
return spHead;
}
//评委打分
void score(struct singer *);
void score(struct singer *sp)
{
long lv;
struct singer *spCur;
do{
spCur = sp;
cout << "输入歌手编号:";
cin >> lv;
while(spCur -> pNext != NULL && spCur -> lNum != lv)
{
spCur = spCur -> pNext;
}
if (spCur ->lNum == lv){
spCur -> sum1 = 0;
cout << "请输入相应10位评委成绩:" ;
for(int i = 0; i < 10; i++)
{
cin >> spCur -> fScore[i];
spCur -> sum1 += spCur -> fScore[i];
if(i == 0)
{
spCur -> min = spCur -> fScore[0];
spCur -> max = spCur -> fScore[0];
}
else if(spCur -> fScore[i] > spCur -> max)
{
spCur -> max = spCur -> fScore[i];
}
else if(spCur -> fScore[i] < spCur -> min)
{
spCur -> min = spCur -> fScore[i];
}
}
spCur -> sum2 = (spCur -> sum1) - (spCur -> max) - (spCur -> min);
spCur -> average = spCur -> sum2 / 8.0f;
}
else
{
cout << "歌手编号输入错误,请重新";
}
} while (lv != -1 );//以-1结束。
}
//遍历输出数歌手数据
void TraverLiList(struct singer *);
void TraverLiList(struct singer *sp)
{
struct singer *spCur;
spCur = sp -> pNext;
while (spCur != NULL){
cout << "ID:" << setw(6) << spCur -> lNum << endl;
cout << "姓名: " << spCur -> name << endl;
cout << "十位评委打分成绩为:" << endl;
for(int i = 0; i < 10; i++)
cout << "第" << i + 1 << "评委打分为:" << setw(5) << fixed << setprecision(1) << spCur -> fScore[i] << endl;
cout << "去除最高分和最低分的总分为:" << spCur -> sum2;
cout << " 平均分数为:" << spCur -> average << endl;
cout << endl;
spCur = spCur -> pNext;
}
}
//追加选手数据
int AppendNode(struct singer *,long , char *, float*);
int AppendNode(struct singer *sp,long lArg, char *m, float *fArg)
{
struct singer *spCur,*spNew;
spCur = sp;
int i = 0, j = 0;
while(spCur -> pNext != NULL){
spCur = spCur -> pNext;
}
spNew = new struct singer;
if (spNew == NULL){
return 1;
}
spNew -> lNum = lArg;
for(m, j; *m; m++, j++)
{
spNew -> name[j] = *m;
}
spNew -> name[j] = '\0';
for(i = 0; i < 10; i++)
{
spNew -> fScore[i] = fArg[i];
}
for(i = 0; i < 10; i++)
{
spNew -> sum1 += spNew -> fScore[i];
if(i == 0)
{
spNew -> min = spNew -> fScore[0];
spNew -> max = spNew -> fScore[0];
}
else if(spNew -> fScore[i] > spNew -> max)
{
spNew -> max = spNew -> fScore[i];
}
else if(spNew -> fScore[i] < spNew -> min)
{
spNew -> min = spNew -> fScore[i];
}
}
spNew -> sum2 = (spNew -> sum1) - (spNew -> max) - (spNew -> min);
spNew -> average = spNew -> sum2 / 8.0f;
spNew -> pNext = NULL;
spCur -> pNext = spNew;
return 0;
}
//删除数据
int DeleteNode(struct singer *,long);
int DeleteNode(struct singer *sp,long lArg)
{
struct singer *spCur,*spT;
spCur = sp;
while(spCur -> pNext != NULL && spCur -> pNext ->lNum != lArg){
spCur = spCur -> pNext;
}
if (spCur -> pNext == NULL){
return 1;
}
spT = spCur -> pNext;
spCur -> pNext = spCur -> pNext -> pNext;
delete spT;//删除歌手的数据
return 0;
}
//搜索数据
int SearchNode(struct singer *,long );
int SearchNode(struct singer *sp,long lArg)
{
struct singer *spCur;
spCur = sp;
while(spCur -> pNext != NULL && spCur -> lNum != lArg){
spCur = spCur -> pNext;
}
if (spCur ->lNum == lArg){
cout << "ID:" << setw(12) << spCur -> lNum << endl;
cout << "name: " << spCur -> name << endl;
cout << "评委成绩为:" << endl;
for(int i = 0; i < 10; i++)
{
cout << setw(8) << fixed << setprecision(1) << spCur -> fScore[i] << endl;
}
cout << "去除最高分和最低分的总分为:" << spCur -> sum2;
cout << " 平均分数为:" << spCur -> average << endl;
return 0;
}
else
{
return 1;
}
}
//退出系统,删除链表数据
struct singer *ReleaseLiList(struct singer *);
struct singer *ReleaseLiList(struct singer *sp)
{
struct singer *spCurr,*spPrv;
spPrv = sp;
while (spPrv -> pNext != NULL){
spCurr = spPrv -> pNext;
delete spPrv;
spPrv = spCurr;
}
delete sp;
return NULL;
}
//链表数据根据平均分排序
struct singer* SortList(struct singer* );
struct singer* SortList(struct singer* head) {
if(!head || !head->pNext)
return head;
struct singer* dummy = NULL;
dummy = new singer[1];
dummy -> pNext = head;
struct singer* pre = head; // 当前节点的前驱
struct singer* cur = head->pNext;
while(cur != NULL){
struct singer* tmp = dummy;
if(pre-> average >= cur->average){ //需要进行插入
while(tmp->pNext->average < cur->average) //从第一个节点开始寻找插入位置
tmp = tmp->pNext; // cur应该插入在tmp后面
pre->pNext = cur->pNext; //断开节点cur
cur->pNext = tmp->pNext; //插入
tmp->pNext = cur;
cur = pre->pNext; //继续处理下一个节点
}
else{ //无需插入
pre = pre->pNext;
cur = cur->pNext;
}
}
cout << "歌手按平均分排序成功!请选择功能7遍历查看。";
system("Pause");
return dummy->pNext;
}
//将数据写入文件
void input(struct singer *);
void input(struct singer *sp)
{
fstream outFile;
outFile.open("C:\\Users\\fengling\\Desktop\\歌手比赛打分数据统计.txt", ios::out);
if (!outFile){
cout << "Destination file open error!";
cout << "文件写入错误";
exit(1);
}
else
{
cout << "文件写入中......" << endl;
}
struct singer *spCur;
spCur = sp -> pNext;
while (spCur != NULL){
outFile << "ID:" << setw(6) << spCur -> lNum << endl;
outFile << "姓名: " << spCur -> name << endl;
outFile << "十位评委打分成绩为:" << endl;
for(int i = 0; i < 10; i++)
outFile << "第" << i + 1 << "评委打分为:" <<setw(5) << fixed << setprecision(1) << spCur -> fScore[i] << endl;
outFile << "去除最高分和最低分的总分为:" << spCur -> sum2;
outFile << " 平均分数为:" << spCur -> average << endl;
outFile << endl;
spCur = spCur -> pNext;
}
outFile.close();
cout << "文件写入成功!请在桌面下打开查看。";
system("Pause");
}
int main(void)
{
struct singer *spHead = NULL;
int iIndex, iStatus = 0;
long lID;
float fScore[10];
system("color 5E");
do{
system("CLS");
cout << " ——————————*歌手评分系统*————————" << endl;
Interface x;
string *per=new string[10];
per[0]="输入选手数据";
per[1]="评委打分";
per[2]="成绩排序(按平均分)";
per[3]="歌手数据查询";
per[4]="追加选手数据";
per[5]="写入数据文件";
per[6]="遍历显示数据";
per[7]="删除选手数据 ";
x.GetMessage(8,per);
x.ShowSurface();
cout << "输入选择项:";
cin >> iIndex;
switch(iIndex)
{
case 1://输入选手数据。
system("CLS");
if (spHead != NULL){
ReleaseLiList(spHead);
spHead = NULL;
}
cout << "以空格分隔输入歌手遍号、姓名后回车确认(输入-1结束)\n";
spHead = CreatLiList();
break;
case 2://评委打分。
system("CLS");
if (spHead == NULL){
cout << "歌手数据未录入,请选择1输入数据!";
system("Pause");
break;
}
score(spHead);
break;
case 3://成绩排序。
system("CLS");
if (spHead == NULL){
cout << "歌手数据未录入,请选择1输入数据!";
system("Pause");
break;
}
SortList(spHead);
break;
case 4: //数据查询。
system("CLS");
if (spHead == NULL){
cout << "歌手信息未录入,请选择1输入数据!";
system("Pause");
break;
}
cout << "输入需要查找的歌手编号:";
cin >> lID;
iStatus = SearchNode(spHead,lID);
if (iStatus == 1){
cout << "The Id is not found!\n";
}
system("Pause");
break;
case 5://追加选手数据。
system("CLS");
if (spHead == NULL){
cout << "歌手信息未录入,请选择1输入数据!";
system("Pause");
break;
}
char str[20];
cout << "请输入编号:";
cin >> lID;
getchar();
cout << "请输入姓名:";
cin.getline(str,80);
cout << "请输入分数:";
for(int i = 0; i < 10; i++)
{
cin >> fScore[i];
}
iStatus = AppendNode(spHead, lID, str, fScore);
if (iStatus == 1){
cout << "添加失败!\n";
}
else{
cout << "添加成功!\n";
}
break;
case 6://写入文件
system("CLS");
if (spHead == NULL){
cout << "歌手信息未录入,请选择1输入数据!";
system("Pause");
break;
}
input(spHead);
break;
case 7://遍历显示数据。
system("CLS");
if (spHead == NULL){
cout << "歌手信息未录入,请选择1输入数据!";
system("Pause");
break;
}
cout << "歌手的数据为:\n";
TraverLiList(spHead);
system("pause");
break;
case 8://删除选手数据。
system("CLS");
if (spHead == NULL){
cout << "歌手信息未录入,请选择1输入数据!";
system("Pause");
break;
}
cout << "输入要删除结点的选手编号:";
cin >> lID;
iStatus = DeleteNode(spHead,lID);
if (iStatus == 1){
cout << "删除失败!\n";
}
else{
cout << "删除成功!\n";
}
system("Pause");
break;
case 9://退出系统
if (spHead != NULL){//释放链表
ReleaseLiList(spHead);
spHead = NULL;
}
exit(0);
default:
cout << "选择错误,请重新输入选择项!\n";
system("Pause");
}
} while(1);
return 0;
}
|