大作业:冬奥会志愿者信息管理系统
本作业要求稍显奇葩,要求所有操作都必须在.txt文本文件中进行,如下:
本次作业遇到的主要难题是FILE.eof()函数对文件的处理,如下:
运行过程中发现while进入了死循环。仔细勘察后发现,应该是FILE.get()读取了文本中的‘1’,导致FILE无法读取到任何数字字符 并传入num,导致FILE的文件指针不向后偏移,故而FILE.eof()始终为假,从而陷入死循环!
所以数字和文字混合读取时需要小心!
admin.cpp
#include<iostream>
#include<fstream>
#include"admin.h"
using namespace std;
using namespace adfile;
int main()
{
int cho;//菜单选项
int ID;//查找或删除的ID
admin_inf oper;
admin_inf::person* head;
head = oper.input("input.txt");//读取input.txt的信息,并创建链表,返回头节点
oper.input("menu.txt", cho);//读取菜单选项
if ( cho == 1)//查找
{
oper.input("find.txt",ID);//修改ID
oper.find(head, ID);
system("C:\\Users\\jiangyuxuan\\source\\repos\\冬奥会志愿者信息管理系统\\冬奥会志愿者信息管理系统\\out.txt");//直接弹出文件页面
}
else if (cho == 2)//添加
{
admin_inf::person* new_guys = oper.input("insert.txt", head);//链表末尾新加入了内容,用于在out.txt中显示;
oper.append(head,new_guys);//append()用于往input.txt中加入信息
oper.output(head,"out.txt");//将信息输出到out.txt
system("C:\\Users\\jiangyuxuan\\source\\repos\\冬奥会志愿者信息管理系统\\冬奥会志愿者信息管理系统\\out.txt");
}
else//删除
{
oper.input("find.txt", ID);//查ID;
admin_inf::person* new_head = oper.del(head, ID);//删除节点后返回新链表
oper.output(new_head, "out.txt");//输出新链表
system("C:\\Users\\jiangyuxuan\\source\\repos\\冬奥会志愿者信息管理系统\\冬奥会志愿者信息管理系统\\out.txt");
}
}
admin.h
#ifndef ADMIN
#define ADMIN
namespace adfile
{
class admin_inf
{
public:
struct person
{
int ID;
char name[20];
char sex;
double score;
int age;
char language[10];
struct person* next;
};
public:
person* input(const char* file_name);//读取 input 文件并创建链表
person* input(const char* fileName, person* q);//读取 insert 文件,并添加至链表末尾,返回新增人员的头节点,便于append
void input(const char* fileName, int& num);//读取 menu 文件或 find 文件
void output(person* head, const char* fileName);//将链表内容写入out.txt文件
void find(person* head, int ID);//查找 Id 为 no 的人员,并返回该结点前一结点便于删除函数调用
person* del(person* head, int ID);//从链表中删除 Id 为 no 的人员,返回链首
void append(person* head, person* s);//插入一名人员至链尾,返回链首
};
}
#endif // !ADMIN
admin_def.cpp
#include<iostream> #include<fstream> #include"admin.h" using namespace std; using namespace adfile; admin_inf::person* admin_inf::input(const char* file_name) //务必在函数名前加上admin_inf::!!!否则当外部函数处理!极易错沃日 { ifstream rFILE("input.txt", ios::in);//使用构造函数以只读模式打开文件 ofstream wFILE("out.txt", ios::out);//使用构造函数以写入模式打开文件 if (!rFILE) { wFILE << "打开" << file_name << "文件失败!"; wFILE.close(); exit(1); } admin_inf::person* head = new admin_inf::person;//创建头节点,不存放数据,方便删除第一个人的信息 head->next = NULL; admin_inf::person* temp = head; if (rFILE.peek()==EOF) { wFILE.close(); return head;//input中没有内容,返回头节点 } while (1) { admin_inf::person* node = new admin_inf::person;//创建节点 rFILE >> node->ID >> node->name >> node->age >> node->sex >> node->language >> node->score; head->next = node; head = node; rFILE.get(); //惊天大bug!eof()函数读取的是文件中最后一个字符的下一个字符(文件结束符0xFF)!所以会在末尾读两次!!!导致多建一个尾节点 if (rFILE.peek() == EOF) //所以这里必须要get(),将\n吃掉!这样才能直接读取文件结束符!md裂了,具体见本函数下面的链接 break; //补更:对于有换行的文本文件,get()搭配peek()使用更方便,去nm的eof(); } wFILE.close(); rFILE.close(); head->next = NULL; return temp;//返回头节点 } /* https: //blog.csdn.net/AllanZeng/article/details/4146223?spm=1001.2101.3001.6661.1&utm _medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRL IST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edef ault%7ECTRLIST%7Edefault-1.no_search_link */ void admin_inf::input(const char* file_name, int& num)//读取 menu 文件或 find 文件 { ifstream rFILE(file_name, ios::in); ofstream wFILE("out.txt", ios::out); if (!rFILE) { wFILE << "文件中未检测到文本!"; wFILE.close(); exit(1); } else { if (rFILE.peek()==EOF) { wFILE << "find.txt文件中未检测到文本!"; wFILE.close(); exit(0); } else { rFILE >> num; rFILE.close(); wFILE.close(); } } } void admin_inf::find(admin_inf::person* head, int id)//查找 Id 为 no 的人员 { ofstream wFILE("out.txt", ios::out); admin_inf::person* temp = head->next; while (temp!=NULL&&temp->ID!=id) temp = temp->next; if (temp == NULL) { wFILE << "无此ID,请重新查找!"; wFILE.close(); exit(0); } wFILE << temp->ID << " " << temp->name << " " << temp->age << " " << temp->sex << " " << temp->language << " " << temp->score << endl; } admin_inf::person* admin_inf::input(const char* file_name, admin_inf::person* head)//读取 insert 文件,并添加至链表末尾 { ifstream rFILE(file_name, ios::in); ofstream wFILE("out.txt", ios::out); if (rFILE.peek()==EOF) { wFILE << file_name << "文件中未检测到文本!"; wFILE.close(); exit(0); } admin_inf::person* new_head = new admin_inf::person; new_head->next = NULL; admin_inf::person* temp = new_head; rFILE >> new_head->ID >> new_head->name >> new_head->age >> new_head->sex >> new_head->language >> new_head->score; while (1) { rFILE.get(); if (rFILE.peek() == EOF) //这三行必须放前面 break; admin_inf::person* new_one = new admin_inf::person; new_one->next = NULL; rFILE >> new_one->ID >> new_one->name >> new_one->age >> new_one->sex >> new_one->language >> new_one->score; new_head->next = new_one; new_head = new_one; } rFILE.close(); while (head!=NULL && head->next != NULL) head = head->next; head->next = temp; return temp; } void admin_inf::output(admin_inf::person* head, const char* file_name)//将链表内容写入文件 { ofstream wFILE(file_name, ios::out); admin_inf::person* temp = head->next; if (temp == NULL) { wFILE << "无人员信息!"; wFILE.close(); exit(0); } while (temp) { wFILE << temp->ID << " " << temp->name << " " << temp->age << " " << temp->sex << " " << temp->language << " " << temp->score << endl; temp = temp->next; } wFILE.close(); } admin_inf::person* admin_inf::del(admin_inf::person* head, int id)//从链表中删除 Id 为 no 的人员,返回链首 { ofstream wiFILE("input.txt", ios::out); ofstream woFILE("out.txt", ios::out); admin_inf::person* temp = head; admin_inf::person* Temp; while (temp->next!=NULL && temp->next->ID != id) temp = temp->next; if (temp->next == NULL) { woFILE << "没有此ID信息!请重新查找。"; woFILE.close(); exit(0); } Temp = temp->next; temp->next = temp->next->next; delete Temp;//回收被剔除的节点空间 Temp = NULL; temp = head->next; while (temp) //新的链表放入input文件 { wiFILE << temp->ID << " " << temp->name << " " << temp->age << " " << temp->sex << " " << temp->language << " " << temp->score << endl; temp = temp->next; } woFILE.close(); wiFILE.close(); return head; } void admin_inf::append(admin_inf::person* head, admin_inf::person* s) { ofstream wiFILE("input.txt", ios::app);//app以补加的形式打开 ofstream woFILE("out.txt", ios::out); while (s != NULL) { wiFILE << s->ID << " " << s->name << " " << s->age << " " << s->sex << " " << s->language << " " << s->score << endl; s = s->next; } admin_inf::person* temp = head->next; while (temp != NULL) { woFILE<< temp->ID << " " << temp->name << " " << temp->age << " " << temp->sex << " " << temp->language << " " << temp->score << endl; temp = temp->next; } wiFILE.close(); woFILE.close(); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术