学生通讯录管理系统(链表实现)-程序员宅基地

技术标签: c++  mingw  链表  gcc/gdb编译调试  数据结构  

第一章 设计要求

1.1 问题描述
使用C或C++实现一个通讯录管理系统,具有实现通讯录的建立和输出、通讯者的插入、 删除和查询等几种操作功能。
1.2 需求分析
1.2.1 需求概述
通讯录管理系统是一个比较实用的小型管理系统。随着生活节奏的加快,人们追求丰富便捷的电子产品体验,因此也提高对便捷方式的喜爱。当今社会下人们的交际范围越来越广泛,通讯录系统的出现,方便了人们存储通讯录,便于人们日常的交际。为方便广大人们对通讯管理系统的使用,本设计采用控制语句来改变程序各项功能的实现。主菜单部分主要解决的问题是程序开始选择问题,以及循环选择问题,其余各部分根据其实现功能完成代码设计。
1.2.2 环境需求
本课程设计需要的设备为硬件要求和软件配置要求具体要求如下:
(1)硬件要求:一台计算机。
(2)软件配置:Windows、MinGW 32、CLion2020.2 IDE编译工具。
1.2.3 功能需求
本课程设计是利用数据结构的相关知识在 MinGW编译工具和CLion IDE下用 C++ 实现一个通讯录管理系统。具有实现通讯录的建立和输出、通讯者的插入、删除和查询等几种操作功能。

第二章 概要设计

2.1 主界面设计
主界面设计代码如下图2.1.1所示:
在这里插入图片描述

图 2.1.1主界面代码图

主界面设计图如下图2.1.2所示:
在这里插入图片描述

图 2.1.2 主界面图
2.2 存储结构设计
声明一个结构体作为链表单个节点,其中存储的内容有学号、姓名、出生日期、电话号和家庭住址,这些节点利用指针连接起来。存储结构设计代码如下图2.2所示:
在这里插入图片描述

图 2.2存储结构设计图
2.3 系统功能设计
(1) 菜单功能:输出菜单界面,并提供一个菜单来实现各个函数的调用以及提示用户。
(2) 添加功能:包含输入功能,第一次可以一次完成若干条记录的输入,此后可每次完成一条记录的输入,增加通讯录的基本信息。
(3) 修改功能:根据联系人的名字,修改指定联系人的信息。
(4) 删除功能:根据联系人的名字,删除指定联系人的信息。
(5) 查询功能:根据联系人的名字,查找指定联系人的信息并输出。
(6) 显示功能:将目前所有的联系人的信息输出。
(7) 读取功能:从保存的文件中读取通讯录信息;
(8) 保存功能:保存现有通讯录到文件中,防止程序退出数据丢失;
(9) 关闭功能:退出程序。

第三章 模块设计

3.1 模块设计
3.1.1 功能模块设计
系统的功能模块包括通讯录链表的建立、通讯者结点的插入、通讯者结点的查询、通讯者结点的删除、通讯者结点的修改、通讯录链表的输出、向/从文件中写入或读取通讯录和退出通讯录管理系统,如下图3.1.1所示:
在这里插入图片描述
图3.1.1 功能图

3.1.2 系统流程图
系统流程如下图3.1.2所示:
在这里插入图片描述

图 3.1.2系统流程图
3.2 系统子程序及功能设计
系统子程序功能设计一览表如下表3.2.1:

函数名 功能
void Menu(); 显示菜单
Node *Create(); 新建通讯录链表
bool InsertStudent(Node *head); 插入学生信息
bool DeleteStudent(Node *head, const string& id); 删除学生信息
Node *ReadFromFile(); 从文件中读取通讯录
bool WriteToFile(Node *head); 向文件写入通讯录
Node * FindStudent(Node *head, const string& id); 查询学生信息(学号)
Node* FindStuInformation(const string& pName, Node* pHead); 查询学生信息(姓名)
void PrintStudent(Node *head); 输出全部学生信息
void PrintStudentSingle(Node *pNode); 输出单个学生节点信息
bool ChangeInformation(Node* pNode); 修改学生信息
void SYS_CONTROL(); 系统控制函数

表3.2.1 功能函数一览表
(1) 创建通讯录方法如下图3.2.1所示:
在这里插入图片描述
图3.2.1 Create方法

(2) 删除信息方法如下图3.2.2所示:
在这里插入图片描述

图3.2.2 deletestudent方法
(3) 查询学生信息方法如下图3.2.3所示:
在这里插入图片描述

图3.2.3 Findstudent方法
(4) 插入学生信息方法如下图3.2.4所示:
在这里插入图片描述

图3.2.4 Insertstudent
(5) 打印学生信息功能如下图3.2.5所示:
在这里插入图片描述
图3.2.5 Printstudent

(6) 从文件中读取通讯录功能如下图3.2.6所示:
在这里插入图片描述

图3.2.6 Readfromfile
(7) 保存通讯录功能如下图3.2.7所示:
在这里插入图片描述

图3.2.7 Writeinfile

(8) 修改功能流程图如下图3.2.8所示:
在这里插入图片描述
图3.2.8 修改功能流程图

3.3 函数主要调用关系图

函数主要调用关系如下图3.3所示:
在这里插入图片描述
图3.3.1 函数主要关系调用图

第四章 详细设计

4.1 数据定义
系统的数据定义如下图4.1所示:在这里插入图片描述图4.1 链表节点数据定义图
4.2 系统主要子程序详细设计
4.2.1 通讯录链表建立

Node *Create() {
    
    int i = 1;
    char ch = 'Y';                  // 是否继续输入学生通讯录信息
    Node *head = new Node();       // 头结点,不存放数据
    if(nullptr == head) {
    
        cerr << "内存空间分配失败" << endl;
        exit(1);
    }
    head->next = nullptr;
    while(ch == 'Y'||ch == 'y') {
    
        cout << "请输入第" << i << "位学生的学号、姓名、出生日期、姓别(1:表示是男生,0:表示是女生)、电话和地址(以空格隔开):" << endl;
        Node *newNode = new Node();  // 新建结点
        if(nullptr == newNode) {
    
            cerr << "内存空间分配失败" << endl;
            exit(1);
        }
        cin >> newNode->id >> newNode->name >> newNode->birthday >> newNode->sex >> newNode->phone >> newNode->address;
        newNode->next = nullptr;
        // 采用头插入
        newNode->next = head->next;  // 新结点的next保存首结点(头结点的下一个结点)
        head->next = newNode;       // 头指针往前移
        i++;
        cout << "是否继续输入学生的通讯录信息?(Y/N):";
        cin >> ch;
    }
    return head;
}

4.2.2 插入节点学生信息

bool InsertStudent(Node *head) {
    
    cout << "请输入学生的学号、姓名、出生日期、姓别(1:表示是男生,0:表示是女生)、电话和地址(以空格隔开):" << endl;
    Node *newNode = new Node();	   // 新建结点
    if(nullptr == newNode) {
    
        cerr << "内存空间分配失败" << endl;
        exit(1);
    }
    cin >> newNode->id >> newNode->name >> newNode->birthday >> newNode->sex >> newNode->phone >> newNode->address;
    newNode->next = head->next;	  // 新结点的next保存首结点(头结点的下一个结点)
    head->next = newNode;        	  // 头指针往前移
    return true;                     // 插入成功
}

4.2.3 删除节点学生信息

bool DeleteStudent(Node *head, const string& id) {
    
    Node *prev = head;
    Node *p = head->next;

    while(p != nullptr && p->id != id) {
    		//注意二者不可交换位置
        prev = p;
        p = p->next;
    }
    if(p == nullptr)return false;
    prev->next = p->next;
    delete p;
    p = nullptr;
    return true;		//删除成功
}

4.2.4 查询节点学生信息

// 在通讯录中查询学生信息(按学号查询)
Node* FindStudent(Node *head, const string& id) {
    
    Node *p = head;
    int count = 0;
    while(p != nullptr && id != p->id) {
    		//注意二者不可交换位置
        p = p->next;
        ++count;
    }
    for (int i=0;i<count-1;i++)				//查找对应节点指针
    {
    
        head = head->next;
    }
    if(p == nullptr)return p; else return head;   //分情况返回,防止野指针
}

// 在通讯录中查询学生信息(按姓名查询)
Node* FindStuInformation(const string& pName, Node* pHead) {
    
    Node *p = pHead;
    int count = 0;
    while(p != nullptr && pName != p->name) {
    	//注意二者不可交换位置
        p = p->next;
        ++count;
    }
    for (int i=0;i<count-1;i++)					//查找对应节点指针
    {
    
        pHead = pHead->next;
    }
    if(p == nullptr)return p; else return pHead;		//分情况返回,防止野指针
}

4.2.5 修改节点学生信息

bool ChangeInformation(Node *pNode) {
    
    Node* p = pNode->next;
    int ch = -1;
    string str = "INIT";
    cout<<"按编号选择需要修改的项目,【按0】退出"<<endl;
    while(ch != 0){
    
        cin>>ch;
        switch (ch) {
    
            case 1:
                cout<<"修改学号为:"<<endl;
                cin>>str;
                p->id = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 2:
                cout<<"修改姓名为:"<<endl;
                cin>>str;
                p->name = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 3:
                cout<<"修改出生日期为:"<<endl;
                cin>>str;
                p->birthday = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 4:
                p->sex = !(p->sex);
                str = "Changed by [4](sex)";
                cout<<"性别已修改!"<<endl;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 5:
                cout<<"修改电话号为:"<<endl;
                cin>>str;
                p->phone = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 6:
                cout<<"修改家庭地址为:"<<endl;
                cin>>str;
                p->address = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 0:
                break;
            default:
                cout<<"选择错误,请重新选择!"<<endl;
        }
    }
    if ( str == "INIT")return false; else return true;
}

4.2.6 保存通讯录

bool WriteToFile(Node *head) {
    
    if (head == nullptr){
    PLCR return false;}
    Node *p = head->next;
    int ch = 0,flag = 1;
    while (flag){
    
        cout<<"[0]覆盖原有通讯录 [1]添加到原有通讯录"<<endl;
        cin>>ch;
        switch (ch) {
    
            case 0:
                flag = 0;
                break;
            case 1:
                flag = 0;
                break;
            default:
                cout<<"选择错误"<<endl;
        }
    }
    // 以写模式打开文件
ofstream outFile;
if(ch){
    outFile.open("StuMessageFile/student.txt",ios::out|ios::app);}else{
    outFile.open("StuMessageFile/student.txt", ios::out);};
    if(!outFile)
    {
    
        cout << "Error: opening file fail" << endl;
        exit(1);
    }
    while(p != nullptr) {
    
        // 写入文件
        outFile << p->id << " " << p->name << " " << p->birthday << " " << p->sex << " " << p->phone << " " << p->address << endl;
        p = p->next;      // 往后移
    }
    return true;
}

4.2.7 读取通讯录

Node *ReadFromFile() {
    
    Node *head = new Node();		// 头结点,不存放数据
    if(nullptr == head) {
    
        cerr << "内存空间分配失败" << endl;
        exit(1);
    }
    ifstream inFile;
    inFile.open("StuMessageFile/student.txt", ios::in);		// 以读的方式打开文件
    if(!inFile.is_open())
    {
    
        cout << "Error: opening file fail" << endl;
        exit(1);
    }
    Node *newNode = new Node();		// 新建结点
    if(nullptr == newNode) {
    
        cerr << "内存空间分配失败" << endl;
        exit(1);
    }
    while(!inFile.eof()) {
    		// 当未到文件尾
        Node *newNode = new Node();       // 新建结点
        if(nullptr == newNode) {
    
            cerr << "内存空间分配失败" << endl;
            exit(1);
        }
        // 从文件中输入数据
        inFile >> newNode->id >> newNode->name >> newNode->birthday >> newNode->sex >> newNode->phone >> newNode->address;
        newNode->next = head->next;		// 新结点的next保存首结点(头结点的下一个结点)
        head->next = newNode;		// 头指针往前移
    }
    inFile.close();		// 关闭文件
    head = head->next;
    return head;
}

第五章 测试分析

5.1 遇到的问题及解决方法

  1. 问题:
    (1) 在未创建或未读取通讯录的情况下,选择其他功能程序会崩溃;
    (2) 保存通讯录后,覆盖原有学生信息文件;
    (3) 查询并打印时,打印出被查询学生后的所有学生信息;
    (4) 打印通讯录所有学生信息时,未存储任何信息的头结点被打印;
    (5) 程序测试时,控制台乱码显示中文字符。
  2. 解决办法:
    (6) 在主程序Switch()case……中添加头结点判断;
    (7) 修改文件的打开方式为:追加写入方式;
    (8) 重写PrintStudentSingle函数,取消while(p != nullptr)循环条件;
    (9) 将头结点跳过,从下一个开始,head = head->next;
    (10) 编写程序选择UTF-8编码格式,控制台调试选择GBK编码。

5.2 经验和体会
(1)通过本次项目使我们进一步理解和掌握课堂上所学各种基本抽象数据类型的逻辑结构、存储结构和操作实现算法,以及它们在程序中的使用方法。
(2)使我们掌握软件设计的基本内容和设计方法,并培养了我们进行规范化软件设计的能力。
(3)使我们能掌握使用各种计算机资料和有关参考资料,提高我们进行程序设计的基本能力。

5.3 测试功能展示
(1) 主界面如下图5.3.1所示:
在这里插入图片描述
图5.3.1 主界面

(2) 通讯录链表建立(1. 新建学生通讯录)功能测试如下图5.3.2所示:
在这里插入图片描述
图5.3.2 新建通讯录

(3) 插入节点学生信息(2. 在通讯录插入学生信息)测试如下图5.3.3所示:
在这里插入图片描述
图5.3.3 插入信息

(4) 删除节点学生信息功能(3. 在通讯录删除学生信息)测试如下图5.3.4所示:
在这里插入图片描述
图5.3.4 删除信息

(5) 查询节点学生信息功能(6. 在通讯录按学号查询信息)测试如下图5.4.5所示:
在这里插入图片描述
图5.4.5 查询信息

(6) 修改节点学生信息(8. 修改学生信息)功能测试如下图5.4.6所示:

在这里插入图片描述
图5.4.6 修改学生信息

(7) 保存通讯录(5. 向文件写入通讯录信息)功能如下图所示:
在这里插入图片描述
图5.4.7 保存通讯录

(8) 读取通讯录(4. 从文件读取通讯录信息)功能测试如下图5.4.8所示;
在这里插入图片描述
图5.4.8 读取通讯录

第六章 源程序清单

6.1 main.cpp

#include "student.h"
using namespace std;

int main() {
    
    SYS_CONTROL();
    return 0;
}

6.2 student.cpp

//
// Created by Today me on 2021/6/21.
//

#include "student.h"
//string id; 			// 学生的学号
//string name; 		// 姓名
//string birthday; 		// 出生日期:如1995-01-01
//int sex;             // 1:表示是男生,0:表示是女生
//string phone;        // 电话
//string address;       // 地址

// 新建学生通讯录信息
// 如:1110618014058 Thomas 2000-01-01 1 13521469978 陕西汉中

// 菜单界面
void Menu() {
    
    SYSTEMTIME sys;
    GetLocalTime(&sys);
    cout << "\t\t************************************\n\t\t**^_^欢迎使用学生通讯录管理系统^_^**\n\t\t************************************\n\t\t\t   "<<sys.wYear<<"年"<<sys.wMonth<<"月"<<sys.wDay<<"日";cout<<"\n****************************************************************\n**\t\t\t通讯录管理主菜单\t\t      **\n**------------------------------------------------------------**\n";
    cout << "**|   1.新建学生通讯录\t\t 5.向文件写入通讯录信息      |**\n";
    cout << "**|   2.在通讯录插入学生信息\t 6.在通讯录按学号查询信息    |**\n";
    cout << "**|   3.在通讯录删除学生信息\t 7.在屏幕打印全部学生信息    |**\n";
    cout << "**|   4.从文件读取通讯录信息\t 8.修改学生信息\t\t     |**\n**------------------------------------------------------------**\n****************************************************************\n";
    cout << "**\t\t请输入选择(1-8):【0】退出系统              **\n****************************************************************\n";
}
// 创建通讯录
Node *Create() {
    
    int i = 1;
    char ch = 'Y';                // 是否继续输入学生通讯录信息
    Node *head = new Node();     // 头结点,不存放数据
    if(nullptr == head) {
    
        cerr << "内存空间分配失败" << endl;
        exit(1);
    }
    head->next = nullptr;
    while(ch == 'Y'||ch == 'y') {
    
        cout << "请输入第" << i << "位学生的学号、姓名、出生日期、姓别(1:表示是男生,0:表示是女生)、电话和地址(以空格隔开):" << endl;
        Node *newNode = new Node();     // 新建结点
        if(nullptr == newNode) {
    
            cerr << "内存空间分配失败" << endl;
            exit(1);
        }
        cin >> newNode->id >> newNode->name >> newNode->birthday >> newNode->sex >> newNode->phone >> newNode->address;
        newNode->next = nullptr;
        // 采用头插入
        newNode->next = head->next;  // 新结点的next保存首结点(头结点的下一个结点)
        head->next = newNode;       // 头指针往前移
        i++;
        cout << "是否继续输入学生的通讯录信息?(Y/N):";
        cin >> ch;
    }
    return head;
}

// 向学生通讯录插入学生信息
bool InsertStudent(Node *head) {
    
    cout << "请输入学生的学号、姓名、出生日期、姓别(1:表示是男生,0:表示是女生)、电话和地址(以空格隔开):" << endl;
    Node *newNode = new Node();    // 新建结点
    if(nullptr == newNode) {
    
        cerr << "内存空间分配失败" << endl;
        exit(1);
    }
    cin >> newNode->id >> newNode->name >> newNode->birthday >> newNode->sex >> newNode->phone >> newNode->address;
    newNode->next = head->next;    // 新结点的next保存首结点(头结点的下一个结点)
    head->next = newNode;          // 头指针往前移
    return true;                    // 插入成功
}

// 在通讯录中删除学生信息
bool DeleteStudent(Node *head, const string& id) {
    
    Node *prev = head;
    Node *p = head->next;

    while(p != nullptr && p->id != id) {
           //注意二者不可交换位置
        prev = p;
        p = p->next;
    }
    if(p == nullptr)return false;
    prev->next = p->next;
    delete p;
    p = nullptr;
    return true;
}

// 从文件中读取通讯录信息
Node *ReadFromFile() {
    
    Node *head = new Node();      // 头结点,不存放数据
    if(nullptr == head) {
    
        cerr << "内存空间分配失败" << endl;
        exit(1);
    }
    ifstream inFile;
    inFile.open("StuMessageFile/student.txt", ios::in);      // 以读的方式打开文件
    if(!inFile.is_open())
    {
    
        cout << "Error: opening file fail" << endl;
        exit(1);
    }
    Node *newNode = new Node();       // 新建结点
    if(nullptr == newNode) {
    
        cerr << "内存空间分配失败" << endl;
        exit(1);
    }
    while(!inFile.eof()) {
                   // 当未到文件尾
        Node *newNode = new Node();  // 新建结点
        if(nullptr == newNode) {
    
            cerr << "内存空间分配失败" << endl;
            exit(1);
        }
        // 从文件中输入数据
        inFile >> newNode->id >> newNode->name >> newNode->birthday >> newNode->sex >> newNode->phone >> newNode->address;
        newNode->next = head->next;  // 新结点的next保存首结点(头结点的下一个结点)
        head->next = newNode;       // 头指针往前移
    }
    inFile.close();                   // 关闭文件
    head = head->next;
    return head;
}

// 向文件写入学生通讯录信息
bool WriteToFile(Node *head) {
    
    if (head == nullptr){
    PLCR return false;}
    Node *p = head->next;
    int ch = 0,flag = 1;
    while (flag){
    
        cout<<"[0]覆盖原有通讯录 [1]添加到原有通讯录"<<endl;
        cin>>ch;
        switch (ch) {
    
            case 0:
                flag = 0;
                break;
            case 1:
                flag = 0;
                break;
            default:
                cout<<"选择错误"<<endl;
        }
    }
    // 以写模式打开文件
ofstream outFile;
if(ch){
    outFile.open("StuMessageFile/student.txt",ios::out|ios::app);}else{
    outFile.open("StuMessageFile/student.txt", ios::out);};
    if(!outFile)
    {
    
        cout << "Error: opening file fail" << endl;
        exit(1);
    }
    while(p != nullptr) {
    
        // 写入文件
        outFile << p->id << " " << p->name << " " << p->birthday << " " << p->sex << " " << p->phone << " " << p->address << endl;
        p = p->next;             // 往后移
    }
    return true;
}

// 在通讯录中查询学生信息(按学号查询)
Node* FindStudent(Node *head, const string& id) {
    
    Node *p = head;
    int count = 0;
    while(p != nullptr && id != p->id) {
    
        p = p->next;
        ++count;
    }
    for (int i=0;i<count-1;i++)
    {
    
        head = head->next;
    }
    if(p == nullptr)return p; else return head;
}

// 在屏幕中输出全部学生信息
void PrintStudent(Node *head) {
    
    Node *p = head->next;
    while(p != nullptr) {
    
        cout << "学号:" << p->id << " 姓名:" << p->name << " 出生日期:" << p->birthday;
        if(p->sex == 1)
            cout << " 性别:男";
        else
            cout << " 性别:女";
        cout << " 电话:" << p->phone << " 地址:" << p->address << endl;
        p = p->next;
    }
}

// 单行输出功能
void PrintStudentSingle(Node *pNode) {
    
    Node* p = pNode->next;
    cout << "【1】学号:" << p->id << " 【2】姓名:" << p->name << " 【3】出生日期:" << p->birthday;
    if(p->sex == 1)
        cout << " 【4】性别:男";
    else
        cout << " 【4】性别:女";
    cout << " 【5】电话:" << p->phone << " 【6】地址:" << p->address << endl;

}

// 在通讯录中查询学生信息(按姓名查询)
Node* FindStuInformation(const string& pName, Node* pHead) {
    
    Node *p = pHead;
    int count = 0;
    while(p != nullptr && pName != p->name) {
    
        p = p->next;
        ++count;
    }
    for (int i=0;i<count-1;i++)
    {
    
        pHead = pHead->next;
    }
    if(p == nullptr)return p; else return pHead;
}
//查找所有符合条件的学生
void FindAll(Node* pNode,const string& pName)
{
    
    Node* p = pNode;
    while (pNode != nullptr)
    {
    
        if (pName == pNode->name)PrintStudentSingle(p);
        p = pNode;
        pNode = pNode->next;
    }
}
// 修改学生信息
bool ChangeInformation(Node *pNode) {
    
    Node* p = pNode->next;
    int ch = -1;
    string str = "INIT";
    cout<<"按编号选择需要修改的项目,【按0】退出"<<endl;
    while(ch != 0){
    
        cin>>ch;
        switch (ch) {
    
            case 1:
                cout<<"修改学号为:"<<endl;
                cin>>str;
                p->id = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 2:
                cout<<"修改姓名为:"<<endl;
                cin>>str;
                p->name = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 3:
                cout<<"修改出生日期为:"<<endl;
                cin>>str;
                p->birthday = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 4:
                p->sex = !(p->sex);
                str = "Changed by [4](sex)";
                cout<<"性别已修改!"<<endl;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 5:
                cout<<"修改电话号为:"<<endl;
                cin>>str;
                p->phone = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 6:
                cout<<"修改家庭地址为:"<<endl;
                cin>>str;
                p->address = str;
                cout<<"继续按编号选择需要修改的项目,或【按0】退出"<<endl;
                break;
            case 0:
                break;
            default:
                cout<<"选择错误,请重新选择!"<<endl;
        }
    }
    if ( str == "INIT")return false; else return true;
}

// 系统控制函数
void SYS_CONTROL() {
    
    SetConsoleTitle("学生通讯录管理系统");
    int choice;
    string name;
    string id;
    bool Changed = false;
    bool finished = false;
    Node *head = nullptr;

    while(!finished) {
    
        Menu();
        cin >> choice;
        switch(choice) {
    
            case 1:
                head = Create();                                                                // 新建学生通讯录
                break;
            case 2:
                if(head == nullptr){
    PLCR cout<<"【提示】:<插入失败>"<<endl;}else {
    
                    if (InsertStudent(head))                                                    // 向学生通讯录插入学生信息
                        cout << "插入学生信息成功!" << endl;
                    else
                        cout << "插入学生信息失败!" << endl;
                }
                break;
            case 3:                                                                             // 在通讯录删除学生信息
                if(head == nullptr){
    PLCR}else {
    
                    cout << "请输入要删除的学生通讯录信息的学号:";
                    cin >> id;
                    if (DeleteStudent(head, id))
                        cout << "删除成功!" << endl;
                    else
                        cout << "删除失败!" << endl;
                }
                break;
            case 4:                                                                             // 从文件中读取通讯录信息
                if (head = ReadFromFile())
                {
    
                    cout<<"【提示】:<读取成功>"<<endl;
                }else cout<<"【提示】:<读取失败>"<<endl;
                break;
            case 5:                                                                             // 向文件写入通讯录信息
                if (WriteToFile(head))
                {
    
                    cout<<"【提示】:<写入成功>"<<endl;
                } else{
    cout<<"【提示】:<写入失败>"<<endl;}
                break;
            case 6:                                                                             // 在通讯录中查询学生信息(按学号查询)
                if (head == nullptr){
    PLCR}else{
    
                    cout << "请输入要查找的学生信息的学号:";
                    cin >> id;
                    if(FSPTRID != nullptr) {
    
                        PrintStudentSingle(FSPTRID);
                        break;
                    }else{
    
                        cout << "查无此人!" << endl;
                    }
                }
                break;
            case 7:                                                                             // 在屏幕中输出全部学生信息
                if (head == nullptr){
    PLCR }else {
    
                    PrintStudent(head);
                }
                break;
            case 8:                                                                             // 修改学生信息
                if (head == nullptr){
    PLCR }else {
    
                    cout << "请输入要修改的学生信息的姓名:";
                    cin >> name;
                    if(FindStuInformation(name,head) != nullptr) {
    
                        Node* pTemp = FindStuInformation(name,head);
                        PrintStudentSingle(pTemp);
                        Changed = ChangeInformation(pTemp);
                        if (Changed){
    cout<<"修改后该生通讯录信息为:"<<endl;PrintStudentSingle(pTemp);}else cout<<"【提示】:未修改任何信息"<<endl;

                    }else{
    
                        cout << "查无此人!" << endl;
                    }
                }
                break;
            case 0:
                finished = true;
                break;
            default:
                system("cls");
                cout << "输入选择错误,请重新输入!" << endl;
        }
    }
}

6.3 student.h

//
// Created by Today me on 2021/6/21.
//

#ifndef STUDENT_MANGER_SYS_STUDENT_H
#define STUDENT_MANGER_SYS_STUDENT_H
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>

#define FSPTRID FindStudent(head, id)
#define PLCR system("cls");cout<<"【提示】:<请先读取或者创建通讯录>"<<endl;
using namespace std;

struct Node {
    
    string id;                                // 学生的学号
    string name;                             // 姓名
    string birthday;                           // 出生日期:如1995-01-01
    int sex;                                 // 1:表示是男生,0:表示是女生
    string phone;                            // 电话
    string address;                           // 地址
    Node *next;
};

void Menu();                                 // 显示菜单函数
Node *Create();                               // 新建同学录
bool InsertStudent(Node *head);                 // 向学生通讯录插入学生信息
bool DeleteStudent(Node *head, const string& id);   // 在通讯录中删除学生信息
Node *ReadFromFile();                        // 从文件中读取通讯录信息
bool WriteToFile(Node *head);                // 向文件写入学生通讯录信息
Node * FindStudent(Node *head, const string& id); // 在通讯录中查询学生信息(按学号查询)
void PrintStudent(Node *head);                // 在屏幕中输出全部学生信息
void PrintStudentSingle(Node *pNode);       // 在屏幕中输出单个学生节点信息
Node* FindStuInformation(const string& pName, Node* pHead); // 在通讯录中查询学生信息(按姓名查询)
bool ChangeInformation(Node* pNode);          // 修改学生信息
void SYS_CONTROL();                      // 系统控制函数
void FindAll(Node* pNode,const string& pName); //打印所有符合条件的学生信息
#endif //STUDENT_MANGER_SYS_STUDENT_H

第七章 用户手册

7.1 操作步骤
7.1.1 创建通讯录
(1)按1,创建通讯录,按照提示输入学生信息,输入完成后,选择是否继续插入。
(2)按7,在屏幕中打印已有的学生信息。
(3)按6,查询已有的学生信息。
(4)按3,删除学生信息。
(5)按2,根据提示插入学生信息。
(6)按5,保存该通讯录。
(7)按8,退出系统。
7.1.2 读取通讯录
(1)按4,从文件中读取已保存的通讯录。
(2)按7,在屏幕中打印已有的学生信息。
(3)按6,查询已有的学生信息。
(4)按3,删除学生信息。
(5)按2,根据提示插入学生信息。
(6)按5,保存该通讯录。
(7)按8,退出系统。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/woshinidiegez/article/details/119859829

智能推荐

03 一些常用的gulp插件-程序员宅基地

文章浏览阅读463次。首发于github于gulp的插件数量虽然没有grunt那么多,但也可以说是应有尽有了,下面列举一些常用的插件。_gulp插件

elasticsearch初探-程序员宅基地

文章浏览阅读168次。1.es大致介绍 分布式搜索引擎,底层为lucene,核心思想多台机器启动多个es进程构成集群. index->type->mapping->document->field shard 横向扩展 提高性能 primary shard-> replica shard 高可用2.写入原理,查询...

Python: PS 滤镜--万花筒效果-程序员宅基地

文章浏览阅读402次。本文用 Python 实现 PS 的一种滤镜效果,称为万花筒。也是对图像做各种扭曲变换,最后图像呈现的效果就像从万花筒中看到的一样:图像的效果可以参考之前的博客:http://blog.csdn.net/matrix_space/article/details/46789783import matplotlib.pyplot as pltfrom..._opencv 万花筒

position fixed 固定定位失效问题及解决方案_position: fixed 失效-程序员宅基地

文章浏览阅读1.7w次,点赞2次,收藏9次。最近在项目开发过程中遇到了一个固定定位失效的问题,当给一个元素设置了position: fixed并设置了距离top和left的距离之后发现位置居然一直不正确,fix固定定位失效了。由于出现这个bug的地方使用了better-scroll, 初步猜想失效的原因可能是使用的better-scroll.js插件, 后来在网上查找了一番,发现原来使用isscroll.js滚动库以及在移动端设置-we..._position: fixed 失效

HTML5+CSS3-程序员宅基地

文章浏览阅读806次,点赞9次,收藏18次。1.网页指的是超文本标记语言,不是编程语言,而是一种标记语言。标记语言是一套标记标签所谓超文本,有两层含义:(1)超出了文本限制,可以是图片,音频、视频等(2)它可以从一个文件跳转到另一个文件,与世界各地主机的文件连接(超级链接文本)2.浏览器有IE、火狐、谷歌、Fafari、Opera等**浏览器内核(渲染引擎):**负责读取网页内容,整理讯息,计算网页的显示方式并显示页面3.Web标准Web标准是由W3C组织和其他标准化组织制定的一系列标准的集合。

ESP8266开发(1):Ubuntu+VScode的开发环境_vscode开发esp8266-程序员宅基地

文章浏览阅读2.1k次,点赞3次,收藏11次。本教程基于ESP8266_RTOS_SDK(V3.0)前两天,闲得时候,想玩玩ESP8266,毕竟一代神U,了解了解总没有错的。经过一番折腾,发现这玩意的开发过程跟ESP32大同小异,在此略作记录。在乐鑫更新V3.0版本之后,esp8266的开发框架基本上就和esp32相同了,学会了一个另外一个也就差不多了。感兴趣的小伙伴可以先看看这个教程:ESP32开发(1):搭建Linux下的开发环境..._vscode开发esp8266

随便推点

卡尔曼滤波最通俗理解_卡尔曼滤波最佳实践-程序员宅基地

文章浏览阅读257次。卡尔曼滤波的核心:预测+测量反馈!先记住,看完下面这个段子就理解了。一片绿油油的草地上有一条曲折的小径,通向一棵大树.一个要求被提出:从起点沿着小径走到树下.“很简单.” A说,于是他丝毫不差地沿着小径走到了树下.现在,难度被增加了:蒙上眼。“也不难,我当过特种兵。” B说,于是他歪歪扭扭地走到了树旁。“唉,好久不练,生疏了。” (只凭自己的预测能力)“看我的,我有 DIY 的 GPS!..._卡尔曼滤波最佳实践

VB程序员的FTP编程指南1.4-下载或上传文件 (转)-程序员宅基地

文章浏览阅读129次。VB程序员的FTP编程指南1.4-下载或上传文件 (转)[@more@]专 题:下载或上传文件主 讲:qianqian 下载用FTP下载文件简单而直接。在下载之前,请保证你是在二进制模式下。ftp有两种文件传输模式,A..._逼va ftp

MySql创建用户并赋权-程序员宅基地

文章浏览阅读521次。MySql创建用户并赋权创建数据库# 新建一个数据库 ljwcreate database testDB;use testDB; select * from user; 从上图可以看到,会列出数据库所有的用户及权限创建用户CREATE USER 'user_name'@'host' IDENTIFIED BY 'password';user_name:要创建用户的...

Gradle 环境变量配置,Intellij IDEA下Gradle开发环境配置,配置Gradle的全局镜像仓库提高Gradle的编译速度_idea配置gradle项目环境-程序员宅基地

文章浏览阅读3.4k次,点赞4次,收藏6次。Gradle简介Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,目前也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。Gradle 系统环境变量配置1、下载Gradle官网下载:https://gradle.org/releases/CSDN下载:https://download.csdn.net/download.._idea配置gradle项目环境

一个项目玩转 Android 自定义 Drawable。_android studio自定义drownable-程序员宅基地

文章浏览阅读156次。DreamDrawable项目地址:yanbober/DreamDrawable简介: 一个项目玩转 Android 自定义 Drawable。更多:作者提 Bug标签:一个项目玩转 Android 自定义 Drawable,具体原理参见《Android 应用层开发 Drawable 的一些叨叨絮》,效果如下图所示。说明文档当前实现了多个 Custo..._android studio自定义drownable

matlab求图像暗通道图像,基于暗通道先验条件图像去雾算法-程序员宅基地

文章浏览阅读1.8k次,点赞4次,收藏28次。基于暗通道先验条件图像去雾算法香港大学何凯明博士于2009发表了一篇论文《Single Image Haze Removal Using Dark Channel Prior》。在文章中,何凯明博士提出了一种简单而有效的图像先验暗通道消除单输入图像雾的算法。暗通道先验是一种无雾室外图像的统计。这是基于一个关键的观察——大多数无雾室外图像的局部区域包含一些像素,这些像素在至少一个颜色通道(R,G,B..._暗通道去雾算法流程图

推荐文章

热门文章

相关标签