C++学生信息管理 1.0记录

C++学生信息管理 1.0记录 

该信息管理没有太多可支持的操作,仅有一些基础设置,后续优化中将添加更多功能。

一.头文件引用和命名空间声明

#include <iostream> //输入输出操作
#include <string>   //字符串操作
using namespace std;  //为方便使用,不需要在cout,string等前方加前缀std

二.学生节点的结构体定义。

用来存储学生的基本信息,其中包括学号,姓名,性别,年龄以及指向下一节点的指针。结构体中还包括了一个构造函数,用来初始化成员变量。

struct StudentNode
{
    unsigned studentNumber; //学号
    string name; //姓名
    int age; //年龄
    string sex; //性别
    StudentNode *next; //指向下一节点的指针

    //构造函数用于初始化成员变量
    StudentNode(unsigned sn, const string &na, int ag, const string &se)
                : studentNumber(sn), name(na), age(ag), sex(se), next(nullptr) {}
};

1.这里的学号用的为无符号类型,由于学号整型数太大,int类型可支持范围不够,在输入学号后会超出范围生成垃圾值。

2.因为考虑到以后会对该代码进行优化,添加一些功能,少不了插入与删除操作,所有用链表的形式用来存储信息,便于后续代码的优化。

3.构造函数接受四个参数,其中两个为常量引用类型,因为无需对传递过来的实参做更改处理,设置为常量类型更为合理与安全,且效率也更高。

4.对于unsignedint类型的参数,一般不需要将它们声明为引用类型,因为它们是基础数据类型,传递它们的值通常非常快,且不会涉及额外的内存分配。传递值意味着会创建参数的副本,但对于这些基础类型,这个副本的创建通常是非常高效的。

5.初始化列表是构造函数独有的特性,在其它成员函数中无法使用。与在函数体里面作赋值操作相比,初始化列表往往伴有更快捷的效率以及更明了的意图。

6.在这里将next指向空指针nullprt,nullprt为C++的一个关键字,可直接使用,不需要引用任何头文件和作用域。

三.链表类的定义

class StudentLinkList
{
public:
    //公开构造函数,初始化链表的头节点为nullptr
    StudentLinkList() : head(nullptr) {}
    // 析构函数声明,具体实现在类的外部定义
    ~StudentLinkList();
    // 成员函数声明,用于向链表中添加学生信息 
    void addStudent(unsigned sn, const string &na, int ag,
                    const string &se);
    // 成员函数声明,用于打印链表中的学生信息 
    void printStudent();
    
private:
    // 私有成员变量,指向链表的头节点,初始时为nullptr  
    StudentNode *head;
};

1.在这里使用C++的新特性class类来做为链表,便于对数据与操作这些数据的方法做一个封装,与struct相比,class有更多支持的操作(struct与class本质上并无什么很大的区别,最直观的就是struct结构的成员变量及成员函数均是公开的,而class如果不显式表面public,则默认全是私有的)。以后在进行代码优化的时候添加一些功能也比较方便。

2.构造函数使用初始化列表将链表中的头指针指向nullprt(空指针)。

3.析构函数StudentLinkList(); 这是StudentLinkList类的析构函数声明,用于在对象生命周期结束时执行清理操作,释放链表占用的内存。具体的析构函数实现在类的外部定义。

4.将head指针设置为私有是面向对象编程中常见的做法,它有助于实现代码的某些特性,就是面向对象编程的几大特性。

四.析构函数的定义

StudentLinkList::~StudentLinkList()
{
    // 初始化一个指针current,指向链表的头节点head
    StudentNode *current = head;
    // 当current不为空时,说明还有节点需要被删除 
    while (current != nullptr)
    {
        // 保存当前节点的下一个节点的指针
        StudentNode *next = current->next;
        // 删除当前节点,释放其占用的内存
        delete current;
        // 将current指针移动到下一个节点,继续删除操作 
        current = next;
    }
    // 将头节点指针设置为nullptr,表示链表为空
    head = nullptr;
}

1.在析构函数开始时,首先初始化一个指针current,并将其指向链表的头节点head。这是开始遍历链表并删除节点的起点。
2.使用while循环来遍历链表中的每一个节点。循环继续的条件是current不为nullptr,即还有节点未被处理。
3.在删除当前节点之前,通过current->next保存下一个节点的指针到next变量中。这是因为一旦当前节点被删除,我们就无法通过它访问下一个节点了。
4.使用delete操作符(这是C++中的关键字,相当于C语言中的free())释放当前节点current所占用的内存。这会将该节点从内存中移除,并且任何对该节点的引用都将变得无效。 
5.将current指针更新为next,即我们之前保存的下一个节点的指针。这样,在下一次循环迭代时,我们就可以处理链表中的下一个节点。
6.循环继续,直到current变为nullptr,表示链表中的所有节点都已被删除。
7.最后,将头节点指针head置为nullptr,表示链表现在为空。这是一个很重要的步骤,因为它确保了head指针不再指向任何已删除的内存区域,从而避免了很大的安全风险。

五.增添函数的定义

void StudentLinkList::addStudent(unsigned sn, const string &na,
                                 int ag, const string &se)
{
    //创建一个新的StudentNode对象,并使用传入的参数初始化它。这个新节点会被添加到链表的末尾。
    StudentNode *newNode = new StudentNode(sn, na, ag, se);
    //如果链表为空(即head为nullptr),则直接将新节点设置为链表的头节点。
    if (head == nullptr)
    {
        head = newNode;
    }
    //如果链表不为空,初始化一个指针current,使其指向链表的头节点。
    else
    {
        StudentNode *current = head;
        //使用一个循环遍历链表,直到找到链表的最后一个节点(即next指针为nullptr的节点)。
        while (current->next != nullptr)
        {
            current = current->next;
        }
        //将最后一个节点的next指针指向新创建的节点,从而将新节点添加到链表的末尾
        current->next = newNode;
    }
}

1.该函数操作为链表的基本操作,因为定义的函数体代码多,与上面的析构函数一样定义在了类外,所以要加上::作用域解析运算符,告诉编译器所属范围。 

 

六.打印函数的定义

//用于打印出学生信息
void StudentLinkList::printStudent()
{
    //将当前节点指向头节点
    StudentNode *current = head;
    //遍历整个链表,对联表内的所有内容进行打印
    while (current != nullptr)
    {
        cout << "Student Number: " << current->studentNumber
             << ", Name: " << current->name
             << ", Age: " << current->age
             << ", Sex: " << current->sex << endl;
        //打印完当前节点后将指针移动向下一节点
        current = current->next;
    }
}

 七.函数主体

int main()
{
    StudentLinkList student;

    student.addStudent(2410145903, "Zhangsan", 18, "Man");
    student.addStudent(2415343923, "Lisi", 21, "Man");
    student.addStudent(2345351878, "Wangwu", 19, "Man");
    student.printStudent();

    return 0;
}

这个管理信息没有什么较为复杂的操作,在后续还将进行优化,增添一些插入和删除学生信息的操作,该系统学生信息的获取也是比较直观,在后续的优化中会进行一些升级。

八.完整代码

#include <iostream> //输入输出操作
#include <string>   //字符串操作
using namespace std;  //为方便使用,不需要在cout,string等前方加前缀std

//结构体的声明,学生的基本信息存储
struct StudentNode
{
    unsigned studentNumber; //学号
    string name; //姓名
    int age; //年龄
    string sex; //性别
    StudentNode *next; //指向下一节点的指针

    //构造函数用于初始化成员变量
    StudentNode(unsigned sn, const string &na, int ag, const string &se)
        : studentNumber(sn), name(na), age(ag), sex(se), next(nullptr) {}
};

//链表类的声明
class StudentLinkList
{
public:
    //公开构造函数,初始化链表的头节点为nullptr
    StudentLinkList() : head(nullptr) {}
    // 析构函数声明,具体实现在类的外部定义
    ~StudentLinkList();
    // 成员函数声明,用于向链表中添加学生信息 
    void addStudent(unsigned sn, const string &na, int ag,
                    const string &se);
    // 成员函数声明,用于打印链表中的学生信息 
    void printStudent();
    
private:
    // 私有成员变量,指向链表的头节点,初始时为nullptr  
    StudentNode *head;
};

//析构函数定义
StudentLinkList::~StudentLinkList()
{
    // 初始化一个指针current,指向链表的头节点head
    StudentNode *current = head;
    // 当current不为空时,说明还有节点需要被删除 
    while (current != nullptr)
    {
        // 保存当前节点的下一个节点的指针
        StudentNode *next = current->next;
        // 删除当前节点,释放其占用的内存
        delete current;
        // 将current指针移动到下一个节点,继续删除操作 
        current = next;
    }
    // 将头节点指针设置为nullptr,表示链表为空
    head = nullptr;
}

//增添学生信息
void StudentLinkList::addStudent(unsigned sn, const string &na,
                                 int ag, const string &se)
{
    //创建一个新的StudentNode对象,并使用传入的参数初始化它。这个新节点会被添加到链表的末尾。
    StudentNode *newNode = new StudentNode(sn, na, ag, se);
    //如果链表为空(即head为nullptr),则直接将新节点设置为链表的头节点。
    if (head == nullptr)
    {
        head = newNode;
    }
    //如果链表不为空,初始化一个指针current,使其指向链表的头节点。
    else
    {
        StudentNode *current = head;
        //使用一个循环遍历链表,直到找到链表的最后一个节点(即next指针为nullptr的节点)。
        while (current->next != nullptr)
        {
            current = current->next;
        }
        //将最后一个节点的next指针指向新创建的节点,从而将新节点添加到链表的末尾
        current->next = newNode;
    }
}

//用于打印出学生信息
void StudentLinkList::printStudent()
{
    //将当前节点指向头节点
    StudentNode *current = head;
    //遍历整个链表,对联表内的所有内容进行打印
    while (current != nullptr)
    {
        cout << "Student Number: " << current->studentNumber
             << ", Name: " << current->name
             << ", Age: " << current->age
             << ", Sex: " << current->sex << endl;
        //打印完当前节点后将指针移动向下一节点
        current = current->next;
    }
}

int main()
{
    StudentLinkList student;

    student.addStudent(2410145903, "Zhangsan", 18, "Man");
    student.addStudent(2415343923, "Lisi", 21, "Man");
    student.addStudent(2345351878, "Wangwu", 19, "Man");
    student.printStudent();

    return 0;
}

九.运行示例 

  • 37
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值