当前位置: 代码迷 >> 综合 >> 01-0001 C++实现学生信息管理系统 [第一篇]
  详细解决方案

01-0001 C++实现学生信息管理系统 [第一篇]

热度:30   发布时间:2023-11-24 01:59:52.0

C++实现学生信息管理系统[界面+数据处理]

  • 1.简单的问题描述
  • 2.遇到的相关问题
  • 3.源代码
  • 4.吐槽

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

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