标题:学生成绩处理的一个界面
只看楼主
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
结帖率:100%
 问题点数:0 回复次数:10 
学生成绩处理的一个界面
开始时的画面:


增删数据后并进入编辑状态的画面:


按总分排序后的画面:


可执行程序及相关数据文件的压缩包:
test.zip (12.94 KB)


[ 本帖最后由 TonyDeng 于 2012-4-1 22:32 编辑 ]
搜索更多相关主题的帖子: 数据 编辑 压缩包 
2012-04-01 22:28
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
程序源代码(非完整及完善版本,只作参考,不供实现):

程序代码:
#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;
}

授人以渔,不授人以鱼。
2012-04-01 22:36
fenghelong
Rank: 3Rank: 3
来 自:上海
等 级:论坛游侠
威 望:2
帖 子:209
专家分:197
注 册:2011-8-18
得分:0 
回复 2楼 TonyDeng
头文件咋不给人家嘞。
2012-04-01 22:47
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
以下是引用fenghelong在2012-4-1 22:47:21的发言:

头文件咋不给人家嘞。

就是那个故意不给呀。反正有可执行程序,对照着看不难理解,功能代码都贴出来了。
那个头应该是要每个人自己实现的东西,看函数名和用法都能猜到那是干什么的,自己可以做一套。

授人以渔,不授人以鱼。
2012-04-01 22:53
chinaflag
Rank: 2
来 自:福建泉州
等 级:论坛游民
帖 子:46
专家分:83
注 册:2012-4-1
得分:0 
回复 2楼 TonyDeng
我是个新手  这个console不是C#里面的吗? 为什么C语言也有这个东西?
2012-04-02 09:03
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
得分:0 
回复 4楼 TonyDeng
怎么没有查找功能啊

                                         
===========深入<----------------->浅出============
2012-04-02 10:15
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
学习了。

梅尚程荀
马谭杨奚







                                                       
2012-04-02 12:33
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
以下是引用laoyang103在2012-4-2 10:15:54的发言:

怎么没有查找功能啊

没写而已,只是个示范,数组(vector只是一个结构体数组)查找很多人都会,这里只举了排序和增删的方法。查找、在中间插入数据,等不难做,实现了这样的界面,想加什么都没有问题,比如排序可以询问按什么排之类。那些是搞系统设计的人自己按需要做了,我只是出个模板,说可以做到这样的功能而已。

授人以渔,不授人以鱼。
2012-04-02 13:46
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
以下是引用chinaflag在2012-4-2 09:03:49的发言:

我是个新手  这个console不是C#里面的吗? 为什么C语言也有这个东西?

Console是CLR库中的类,在VS中C/C++也有,要用C++/CLR模式写,而我这个是传统的C++模式(准确地说,除了使用了用C++封装过的自编类和STL标准库之外,程序主体其实是C模式,很多应该分隔封装的功能都没做),没有使用CLR库,这里的Console是我自己写的类,只是对控制台的输出API进行了封装,用来取代TC/BC的conio头库,比如gotoxy()、cls()之类的功能,就用这个实现。

[ 本帖最后由 TonyDeng 于 2012-4-2 14:07 编辑 ]

授人以渔,不授人以鱼。
2012-04-02 13:49
hellovfp
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:禁止访问
威 望:30
帖 子:2976
专家分:7697
注 册:2009-7-21
得分:0 
C++编程?学习了。

我们都在路上。。。。。
2012-04-02 14:02



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-365022-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.035844 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved