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有点反胃,然后就看到这个教程,某州教育的,刚开始没发现,还一会会有干活,但是后来就越听越恶心,最主要是,功能不全,而且非常老旧,气死人,中途老师只知道说用什么函数,就是不讲为什么,简直是差劲的要死,我算是服了,想骂人的冲动已然熊熊燃烧,如果以后会做老师,也会跟这家对着干。

.
下一次再写代码的时候应该边写边做笔记,而不是这样写完之后发现自己好像没怎么出错。
.
遇到类型转换的东西,不能慌,也别乱,看到长文就不想看,这样是不行的,可是事实就是这样
.
另外,需要实现检测输入以及文件写入的功能
备注:原工程文件[其实上面有,多加一个入口,方便以后使用]
备注:如果转载,请著名来源以及作者。

发布了14 篇原创文章 · 获赞 9 · 访问量 4241

猜你喜欢

转载自blog.csdn.net/qq_37766828/article/details/103940791