程序源代码(非完整及完善版本,只作参考,不供实现):

程序代码:
#include <Windows.h>
#include <vector>
#include <string>
#include <locale>
#include <algorithm>
#include <numeric>
#include <conio.h>
#include "myConsole.h"
using namespace std;
// 学生信息数据结构
struct Student_Info
{
int ID; // 学号
wchar_t Name[11]; // 姓名
double Scores[4]; // 学科成绩
};
// 表格数据结构
struct Column_Info
{
wchar_t Caption[20]; // 标题名
wchar_t Separate; // 分隔符
size_t Width; // 栏宽
};
// 游标数据结构
struct Pointer_Info
{
int Row; // 行号
vector<Student_Info>::iterator current; // 指向的记录
};
// 全局变量
const Column_Info Columns[] =
{
{ L"学号", L'=', 4 },
{ L" 姓名 ", L'=', 10 },
{ L" 语文 ", L'=', 8 },
{ L" 数学 ", L'=', 8 },
{ L" 英语 ", L'=', 8 },
{ L" 计算机 ", L'=', 8 }
};
const wstring FileName(L"Students.dat");
const wstring Tips1(L"Esc:结束 Enter:编辑 Ins:增加 Del:删除 F2:存盘 F3:读盘 F4:排序");
const SMALL_RECT DataRect = { 4, 0, 79, 23 };
const SMALL_RECT TipsRect = { 0, 24, 79, 24 };
const int PageRecords(DataRect.Bottom - DataRect.Top - 2);
myConsole Console(GetStdHandle(STD_OUTPUT_HANDLE));
vector<Student_Info> Students;
Pointer_Info Pointer;
// 函数原型
void Show_Tips(const wstring tips);
void Set_Pointer(Pointer_Info& pointer, bool on);
void Show_Data(const vector<Student_Info>::iterator first);
void Append_Data(void);
void Edit_Data(const vector<Student_Info>::iterator current, int row);
bool Save_Data(const wchar_t file_name[]);
bool Load_Data(const wchar_t file_name[]);
bool IsGreater(const Student_Info& lhs, const Student_Info& rhs);
// 程序入口
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
setlocale(LC_ALL, "chs");
if (!Load_Data(FileName.c_str()))
{
wprintf_s(L"文件%s打开失败,请检查再试。\n", FileName.c_str());
Console.ReadKey();
return EXIT_FAILURE;
}
Console.SetTitle(L"学生成绩处理");
Console.Cls(myConsole::ForeWhite | myConsole::BackDarkBlue);
Show_Tips(Tips1);
bool refresh(true);
bool finish(false);
Console.SetCursorVisible(false);
vector<Student_Info>::iterator first(Students.begin());
Pointer.Row = 0;
Pointer.current = first;
Set_Pointer(Pointer, true);
while (!finish)
{
if (refresh)
{
Show_Data(first);
refresh = false;
}
if (_kbhit())
{
WCHAR key(Console.ReadKey());
switch (key)
{
case myConsole::K_DOWN:
if (Pointer.current != Students.end() - 1)
{
Set_Pointer(Pointer, false);
if (Pointer.Row < PageRecords)
{
++Pointer.Row;
}
else
{
++first;
refresh = true;
}
++Pointer.current;
Set_Pointer(Pointer, true);
}
break;
case myConsole::K_UP:
if (Pointer.current != Students.begin())
{
Set_Pointer(Pointer, false);
if (Pointer.Row > 0)
{
--Pointer.Row;
}
else
{
--first;
refresh = true;
}
--Pointer.current;
Set_Pointer(Pointer, true);
}
break;
case myConsole::K_HOME:
Set_Pointer(Pointer, false);
Pointer.current = Students.begin();
Pointer.Row = 0;
Set_Pointer(Pointer, true);
first = Students.begin();
refresh = true;
break;
case myConsole::K_END:
Set_Pointer(Pointer, false);
Pointer.current = Students.end() - 1;
if (Pointer.current - Students.begin() < PageRecords)
{
Pointer.Row = Pointer.current - Students.begin();
}
else
{
Pointer.Row = PageRecords;
}
Set_Pointer(Pointer, true);
first = Pointer.current - Pointer.Row;
refresh = true;
break;
case myConsole::K_INS:
Set_Pointer(Pointer, false);
Append_Data();
Pointer.current = Students.end() - 1;
if (Pointer.current - Students.begin() < PageRecords)
{
Pointer.Row = Pointer.current - Students.begin();
}
else
{
Pointer.Row = PageRecords;
}
first = Pointer.current - Pointer.Row;
Set_Pointer(Pointer, true);
refresh = true;
break;
case myConsole::K_DEL:
if (Pointer.current != Students.begin())
{
Set_Pointer(Pointer, false);
Pointer.current = Students.erase(Pointer.current);
if (Pointer.current == Students.end())
{
Pointer.current = Students.end() - 1;
--Pointer.Row;
}
Set_Pointer(Pointer, true);
refresh = true;
}
else
{
Show_Tips(L"不能删除第一条记录! 按<Enter>键返回");
while (Console.ReadKey() != myConsole::K_ENTER)
{
;
}
Show_Tips(Tips1);
}
break;
case myConsole::K_ENTER:
Edit_Data(Pointer.current, Pointer.Row);
refresh = true;
break;
case myConsole::K_F2:
if (Save_Data(FileName.c_str()))
{
Show_Tips(L"数据已存盘! 按<Enter>键返回");
while (Console.ReadKey() != myConsole::K_ENTER)
{
;
}
Show_Tips(Tips1);
}
break;
case myConsole::K_F3:
Set_Pointer(Pointer, false);
refresh = Load_Data(FileName.c_str());
if (refresh)
{
Pointer.current = Students.begin();
Pointer.Row = 0;
first = Pointer.current;
}
Set_Pointer(Pointer, true);
break;
case myConsole::K_F4:
Set_Pointer(Pointer, false);
stable_sort(Students.begin(), Students.end(), IsGreater);
Pointer.current = Students.begin();
Pointer.Row = 0;
first = Pointer.current;
Set_Pointer(Pointer, true);
refresh = true;
break;
case myConsole::K_ESC:
finish = true;
break;
}
}
}
Console.SetCursorVisible(true);
Console.SetTextAttribute(myConsole::ForeWhite | myConsole::BackBlack).Cls();
return EXIT_SUCCESS;
}
void Show_Tips(const wstring tips)
{
WORD attr(Console.GetTextAttribute());
Console.SetTextAttribute(myConsole::ForeYellow | myConsole::BackRed);
Console.Clear(TipsRect);
Console.MoveCursor(TipsRect.Left, TipsRect.Top).WriteText(tips);
Console.SetTextAttribute(attr);
}
void Set_Pointer(Pointer_Info& pointer, bool on)
{
Console.MoveCursor(DataRect.Left - 3, DataRect.Top + 2 + pointer.Row).WriteText(on ? L"→" : L" ");
}
void Show_Data(const vector<Student_Info>::iterator first)
{
const WORD attr(Console.GetTextAttribute());
int row, col;
Console.Clear(DataRect);
// 输出标题
Console.SetTextAttribute(myConsole::ForeGreen | myConsole::BackDarkBlue);
row = DataRect.Top;
col = DataRect.Left;
for (int i = 0; i < _countof(Columns); ++i)
{
Console.MoveCursor(col, row).WriteText(Columns[i].Caption);
wstring s(Columns[i].Width, Columns[i].Separate);
Console.MoveCursor(col, row + 1).WriteText(s);
col += Columns[i].Width + 2;
}
++row;
// 输出数据
Console.SetTextAttribute(attr);
vector<Student_Info>::difference_type count(0);
for (vector<Student_Info>::iterator it = first; (it != Students.end()) && (count++ <= PageRecords); ++it)
{
col = DataRect.Left;
++row;
for (int i = 0; i < _countof(Columns); ++i)
{
WCHAR buffer[20], format[10];
switch (i)
{
case 0:
swprintf_s(format, L"%%0%dd", Columns[i].Width);
swprintf_s(buffer, format, it->ID);
break;
case 1:
wcscpy_s(buffer, it->Name);
break;
default:
swprintf_s(format, L"%%%d.2f", Columns[i].Width);
swprintf_s(buffer, format, it->Scores[i-2]);
break;
}
Console.MoveCursor(col, row).WriteText(buffer);
col += Columns[i].Width + 2;
}
}
}
void Append_Data(void)
{
Student_Info student;
student.ID = Students.size() + 1;
student.Name[0] = L'\0';
for (int i = 0; i < _countof(student.Scores); ++i)
{
student.Scores[i] = 0.0;
}
Students.push_back(student);
}
void Edit_Data(const vector<Student_Info>::iterator current, int row)
{
const WORD attr(Console.GetTextAttribute());
const BOOL cursor(Console.GetCursorVisible());
Console.SetTextAttribute(myConsole::ForeRed | myConsole::BackGreen);
Console.SetCursorVisible(true);
int x(DataRect.Left);
int y(DataRect.Top + 2 + row);
for (int i = 0; i < _countof(Columns); ++i)
{
Console.MoveCursor(x, y);
WCHAR buffer[20];
switch (i)
{
case 0:
swprintf_s(buffer, L"%d", current->ID);
Console.ReadString(buffer, Columns[i].Width);
swscanf_s(buffer, L"%d", &(current->ID));
break;
case 1:
Console.ReadString(current->Name, Columns[i].Width);
break;
default:
swprintf_s(buffer, L"%.2f", current->Scores[i-2]);
Console.ReadString(buffer, Columns[i].Width);
swscanf_s(buffer, L"%lf", &(current->Scores[i-2]));
break;
}
x += Columns[i].Width + 2;
}
Console.SetCursorVisible(cursor);
Console.SetTextAttribute(attr);
}
bool Save_Data(const wchar_t file_name[])
{
FILE* file;
errno_t error = _wfopen_s(&file, file_name, L"wb");
if ( error == 0)
{
for (vector<Student_Info>::iterator it = Students.begin(); it != Students.end(); ++it)
{
fwrite(&(*it), sizeof(Student_Info), 1, file);
}
fclose(file);
}
return error == 0;
}
bool Load_Data(const wchar_t file_name[])
{
FILE* file;
errno_t error = _wfopen_s(&file, file_name, L"rb");
if (error == 0)
{
Students.clear();
Student_Info student;
while (!feof(file) && (fread(&student, sizeof(student), 1, file) == 1))
{
Students.push_back(student);
}
fclose(file);
}
return error == 0;
}
bool IsGreater(const Student_Info& lhs, const Student_Info& rhs)
{
double sum1(0.0);
double sum2(0.0);
for (int i = 0; i < _countof(Columns) - 2; ++i)
{
sum1 += lhs.Scores[i];
sum2 += rhs.Scores[i];
}
return sum1 > sum2;
}