2023/12/12 志愿者信息管理系统

 一、程序实验要求

二、框架构建

首先这个程序包含的文件一共有如下5个:input.txt,menu.txt,find.txt,insert.txt,out.txtx。其中input.cpp又可以分成三个部分(函数重载),input就是读取文件输入数据所用。我们使用如下几个函数实现功能:

  1. volunteer* input(const char* fileName);//读取input文件并创建链表
  2. void input(const char* fileName, volunteer* q);//读取insert文件
  3. void input(const char* fileName, int& num);//读取menu文件或find文件

然后是output.cpp,它对应数据输出到 文件中。

void output(volunteer* head, const char* fileName);//将链表内容写入文件

 find.cpp:

volunteer* find(volunteer* head, int no);//查找number为no的人员,并返回该结点前一结点便于删除函数调用

del.cpp :

volunteer* del(volunteer* head, int no);//从链表中删除number为no的人员,返回链首

append.cpp:

 volunteer* append(volunteer* head, volunteer* s);//插入一名人员至链尾,返回链首

大体框架已经搭建好,我们给出头文件project.h 

#pragma once
#include<iostream>
#include<fstream>
#include<string>

using namespace std;

struct volunteer 
{
	int number;
	char name[20];
	int  age;
	char gender;
	char language[10];
	double grade;
	volunteer* next;
};
volunteer* input(const char* fileName);//读取input文件并创建链表
void input(const char* fileName, volunteer* q);//读取insert文件
void input(const char* fileName, int& num);//读取menu文件或find文件
void output(volunteer* head, const char* fileName);//将链表内容写入文件
volunteer* find(volunteer* head, int no);//查找number为no的人员,并返回该结点前一结点便于删除函数调用
volunteer* del(volunteer* head, int no);//从链表中删除number为no的人员,返回链首
volunteer* append(volunteer* head, volunteer* s);//插入一名人员至链尾,返回链首

接下来的内容就是对每个部分实现函数的填充。

三、写入函数

  • input.cpp

         volunteer* input(const char* fileName)//读取input文件并创建链表

// 从给定的文件名中读取志愿者信息,并返回链表的头指针  
volunteer* input(const char* fileName)
{
    ifstream inputFile; // 定义一个输入文件流对象  
    inputFile.open(fileName, ios::in); // 使用输入模式打开指定的文件  

    volunteer* head = new volunteer; // 创建一个新的志愿者节点作为链表的头结点  
    volunteer* per = new volunteer; // 创建一个临时指针,用于遍历链表  
    head->next = per; // 将头结点的下一个节点指向per,为后续的链表连接做准备  
    per = head; // 移动临时指针到头结点  

    do {
        volunteer* q = new volunteer; // 为新的志愿者创建一个节点  
        inputFile >> q->number >> q->name >> q->age >> q->gender >> q->language >> q->grade; // 从文件中读取志愿者的信息  
        q->next = NULL; // 设置新创建的节点的下一个节点为NULL,表示当前节点是链表的结尾  
        per->next = q; // 将当前节点的下一个节点指向新创建的节点,将新节点添加到链表的末尾  
        per = q; // 移动临时指针到新的节点,为读取下一个志愿者的信息做准备  
    } while (!inputFile.eof()); // 循环直到文件末尾  

    per->next = NULL; // 设置链表的最后一个节点的下一个节点为NULL,表示链表的结尾  
    return head; // 返回链表的头指针  
}
void input(const char* fileName, volunteer* p) // 函数定义  
{
    ifstream inputFile(fileName); // 尝试打开指定文件名的文件  
    if (!inputFile.is_open()) // 检查文件是否成功打开  
    {
        cout << "文件无法打开" << endl; // 如果文件无法打开,输出错误信息  
        return; // 结束函数执行  
    }
    inputFile >> p->number >> p->name >> p->age >> p->gender >> p->language >> p->grade; // 从文件中读取志愿者信息,并存储在p指向的结构体中  
}
void input(const char* fileName, int& num) // 函数定义  
{
    ifstream inputFile(fileName); // 尝试打开指定文件名的文件  
    if (!inputFile.is_open()) // 检查文件是否成功打开  
    {
        cout << "文件无法打开" << endl; // 如果文件无法打开,输出错误信息  
        return; // 结束函数执行  
    }
    inputFile >> num; // 从文件中读取一个整数并存储在num中  
}

        首先就是读取文件,这里我们使用ifstream。然后这里跟上对文件是否打开的检测:

ifstream inputFile(fileName);
if (!inputFile.is_open())
{
    cout << "文件无法打开" << endl;
    return NULL;
}

         然后我们创建一个链表,创建它的head节点和一个p节点,以及一个tail节点(用来给p->next分配内存)

  • output.cpp

void output(volunteer* head, const char* fileName)//将链表内容写入文件

void output(volunteer* head, const char* fileName)//将链表内容写入文件
{
	ofstream outputFile(fileName);
	if (!outputFile.is_open())
	{
		cout << "文件打开失败" << endl;
		return;
	}
	volunteer* p = head->next;
	while (p != NULL)
	{
		outputFile << p->number << p->name << p->age << p->gender << p->language << p->grade << endl;
		p = p->next;
	}
	outputFile.close();
}

这个程序中所需要和文件建立关系的就input.cpp和output.cpp,这里我们先和out.txt建立联系。然后和普通的链表操作一样,先创建一个p指针,实现输出。最后记得 outputFile.close();就行。

  • find.cpp

volunteer* find(volunteer* head, int no)//查找number为no的人员,并将该节点接到头节点之后方便output.cpp调用

这里为什么说是方便output.cpp调用呢?因为我们删除功能仅仅是读取find.txt而不是用find.cpp。find.cpp仅仅是为了方便查找功能的输出。

volunteer* find(volunteer* head, int no)//查找number为no的人员,并将该节点接到头节点之后方便output.cpp调用
{
	volunteer* p = head->next;
	while (p != NULL)
	{
		if (p->number == no)
		{
			head->next = p;
			p->next = NULL;
			return head;
		}
		p = p->next;
	}
	return head;
}
  • append.cpp

volunteer* append(volunteer* head, volunteer* s)//插入一名人员至链尾,返回链首

volunteer* append(volunteer* head, volunteer* s)//插入一名人员至链尾,返回链首
{
	volunteer* p = head;
	while (p->next != NULL)
	{
		p = p->next;
	}//p到链表尾部
	volunteer* tmp = new volunteer;
	if (tmp == NULL)
	{
		return 0;
	}//内存不够,返回
	tmp = s;
	tmp->next = NULL;
	p->next = tmp;

	return head;
}

这里是链表尾插法的实现。 

  • del.cpp

volunteer* del(volunteer* head, int no)//从链表中删除number为no的人员,返回链首

volunteer* del(volunteer* head, int no)//从链表中删除number为no的人员,返回链首
{
	volunteer* tmp = NULL;
	volunteer* p = head;
	while (p->next != NULL)
	{
		if (p->next->number == no)
		{
			tmp = p->next;
			p->next = p->next->next;
			delete tmp;
			return head;
		}
		p = p->next;
	}
}
  • FileName.cpp

#include"project.h"
using namespace std;

int main()
{
	volunteer* head = NULL;
	head = input("input.txt");//读入input.txt
	int num = 0;
	input("menu.txt", num);//读入menu.txt

	switch (num)
	{
	case 1:
	{
		int number = 0;
		input("find.txt", number);//读入find.txt
		head=find(head, number);
		output(head, "out.txt");
		break;
	}
	case 2:
	{
		volunteer* person = new volunteer;
		input("insert.txt", person);
		head = append(head, person);
		output(head, "out.txt");
		break;
	}
	case 3:
	{
		int number = 0;
		input("find.txt", number);
		head = del(head, number);
		output(head, "out.txt");
		break;
	}
	}
	return 0;
}

四、总结

遇到过的问题:

  •  最开始没有把q->next马上置为空

  • input.txt文件在文件末尾多出了一个换行符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值