01-0001 C++實現學生信息管理系統 [第一篇]

C++實現學生信息管理系統[界面+數據處理]

1.簡單的問題描述

1.自行設計學生信息管理系統
2.實現學生信息錄入、刪除、查找以及瀏覽的功能[這個需求真的是噁心]
3.使用EasyX圖形庫,實現界面
4.參考視頻:https://www.bilibili.com/video/av13231926

2.遇到的相關問題

2.1 重複包含

在這裏插入圖片描述

備註:添加較爲完整的問題描述

2.2 在Unicode字符集下面聲明並初始化LPCTSTR類型的數組

LPCTSTR s[5] = { L"學號",L"姓名",L"英語",L"數學",L"語文" };

備註:LP【指針】、C【const】、W【wide寬字符】、T【表示在Win32環境中, 有一個_T宏】
參考鏈接:1、LPCTSTR LPCWSTR LPCSTR 含義
2、LPTSTR、LPCSTR、LPCTSTR、LPSTR的來源及意義 VS2005 中error C2440: 如無法從“const char [N]”轉換爲“LPCWSTR” 的一點總結[外網]

2.3 LPTSTR的初始化

LPTSTR temp=new TCHAR[10];

看一下 LPTSTR 的定義便可知應該怎麼初始化,如下:

#ifdef _UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif // _UNICODE

typedef const TCHAR* LPCTSTR;
typedef TCHAR* LPTSTR

事實上TCHAR就是寬字符類型,而LPTSTR則是寬字符類型的指針,初始化的時候只有兩種方式,new TCHAR,或者是new TCHAR[SIZE],類比的如下

char* a=new char;
char* b=new char[100]
//標準規定,char佔8位,也就是一個字節

2.4 CString轉換爲LPTSTR,CString字符串的連接,其他類型轉換爲CString

CString str;
//int to CString
int a=1;
str.Format(_T("%d"), a);
//float to CString
float b=1.2;
str.Format(_T("%f"), b);
//char* to CString
char* name="Liming";
str=name;

//CSting to LPTSTR
LPTSTR out_str;
out_str=str.GetBuffer();

//CString字符串的連接
CString str1;
CString str2;
str2+=str1;

2.5 函數中傳入了const類型的參數,卻要返回沒有const的數據,需要結束const並返回

//Studet是個學生類,有一個name屬性
//將Student對象存儲在vector之中
//定義search方法,返回找到對應數據時指向該數據的指針
Student* search(const vector<Student>& v, const char* name) {
    int count = 0;
    for (auto it : v) {
        if (!strcmp(it.name,name)){
            return const_cast<Student*>(&v[count]);
        }
        count++;
    }
    return NULL;
}

//下面語句解除const使得該指針能夠返回
//複製代碼的時候不要都複製,只複製上面函數部分即可
return const_cast<Student*>(&v[count]);

2.6 有一個指向數組或者向量某元素的指針,判斷這個元素是第幾個

vector<int> v;//生命一個向量,需要初始化,但這裏沒有
int* a=&v[3];//指針指向第四個元素
int rank=a-&v[0];//得到該元素的秩
v.erase(v.begin()+(a-&v[0]));//釋放該元素

2.7 debug_heap.cpp、line904、_crtisvalidheappointer不知道是什麼原因的錯誤

	//debug_heap.cpp line904 _crtisvalidheappointer
    LPTSTR temp = new TCHAR[10];
    InputBox(temp, 10, L"請輸入學生姓名:");
    outtextxy(183, 86, temp);
    USES_CONVERSION;
    char* c_temp=new char[20];
    c_temp = T2A(temp);
    stu.name = new char[strlen(c_temp) + 1];
    strcpy_s(stu.name, strlen(c_temp) + 1, c_temp);
    delete[] c_temp;//這裏會出錯,不知道是什麼原因
    //推測是,重複delete了同一塊內存空間

3.源代碼

地址:原工程文件,也可以拷貝下面的源碼,自己新建工程。
文件1:School.h

#ifndef SCHOOL_H_
#define SCHOOL_H_

#include <iostream>
#include <vector>
#include <graphics.h>
#include <mmstream.h>//包含多媒體設備接口的頭文件
#pragma comment(lib,"winmm.lib")//包含多媒體設備接口的庫文件
#include "Student.h"
using namespace std;
const int win_width = 600;
const int win_hight = 400;
IMAGE bkimg, butimg;

//管理系統界面的初始化
void iniInterface();
//初始化:管理系統聲音
void iniSound();
//初始化:管理系統文字
void iniText();
//整體初始化
void beginItf();
//插入數據
void insertIfo(vector<Student>& v);
//檢測鼠標相關事件
void butPress(vector<Student>& v);
//搜索數據
void searchIfo(const vector<Student>& v);
//瀏覽數據
void scanIfo(const vector<Student>& v);
//刪除數據
void deleteIfo(vector<Student>& v);
//重載兩個查找函數
//可以使用學號或者是姓名查找
Student* search(const vector<Student>& v, const int id);
Student* search(const vector<Student>& v, const char* name);
//重載了EasyX中的文字輸出函數
void outtextxy(int x, int y, Student s);
#endif // !SCHOOL_H_
文件2:Student.h
#pragma once
#include<iostream>
class Student {
public:
	int id;
	char *name;
	float s_english;
	float s_math;
	float s_chinese;
};
//之所以使用char*,是爲了方便後面的類型轉換
文件3:School.cpp
#include "School.h"
#include <atlconv.h>
#include <atlstr.h>
#include <cstring>
int main()
{
    //數據存儲位置
    vector<Student> stu_vct;//使用向量來存儲學生數據
    //vector<Student>* stu_p = &stu_vct;//聲明指針指向存儲學生數據的向量,以節省空間
    Student s1={1111,(char*)"張三",123,123,123};
    Student s2={2222,(char*)"李四",123,123,123 };
    stu_vct.push_back(s1);
    stu_vct.push_back(s2);

    //初始化
    initgraph(win_width, win_hight);
    beginItf();
    butPress(stu_vct);

    //函數尾部,卡屏,關閉圖片流
    std::cin.get();
    closegraph();
    cout << stu_vct[0].id << endl;
    std::cout << "Hello World!\n";
}


//檢測鼠標相關事件
void butPress(vector<Student>& v) {
    MOUSEMSG msg{};
    while (true) {
        msg = GetMouseMsg();
        switch (msg.uMsg) {
        case WM_LBUTTONDOWN://鼠標左鍵按下
            if (msg.x > 200 && msg.x < 400 && msg.y>80 && msg.y < 130) {
                //錄入信息
                insertIfo(v);
                beginItf();
            }
            if (msg.x > 200 && msg.x < 400 && msg.y>140 && msg.y < 190) {
                //查找信息
                searchIfo(v);
                beginItf();
            }
            if (msg.x > 200 && msg.x < 400 && msg.y>200 && msg.y < 250) {
                //刪除信息
                deleteIfo(v);
                beginItf();
            }
            if (msg.x > 200 && msg.x < 400 && msg.y>260 && msg.y < 310) {
                //瀏覽信息
                scanIfo(v);
                beginItf();
            }
            break;
        case WM_MOUSEMOVE://鼠標移動
            if (msg.mkLButton) {
                //移動過程中點擊鼠標左鍵要做的事情
                //...
            }
            break;
        default:
            break;
        }
    }
}

//插入一條學生信息
void insertIfo(vector<Student>& v) {
    //功能完善:
    //  1.不能重複插入,如果已經存在該學生信息,需要給出提示
    //  2.檢測對於不正當的輸入,直到用戶輸入正確內容後停止
    //  3.支持直接返回,按back鍵等,可以直接返回
    //  4.支持文件寫入,如果能夠插入,則需要將該內容寫入文件
    Student stu;
    putimage(0, 0, &bkimg);//使得背景不發生變化
    //char s[][5]={ "學號","姓名","英語","數學","語文" };
    //TCHAR* s[5] = { L"學號","姓名","英語","數學","語文" };
    LPCTSTR s[5] = { L"學號",L"姓名",L"英語",L"數學",L"語文" };
    for (int i = 0; i < 5; i++) {
        setlinecolor(RED);
        rectangle(100, 50 + i * 35, 500, 85 + i * 35);
        outtextxy(100, 51 + i * 35, s[i]);
    }
    line(180, 50, 180, 225);
    
    //LPSTR:32bit指針指向一個字符串,每個字符佔1字節,等價與char 
    LPTSTR temp=new TCHAR[10];

    InputBox(temp, 10, L"請輸入學生id:");
    outtextxy(183, 51, temp);
    stu.id = _wtoi(temp);


    InputBox(temp, 10, L"請輸入學生姓名:");
    outtextxy(183, 86, temp);
    USES_CONVERSION;
    char* c_temp;
    c_temp= T2A(temp);
    stu.name = new char[strlen(c_temp) + 1];
    strcpy_s(stu.name,strlen(c_temp)+1, c_temp);

    InputBox(temp, 10, L"請輸入英語成績:");
    outtextxy(183, 121, temp);
    stu.s_english = _wtof(temp);

    InputBox(temp, 10, L"請輸入數學成績:");
    outtextxy(183, 156, temp);
    stu.s_math = _wtof(temp);

    InputBox(temp, 10, L"請輸入數學成績:");
    outtextxy(183, 191, temp);
    stu.s_chinese = _wtof(temp);

    delete[] temp;//應該清除的是temp而不是上面的c_temp
    v.push_back(stu);
}
//搜索一條學生信息
void searchIfo(const vector<Student>& v) {
    //支持查找id或者姓名
    //下面關於界面的兩條語句應該封裝成一個
    putimage(0, 0, &bkimg);//使得背景不發生變化
    settextcolor(RGB(93, 107, 153));//調整文字顏色
    settextstyle(15, 0, L"楷體");

    LPTSTR temp = new TCHAR[10];
    InputBox(temp, 10, L"請輸入學生id或學生姓名:");
    int t_id;
    char* t_name;
    Student* s;
    if (t_id= _wtoi(temp)) {
        //可以使用find_if
        s=search(v, t_id);
        if (s != NULL) {
            outtextxy(0, 0, *s);
            outtextxy(0, 16, L"請按任意鍵返回...");
            cin.get();
        }
        else {
            outtextxy(0, 0, L"沒有該學生,請按任意鍵返回...");
            cin.get();
        }
    }
    else {
        USES_CONVERSION;
        t_name = W2A(temp);
        s = search(v, t_name);
        if (s != NULL) {
            outtextxy(0, 0, *s);
            outtextxy(0, 16, L"請按任意鍵返回...");
            cin.get();
        }
        else {
            outtextxy(0, 0, L"沒有該學生,請按任意鍵返回...");
            cin.get();
        }
    }
}
//刪除學生信息
void deleteIfo(vector<Student>& v) {
    putimage(0, 0, &bkimg);//使得背景不發生變化
    settextcolor(RGB(93, 107, 153));//調整文字顏色
    settextstyle(15, 0, L"楷體");
    Student* s;
    int t_id;
    LPTSTR temp = new TCHAR[10];
    InputBox(temp, 10, L"請輸入學生id:");
    if (t_id = _wtoi(temp)) {
        //可以使用find_if
        s = search(v, t_id);
        if (s != NULL) {
            outtextxy(0, 0, *s);
            v.erase(v.begin() + (s - &v[0]));//利用指針按照元素塊可加減的原理,調用erase()函數
            outtextxy(0,16,L"已經成功刪除,請按任意鍵返回...");
            cin.get();
        }
        else {
            outtextxy(0, 0, L"沒有該學生,請按任意鍵返回...");
            cin.get();
        }
    }

}

void scanIfo(const vector<Student>& v) {
    //需要設置滾動效果,忽略掉了,是在不想寫,噁心
}

//將下面幾個初始化封裝在了一起
void beginItf() {
    iniSound();
    iniInterface();
    iniText();
}

//初始化:管理系統界面
void iniInterface() {

    //加載圖片
    loadimage(&bkimg, L"./res/bkimg.jpg", 600, 400);//後兩個參數爲縮放比例
    loadimage(&butimg, L"./res/butimg.jpg", 200, 50);//後兩個參數爲縮放比例
    //loadimage(NULL, L"./res/bkimg.jpg", 600, 400);//直接將圖片輸出到控制檯,但是測試的時候並沒有

    //貼圖片--朝某流輸出圖片
    putimage(0, 0, &bkimg);//座標系在左上角,朝下
    putimage(200, 80, &butimg);
    putimage(200, 140, &butimg);
    putimage(200, 200, &butimg);
    putimage(200, 260, &butimg);
}

//初始化:管理系統聲音
void iniSound() {
    //打開並播放mp3文件
    //mciSendString(L"open ./res/bkmusic.mp3 alias bgm", 0, 0, 0);//添加背景音樂
    //mciSendString(L"play bgm repeat", 0, 0, 0);//播放背景音樂

    //播放wav格式的文件
    //PlaySound(L"./res/music.wav", NULL, SND_FILENAME | SND_LOOP | SND_ASYNC);//最後一個參數控制異步播放
}

//初始化:管理系統文字
void iniText() {
    //設置文字樣式
    settextstyle(30, 0, L"楷體");
    //設置文字顏色
    settextcolor(RGB(204, 213, 240));
    //設置文字模式
    setbkmode(TRANSPARENT);
    //指定位置輸出文字
    outtextxy(180, 20, L"XXX學校管理系統");
    outtextxy(247, 88, L"錄入信息");
    outtextxy(247, 148, L"查找信息");
    outtextxy(247, 208, L"刪除信息");
    outtextxy(247, 268, L"瀏覽信息");
}

Student* search(const vector<Student>& v, const int id) {
    int count=0;
    for (auto it : v) {
        if (it.id == id) {
            return const_cast<Student*>(&v[count]);
        }
        count++;
    }
    return NULL;
}

Student* search(const vector<Student>& v, const char* name) {
    int count = 0;
    for (auto it : v) {
        if (!strcmp(it.name,name)){
            return const_cast<Student*>(&v[count]);
        }
        count++;
    }
    return NULL;
}

void outtextxy(int x, int y, Student s) {
    //連接成整個字符串,統一輸出
    LPTSTR out_LPT;
    CString str;
    CString out_str;
    str.Format(_T("%d"), s.id);
    out_str =out_str + "ID:"  + str + " ";
    str = s.name;
    out_str = out_str+ "姓名:" + str + " ";
    str.Format(_T("%.1f"), s.s_english);
    out_str = out_str + "英語:" +  str + " ";
    str.Format(_T("%.1f"), s.s_math);
    out_str = out_str + "數學:" + str + " ";
    str.Format(_T("%.1f"), s.s_chinese);
    out_str = out_str + "語文:" + str;
    out_LPT = out_str.GetBuffer();
    cout << "name" << endl;
    outtextxy(0, 0, out_LPT);
}
效果

在這裏插入圖片描述

4.吐槽

本來就是想找個管理系統好好做一做,一直看c++ primer plus有點反胃,然後就看到這個教程,某州教育的,剛開始沒發現,還一會會有幹活,但是後來就越聽越噁心,最主要是,功能不全,而且非常老舊,氣死人,中途老師只知道說用什麼函數,就是不講爲什麼,簡直是差勁的要死,我算是服了,想罵人的衝動已然熊熊燃燒,如果以後會做老師,也會跟這家對着幹。

.
下一次再寫代碼的時候應該邊寫邊做筆記,而不是這樣寫完之後發現自己好像沒怎麼出錯。
.
遇到類型轉換的東西,不能慌,也別亂,看到長文就不想看,這樣是不行的,可是事實就是這樣
.
另外,需要實現檢測輸入以及文件寫入的功能
備註:原工程文件[其實上面有,多加一個入口,方便以後使用]
備註:如果轉載,請著名來源以及作者。

發佈了16 篇原創文章 · 獲贊 9 · 訪問量 4676
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章