真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

2023-01-12用C++完成一個多平臺可用的學生管理系統(tǒng)-創(chuàng)新互聯(lián)

用C++完成一個跨平臺可用的學生管理系統(tǒng)
  • 前言
  • 一、Windows和Linux終端編碼
  • 二、完整代碼
  • 總結(jié)

創(chuàng)新互聯(lián)成立于2013年,先為商城等服務建站,商城等地企業(yè),進行企業(yè)商務咨詢服務。為商城企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。
前言

學生管理系統(tǒng)可能是計算機相關專業(yè)學生在學完C語言和C++之后能做的比較完整的一個程序, 所以問答中經(jīng)常出現(xiàn). 例如設計學生成績管理系統(tǒng).

用C語言或C++的基本特性就完全能夠解決, 基本用不到多線程, 多態(tài), 模板等.

但有個小問題, 在Windows平臺和Linux平臺, 對中文的編碼和輸出不太一樣, Windows終端是GBK編碼, 雖然可以用簡單命令轉(zhuǎn)為UTF-8編碼, 但實踐操作中發(fā)現(xiàn), 這只適用于漢字輸出, 對于輸入是一塌糊度. 如果是純Windows平臺程序, 我倒是建議將代碼編碼格式直接設置為GBK, 這樣對于輸入輸出不會有什么問題, 只不過會有一些編碼警告, 忽略即可.

如果要跨平臺, 甚至日后進行拓展, 則需要UTF-8編碼, 而對編碼的轉(zhuǎn)換, 需要一些函數(shù)實現(xiàn), 目前問題主要集中在Windows中.


一、Windows和Linux終端編碼

可能是某些歷史原因, Windows終端選擇用GBK編碼, 而Linux終端則選擇用utf8編碼, 這導致了跨平臺IO的不同, 一套代碼不能在兩個平臺使用.

以前我們討論過, 關于中文編碼, 存儲, 編碼轉(zhuǎn)換, 多字節(jié), 寬字節(jié)等等, 總之到處是坑, 防不勝防, 不親自踩幾個坑, 很難知道這水有多混.

由于Linux終端編碼如此貼心, 無需太多顧忌, 我們只需處理號Windows終端編碼就好了.

我們需要判斷目前程序是在哪個平臺, 于是要用到宏:

#ifdef __WIN64
    SetConsoleOutputCP(CP_UTF8); // 終端輸出的是UTF8編碼
    SetConsoleCP(CP_ACP);        // 終端輸入的是GBK編碼
#endif

以上代碼的意思是如果定義了win64, 也就是在Windows64平臺, 那么設置輸出編碼是UTF8, 輸入編碼是系統(tǒng)的local編碼, 也就是中文GBK. 當然以上編碼需要windows.h頭文件, 這個會在下面程序代碼中.

為什么不把輸入編碼設為UTF8, 和Linux一樣, 這樣就省事多了. 開始我也是這么想的, 但是馬上就踩坑了, 當輸入設置為utf8, 漢字無法輸入, 我不知到它究竟將漢字轉(zhuǎn)換成什么東西, 總之是不可以, 這個終端黑盒沒有透露什么細節(jié), 所以沒辦法.

退而求其次, 用終端local編碼進行輸入, 因為我們的程序編碼是utf8, 輸入進來的是GBK, 中間沒有轉(zhuǎn)化, 所以如果直接看, 就是亂碼, 直接輸出也是亂碼.

為了補足編碼轉(zhuǎn)換, 我用了下面這個Windows專有的轉(zhuǎn)換函數(shù). 通過終端傳過來的四不像編碼文字轉(zhuǎn)換為寬字符( MultiByteToWideChar() ), 再將寬字符轉(zhuǎn)回真正的utf8編碼文字( WideCharToMultiByte() ).

細節(jié)上, 由于名字很可能有空格, 所以需要讀取整行, 但是通常如果直接讀會讀到上一個輸入剩下的換行符, 完美錯過真正的內(nèi)容, 所以需要進行輸入流清空( ignore() ). 同時為防止姓名字過多, 一般是故意的, 但某些國家名字百八十個字母也是有的, 需要在超出緩沖區(qū)后清空輸入流, 以防止后續(xù)直接跳出.

為了節(jié)省點創(chuàng)建緩沖區(qū)時間, 我把緩沖區(qū)設置為靜態(tài)區(qū)域, 但要注意, 靜態(tài)區(qū)域在你用完后不會自己清空, 所以需要手動清空,以備后用.

#ifdef __WIN64
#includevoid gbkToUtf8(std::istream &istm, char *chrs)
{static char temp[BUFFERSIZE] = {};
    static wchar_t wTemp[WCHARBUFFERSIZE] = {};
    istm.clear();
    istm.ignore(CLEARCHARSIZE, '\n');
    if (!istm.getline(temp, BUFFERSIZE))
    {istm.clear();
        istm.ignore(CLEARCHARSIZE, '\n');
    }
    MultiByteToWideChar(CP_ACP, 0, temp, -1, wTemp, WCHARBUFFERSIZE);
    WideCharToMultiByte(CP_UTF8, 0, wTemp, -1, chrs, BUFFERSIZE, nullptr,
                        nullptr);
    memset(reinterpret_cast(temp), 0, BUFFERSIZE);
    memset(reinterpret_cast(wTemp), 0, BUFFERSIZE);
}
#endif
二、完整代碼

這是基本要求, 不難實現(xiàn):

設計和實現(xiàn)一個“學生成績管理系統(tǒng)”,滿足以下要求:

  1. 系統(tǒng)以菜單方式工作;
  2. 使用鏈表或結(jié)構(gòu)數(shù)組對學生成績進行管理和維護;
  3. 使用二進制文件在磁盤上保存學生記錄信息;
  4. 鏈表中各結(jié)點或結(jié)構(gòu)數(shù)組中各元素包括“學號、姓名、成績數(shù)組(含計算機、數(shù)學、
    物理、外語四門課程)、總分”基本字段;
  5. 實現(xiàn)如下基本功能:
    (1) 查看所有學生信息
    (2) 計算總分
    (3) 排序
    按學號排序
    按總分排序
    (4) 添加學生(此功能下可實現(xiàn)學生信息的錄入)
    (5) 插入學生(在已按學號有序的提下,將學生插入到合適的位置)
    (6) 查找學生(查找并顯示學生的學號、姓名、四門課程成績、總分)
    按學號查找
    按姓名查找
    查詢每門課成績都在80分以上的學生信息
    (7) 刪除學生 ( 刪除指定學號的學生 )
    (8) 將學生記錄保存到文件存盤 ( 將數(shù)據(jù)以文件的形式存盤 )
    (9) 從文件中讀入學生記錄 ( 將已經(jīng)存盤的文件數(shù)據(jù)讀入內(nèi)存 )

為了滿足二進制存儲和讀取, 學生類不能用string或vector這種非平凡類對象成員, 這樣只能用char數(shù)組表示名字的字符串, 但為了進行方便比較, 還是實現(xiàn)一個函數(shù)將字符串轉(zhuǎn)換為string.

為了便于添加和排序以及查找, 我用list鏈表存儲學生數(shù)據(jù). 由于各成員函數(shù)使用了大量算法庫中的函數(shù), 所以也大量引入了簡單的lambda閉包, 如果你對lambda不熟悉, 請務必盡快熟悉, 否則C++高級性質(zhì)就基本與你無緣. 另外, 某些算法函數(shù)會再套用算法函數(shù), 不必害怕, 都非常簡單, 相比于自己實現(xiàn), 這種函數(shù)套用更為方便, 且語義更為準確.

菜單實現(xiàn)選擇太多, 就不要用if語句了, swich語句是最為合適的.

#include 
#include#include#include#include#include#define BUFFERSIZE 32
#define WCHARBUFFERSIZE 16
#define CLEARCHARSIZE 1024

#ifdef __WIN64
#includevoid gbkToUtf8(std::istream &istm, char *chrs)
{static char temp[BUFFERSIZE] = {};
    static wchar_t wTemp[WCHARBUFFERSIZE] = {};
    istm.clear();
    istm.ignore(CLEARCHARSIZE, '\n');
    if (!istm.getline(temp, BUFFERSIZE))
    {istm.clear();
        istm.ignore(CLEARCHARSIZE, '\n');
    }
    MultiByteToWideChar(CP_ACP, 0, temp, -1, wTemp, WCHARBUFFERSIZE);
    WideCharToMultiByte(CP_UTF8, 0, wTemp, -1, chrs, BUFFERSIZE, nullptr,
                        nullptr);
    memset(reinterpret_cast(temp), 0, BUFFERSIZE);
    memset(reinterpret_cast(wTemp), 0, BUFFERSIZE);
}
#endif

struct student
{student() = default;

    explicit student(std::istream &istm)
    {std::cout<< "輸入學號: "<< std::endl;
        istm >>xueHao;
        std::cout<< "輸入姓名"<< std::endl;

#ifdef __WIN64
        gbkToUtf8(istm, xingMing);
#endif

#ifndef __WIN64
        istm >>xingMing;
#endif
        std::cout<< "輸入計算機成績"<< std::endl;
        istm >>jiSuanJiChengJi;
        std::cout<< "輸入數(shù)學成績"<< std::endl;
        istm >>shuXueChengJi;
        std::cout<< "輸入物理成績"<< std::endl;
        istm >>wuLiChengJi;
        std::cout<< "輸入外語成績"<< std::endl;
        istm >>waiYuChengJi;
        zongFen = jiSuanJiChengJi + shuXueChengJi + wuLiChengJi + waiYuChengJi;
    }

    [[nodiscard]] auto showZongFen() const ->int
    {return zongFen;
    }

    [[nodiscard]] auto showXueHao() const ->int
    {return xueHao;
    }

    [[nodiscard]] auto showXingMing() const ->std::string
    {return xingMing;
    }

    void print() const
    {std::cout<< xueHao<< '\t'<< xingMing<< '\t'<< jiSuanJiChengJi
       << '\t'<< shuXueChengJi<< '\t'<< wuLiChengJi<< '\t'
       << waiYuChengJi<< '\t'<< zongFen<< '\n';
    }

    void printZongFen() const
    {std::cout<< xueHao<< '\t'<< xingMing<< '\t'<< zongFen<< '\n';
    }

    void printTo(std::ostream &ostm) const
    {ostm.write(reinterpret_cast(this), sizeof(student));
    }

    [[nodiscard]] auto everyScoreUp(int num) const ->bool
    {return jiSuanJiChengJi >num && shuXueChengJi >num &&
               wuLiChengJi >num && waiYuChengJi >num;
    }

  private:
    int xueHao = 0;
    char xingMing[BUFFERSIZE] = {};
    int jiSuanJiChengJi = 0;
    int shuXueChengJi = 0;
    int wuLiChengJi = 0;
    int waiYuChengJi = 0;
    int zongFen = 0;
};

struct studentVector
{studentVector() = default;

    void viewStudent()
    {std::cout<< "學號\t姓名\t計算機\t數(shù)學\t物理\t外語\t總分\n";
        std::for_each(studentList.begin(), studentList.end(),
                      [](const student &stu) {stu.print(); });
    }

    void viewZongFen()
    {std::cout<< "學號\t姓名\t總分\n";
        std::for_each(studentList.begin(), studentList.end(),
                      [](const student &stu) {stu.printZongFen(); });
    }

    void sortWithXueHao()
    {studentList.sort([](const student &stuA, const student &stuB) {return stuA.showXueHao()< stuB.showXueHao();
        });

        sortXueHao = true;
    }

    void sortWithZongFen()
    {studentList.sort([](const student &stuA, const student &stuB) {return stuA.showZongFen() >stuB.showZongFen();
        });

        sortXueHao = false;
    }

    void pushStudent(const student &stu)
    {studentList.push_back(stu);

        sortXueHao = false;
    }

    void insertStudent(const student &stu)
    {if (sortXueHao)
        {studentList.insert(
                std::find_if(studentList.begin(), studentList.end(),
                             [&stu](const student &stuA) { return stu.showXueHao()< stuA.showXueHao();
                             }),
                stu);
        }
        else
        {sortWithXueHao();

            studentList.insert(
                std::find_if(studentList.begin(), studentList.end(),
                             [&stu](const student &stuA) { return stu.showXueHao()< stuA.showXueHao();
                             }),
                stu);
        }
    }

    void searchStudentWithXueHao(int xueHao_)
    {auto result = std::find_if(studentList.begin(), studentList.end(),
                                   [&xueHao_](const student &stu) {   return xueHao_ == stu.showXueHao();
                                   });

        if (result != studentList.end())
        {result->print();
        }
    }

    void searchStudentWithXingMing(const std::string &xingMing_)
    {auto result = std::find_if(studentList.begin(), studentList.end(),
                                   [&xingMing_](const student &stu) {   return xingMing_ == stu.showXingMing();
                                   });

        if (result != studentList.end())
        {result->print();
        }
    }

    void searchStudentWithEveryScoreUp80()
    {std::for_each(studentList.begin(), studentList.end(),
                      [](const student &stu) {  if (stu.everyScoreUp(80))
                          {  stu.print();
                          }
                      });
    }

    auto deleteStudent(int xueHao_) ->bool
    {auto result = std::find_if(studentList.begin(), studentList.end(),
                                   [&xueHao_](const student &stu) {   return xueHao_ == stu.showXueHao();
                                   });

        if (result != studentList.end())
        {studentList.erase(result);
            return true;
        }

        return false;
    }

    void save()
    {std::ofstream file("studentVector.bak");

        std::for_each(studentList.begin(), studentList.end(),
                      [&file](const student &stu) {stu.printTo(file); });
    }

    void read()
    {std::ifstream file("studentVector.bak");

        student stu;

        while (file.read(reinterpret_cast(&stu), sizeof(student)))
        {studentList.push_back(stu);
        }
    }

  private:
    std::liststudentList;
    bool sortXueHao = false;
};

void pritnCaiDan()
{std::cout<< "學生成績管理系統(tǒng), 請按相應數(shù)字進行操作\n";
    std::cout<< "————————————————————命令概覽—————————————————————\n";
    std::cout<< "| 1 查看學生信息\t\t\t\t|\n";
    std::cout<< "| 2 計算學生總分\t\t\t\t|\n";
    std::cout<< "| 3 按照學號排序(由小到大)\t\t\t|\n";
    std::cout<< "| 4 按照總成績排序(由高到低)\t\t\t|\n";
    std::cout<< "| 5 添加學生\t\t\t\t\t|\n";
    std::cout<< "| 6 插入學生\t\t\t\t\t|\n";
    std::cout<< "| 7 按學號查找學生信息\t\t\t\t|\n";
    std::cout<< "| 8 按姓名查找學生信息\t\t\t\t|\n";
    std::cout<< "| 9 查找每門高于80分學生信息\t\t\t|\n";
    std::cout<< "| 10 刪除指定學號的學生\t\t\t\t|\n";
    std::cout<< "| 11 保存到指定文件\t\t\t\t|\n";
    std::cout<< "| 12 從指定文件讀取數(shù)據(jù)\t\t\t\t|\n";
    std::cout<< "| 15 退出程序\t\t\t\t\t|\n";
    std::cout<< "—————————————————————————————————————————————————\n";
}

auto main() ->int
{#ifdef __WIN64
    SetConsoleOutputCP(CP_UTF8); // 終端輸出的是UTF8編碼
    SetConsoleCP(CP_ACP);        // 終端輸入的是GBK編碼
#endif

    studentVector stuVec;
    pritnCaiDan();
    int caiDanXuanXiang = 0;
    while (std::cin >>caiDanXuanXiang)
    {switch (caiDanXuanXiang)
        {case 1:
            stuVec.viewStudent();
            break;
        case 2:
            stuVec.viewZongFen();
            break;
        case 3:
            stuVec.sortWithXueHao();
            break;
        case 4:
            stuVec.sortWithZongFen();
            break;
        case 5:
            stuVec.pushStudent(student(std::cin));
            break;
        case 6:
            stuVec.insertStudent(student(std::cin));
            break;
        case 7: {std::cout<< "請輸入學號: "<< std::endl;
            int xueHao_;
            std::cin >>xueHao_;
            std::cout<< "學號\t姓名\t計算機\t數(shù)學\t物理\t外語\t總分\n";
            stuVec.searchStudentWithXueHao(xueHao_);
            break;
        }
        case 8: {std::cout<< "請輸入學生姓名: "<< std::endl;

#ifdef __WIN64
            static char temp[BUFFERSIZE] = {};
            gbkToUtf8(std::cin, temp);
            std::cout<< "學號\t姓名\t計算機\t數(shù)學\t物理\t外語\t總分\n";
            stuVec.searchStudentWithXingMing(temp);
            memset(reinterpret_cast(temp), 0, BUFFERSIZE);
            break;
#endif

#ifndef __WIN64
            std::string xingMing_;
            std::cin >>xingMing_;

            std::cout<< "學號\t姓名\t計算機\t數(shù)學\t物理\t外語\t總分\n";
            stuVec.searchStudentWithXingMing(xingMing_);
            break;
#endif
        }
        case 9: {std::cout<< "學號\t姓名\t計算機\t數(shù)學\t物理\t外語\t總分\n";
            stuVec.searchStudentWithEveryScoreUp80();
            break;
        }
        case 10: {std::cout<< "請輸入學號: "<< std::endl;
            int xueHao_;
            std::cin >>xueHao_;
            stuVec.deleteStudent(xueHao_);
            break;
        }
        case 11:
            stuVec.save();
            break;
        case 12:
            stuVec.read();
            break;
        case 15:
            return 0;
            break;
        }
        std::cout<< "\n\n";
        pritnCaiDan();
    }

    return 0;
}

總結(jié)

學生管理系統(tǒng), 可以說是最簡單, 只需要基礎 IO 知識就可以編寫的完整有用的程序, 如果不用跨平臺, 那是相當簡單. 簡單程序也可以逐漸擴展, 比如socket編程, 遠程調(diào)用, 比如連接數(shù)據(jù)庫進行增刪改查, 甚至多線程調(diào)用, 比如 qt 加圖形菜單稱為一個界面程序.

路漫漫其修遠兮, 吾將上下而求索.

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


當前題目:2023-01-12用C++完成一個多平臺可用的學生管理系統(tǒng)-創(chuàng)新互聯(lián)
標題URL:http://weahome.cn/article/hgoge.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部