⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 student.cpp

📁 这个个系统是学生管理系统。利用SDK做界面
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// 增加一个节点到链表
// LPSTUDENT_INFO lpNode:新增加的节点
void AddToLink(LPSTUDENT_INFO lpNode)
{
    if(!lpNode)     return;

    LPSTUDENT_INFO  lpEnd;

    if(!g_lpStudentHeader)  // 原链表本来就为空
    {
        g_lpStudentHeader = lpNode;
        g_lpStudentHeader->m_lpNext = NULL;
        return;
    }

    lpEnd = g_lpStudentHeader;
    while(lpEnd->m_lpNext)  // 将lpEnd移动到最后一个节点
    {
        lpEnd = lpEnd->m_lpNext;
    }
    lpEnd->m_lpNext  = lpNode;
    lpNode->m_lpNext = NULL;

    return;
}

// 从链表中删除一个节点
// LPSTUDENT_INFO lpNode:需要删除的节点
void DeleteFromLink(LPSTUDENT_INFO lpNode)
{
    LPSTUDENT_INFO  lpPrev = NULL;

    if(!lpNode)             return;
    if(!g_lpStudentHeader)  return;

    if(lpNode == g_lpStudentHeader) // 要删除的本来就是头节点
    {
        g_lpStudentHeader = g_lpStudentHeader->m_lpNext;
        free(lpNode);
        return;
    }

    // 删除的不是头节点,则需要查找节点
    lpPrev = g_lpStudentHeader;
    while(lpPrev->m_lpNext != NULL)
    {
        if(lpPrev->m_lpNext == lpNode)
            break;
        lpPrev = lpPrev->m_lpNext;
    }

    if(!lpPrev->m_lpNext)   return;

    lpPrev->m_lpNext = lpNode->m_lpNext;
    free(lpNode);
}

// 查找节点
// TCHAR *szKey:查找的依据
// BOOL bFlag:如果为TRUE,则按照学号查找,否则按照姓名查找
// 返回值:如果正确找到,则返回该节点地址
LPSTUDENT_INFO SearchLink(TCHAR *szKey, BOOL bFlag)
{
    LPSTUDENT_INFO  lpTmp = NULL;
    int             nRet = 0;

    if(!g_lpStudentHeader) return NULL;

    lpTmp = g_lpStudentHeader;
    while(lpTmp != NULL)
    {
        if(bFlag)   nRet = strcmp(szKey, lpTmp->m_szNumber);
        else        nRet = strcmp(szKey, lpTmp->m_szName);
        
        if(!nRet)   break;  // 已经找到
        lpTmp = lpTmp->m_lpNext;
    }
    return lpTmp;
}

// 清空链表
void ClearLink(void)
{
    LPSTUDENT_INFO  lpTmp = NULL;

    lpTmp = g_lpStudentHeader;
    while(lpTmp != NULL)
    {
        g_lpStudentHeader = g_lpStudentHeader->m_lpNext;
        free(lpTmp);
        lpTmp = g_lpStudentHeader;
    }
    g_lpStudentHeader = NULL;
    return;
}

// 将链表保存到文件
// 如果保存失败,则返回FALSE
BOOL SaveLinkToFile(void)
{
    FILE   *fp     = NULL;
    int     nRet   = 0;
    LPSTUDENT_INFO lpTmp = NULL; 

    if(!strlen(g_szFileName))   return FALSE;
    fp = fopen(g_szFileName, "wb");
    if(!fp)     return FALSE;   // 文件打开失败,不予保存

    lpTmp = g_lpStudentHeader;
    while(lpTmp)
    {
        nRet = fwrite(lpTmp, 1, sizeof(STUDENT_INFO), fp);
        if(nRet != sizeof(STUDENT_INFO))
            return FALSE;
        lpTmp = lpTmp->m_lpNext;
    }

	return TRUE;
}

// 从文件读出链表
// 如果读取失败,则返回FALSE
BOOL ReadLinkFromFile(void)
{
    FILE   *fp = NULL;
    int     nRet = 0;
    LPSTUDENT_INFO lpTmp, lpEnd;

    ClearLink();    // 先清空原链表
    if(!strlen(g_szFileName)) return FALSE;

    fp = fopen(g_szFileName, "rb");
    if(!fp)     return FALSE; // 文件打开失败,不予读取

    while(1)
    {
        lpTmp = (LPSTUDENT_INFO)malloc(sizeof(STUDENT_INFO));
        nRet = fread(lpTmp, 1, sizeof(STUDENT_INFO), fp);
        if(nRet == 0)       break;          // 读取结束
        else if(nRet!=sizeof(STUDENT_INFO)) // 读取文件出错
            return FALSE;
        lpTmp->m_lpNext = NULL;
        if(!g_lpStudentHeader)
        {
            lpEnd = g_lpStudentHeader = lpTmp;
        }
        else
        {
            lpEnd->m_lpNext = lpTmp;
            lpEnd = lpEnd->m_lpNext;
        }
    }
    fclose(fp);
    return TRUE;
}

// 将链表以指定规则排序
// enum tagSortBy esOrderBy:指定按照哪个字段排序
// BOOL bAsc:为TRUE则升序,为FALSE则降序
void SortLinkBy(enum tagSortBy esOrderBy, BOOL bAsc)
{
    LPSTUDENT_INFO  lpTmp1 = NULL, lpTmp2 = NULL;
    BOOL    bFlag = FALSE;

    // 使用选择法排序
    for(lpTmp1=g_lpStudentHeader; lpTmp1!=NULL; lpTmp1=lpTmp1->m_lpNext)
    {
        for(lpTmp2=lpTmp1->m_lpNext; lpTmp2!=NULL; lpTmp2=lpTmp2->m_lpNext)
        {
            bFlag = FALSE;
            switch(esOrderBy)   // 看是以哪一种方式排序,从而决定比较哪两个字段
            {
                case NUMBER:    // 按学号排序
                    bFlag = (strcmp(lpTmp1->m_szNumber, lpTmp2->m_szNumber) > 0);
                    break;
                case NAME:      // 按姓名排序
                    bFlag = (strcmp(lpTmp1->m_szName, lpTmp2->m_szName) > 0);
                    break;
                case SEX:       // 按性别排序
                    bFlag = (lpTmp1->m_bSex > lpTmp2->m_bSex);
                    break;
                case AGE:       // 按年龄排序
                    bFlag = (CompareAge(lpTmp1->m_dtBirthday,lpTmp2->m_dtBirthday) > 0);
                    break;
                case CLASS:     // 按班级排序
                    bFlag = (strcmp(lpTmp1->m_szClass, lpTmp2->m_szClass) > 0);
                    break;
                case TELEPHONE: // 按电话号码排序
                    bFlag = (strcmp(lpTmp1->m_szTelephone, lpTmp2->m_szTelephone) > 0);
                    break;
                case ADDRESS:   // 按家庭住址排序
                    bFlag = (strcmp(lpTmp1->m_szAddress, lpTmp2->m_szAddress) > 0);
                    break;
                default: return;
            }

            // bFlag决定是否交换,bAsc决定升序还是降序
            if((bFlag && bAsc) || (!bFlag && !bAsc))
            {
                ExChangeNode(lpTmp1, lpTmp2);   // 交换两个节点的内容
            }
        }
    }
    return;
}

// 交换两个节点
void ExChangeNode(LPSTUDENT_INFO lpNode1, LPSTUDENT_INFO lpNode2)
{
    if(lpNode1==NULL || lpNode2==NULL)  return;

    LPSTUDENT_INFO  lpNext1, lpNext2;
    STUDENT_INFO    tmp;

    // 保存两个节点的“Next”指针先
    lpNext1 = lpNode1->m_lpNext;
    lpNext2 = lpNode2->m_lpNext;

    // 将两个节点对换,使用中间变量tmp
    memcpy(&tmp, lpNode1, sizeof(STUDENT_INFO));
    memcpy(lpNode1, lpNode2, sizeof(STUDENT_INFO));
    memcpy(lpNode2, &tmp, sizeof(STUDENT_INFO));

    // 恢复两个节点的“Next”指针
    lpNode1->m_lpNext = lpNext1;
    lpNode2->m_lpNext = lpNext2;

    return;
}

/////////////////////////////////////////////////////////////////
// 链表操作函数到此结束
/////////////////////////////////////////////////////////////////

// 设置文件是否保存
void SetSaveFlag(BOOL bFlag)
{
    TCHAR  szTitle[MAX_STRING] = "\0";

    g_bIsSaved = bFlag;
	strcpy(szTitle, "思远教育中心 - ");
	if(strlen(g_szFileName))
	{
        strcat(szTitle, g_szFileName);
	}
    else
    {
        strcat(szTitle, "未命名");
    }
    if(!g_bIsSaved)
    {
        strcat(szTitle, " * ");
    }
	SetWindowText(g_hMainWnd, szTitle);

	return;
}

// 显示Windows通用文件对话框,【保存】或者【打开】
// BOOL bSave:如果为TRUE,则显示【保存】对话框,如果为FALSE,则显示【打开】对话框
// 函数如果返回,则返回值为文件完整路径
TCHAR *CommFileDlg(BOOL bSave)
{
    static TCHAR   szFilePath[MAX_STRING] = "StudentInfo1.dat\0";

    OPENFILENAME  ofn;
    // 过滤器字符串
    TCHAR   szFilter[] = "学生信息文件(*.MAP)\0*.dat\0"
                         "所有文件(*.*)\0*.*\0\0";
    TCHAR   szFileTitle[MAX_STRING] = "\0";
    TCHAR   szCurDir[MAX_STRING] = "\0";
    BOOL    bRet = FALSE;

    GetCurrentDirectory(MAX_STRING, szCurDir);     // 得到当前应用程序目录

    memset(&ofn, 0, sizeof(OPENFILENAME));
    ofn.lStructSize       = sizeof(OPENFILENAME);   // 结构体的大小
    ofn.hwndOwner         = g_hMainWnd;             // 弹出的对话框属于哪个窗口
    ofn.hInstance         = g_hAppInst;             // 当前应用程序实例
    ofn.lpstrFilter       = szFilter;               // 过滤器字符串
    ofn.lpstrCustomFilter = NULL;                   // 额外的过滤器,不需要
    ofn.nMaxCustFilter    = 0;                      // 由于不需要额外过滤器,所以直接设置为0
    ofn.nFilterIndex      = 0;                      // 默认过滤器为第几项
    ofn.lpstrFile         = szFilePath;             // 用来盛装选择的文件完整路径名
    ofn.nMaxFile          = MAX_STRING;             // 上一个字段szFilePath的最大长度
    ofn.lpstrFileTitle    = szFileTitle;            // 默认到编辑框中的文本
    ofn.nMaxFileTitle     = MAX_STRING;             // 上一个字段szFileTitle的最大长度
    ofn.lpstrInitialDir   = szCurDir;               // 初始化路径,通常就是NULL
    if(bSave)   ofn.lpstrTitle = "打开学生信息文件";
    else        ofn.lpstrTitle = "保存学生信息";    // 弹出对话框的标题栏上面的文本
    //OFN_ENABLESIZING:对话框允许使用鼠标拖大拖小
    //OFN_EXPLORER:对话框的左侧具有导航栏
    //OFN_OVERWRITEPROMPT:如果是工作是“打开文件以保存”,则提示是否覆盖原文件
    ofn.Flags             = OFN_ENABLESIZING | OFN_EXPLORER | OFN_OVERWRITEPROMPT;
    ofn.nFileOffset       = 0;      // 文件名在文件完整路径中的位置
    ofn.nFileExtension    = 0;      // 文件后缀名在文件完整路径中的位置
    ofn.lpstrDefExt       = NULL;   // 文件默认后缀名
    ofn.lCustData         = 0;      // 用户自定义数据,这里不需要
    ofn.lpTemplateName    = NULL;   // 当需要使用模板对话框的时候,可以指定一个对话框模板
    // 显示【打开/保存】对话框
    if(bSave)
        bRet = GetSaveFileName(&ofn);   // 显示【保存文件】对话框
    else
        bRet = GetOpenFileName(&ofn);   // 显示【打开文件】对话框
    if(!bRet)   return NULL;

    return szFilePath;
}

// 比较两个学生的年龄
// 返回值:如果dt1年龄比dt2大,则返回1
//         如果dt1年龄比dt2小,则返回-1
//         如果两人相同年龄,  则返回0
int CompareAge(DATE dt1, DATE dt2)
{
    if(dt1.m_nYear < dt2.m_nYear)
        return 1;
    else if(dt1.m_nYear > dt2.m_nYear)
        return -1;
    else  // 两人年份相同
    {
        if(dt1.m_nMonth < dt2.m_nMonth)
            return 1;
        else if(dt1.m_nMonth > dt2.m_nMonth)
            return -1;
        else    // 年份和月份都相同
        {
            if(dt1.m_nDay < dt2.m_nDay)
                return 1;
            else if(dt1.m_nDay > dt2.m_nDay)
                return -1;
            else return 0;  // 同年同月同日出生
        }
    }
    return 0;
}
// 【添加新学生】对话框回调函数,此函数可以用来实现【修改学生信息】
LRESULT CALLBACK NewStuDlgProc(HWND hDlgWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static  LPSTUDENT_INFO  lpOrgStu = NULL;
    switch (message)
	{
		case WM_INITDIALOG:
            HWND    hCtrlWnd;
            int     x;
            TCHAR   szText[MAX_STRING];
            
            // 设置“性别”单选框
            CheckRadioButton(hDlgWnd, IDC_RADIO_MALE, IDC_RADIO_FEMALE, IDC_RADIO_MALE);

            hCtrlWnd = GetDlgItem(hDlgWnd, IDC_EDIT_NAME);
            SendMessage(hCtrlWnd, EM_LIMITTEXT, 7, 0);     // 设置“姓名”编辑框字符个数上限

            hCtrlWnd = GetDlgItem(hDlgWnd, IDC_EDIT_NUMBER);
            SendMessage(hCtrlWnd, EM_LIMITTEXT, 7, 0);     // 设置“学号”编辑框字符个数上限

            hCtrlWnd = GetDlgItem(hDlgWnd, IDC_EDIT_TEL);
            SendMessage(hCtrlWnd, EM_LIMITTEXT, 7, 0);     // 设置“联系电话”编辑框字符个数上限

            hCtrlWnd = GetDlgItem(hDlgWnd, IDC_EDIT_ADDRESS);
            SendMessage(hCtrlWnd, EM_LIMITTEXT, 48, 0);     // 设置“家庭住址”编辑框字符个数上限

            hCtrlWnd = GetDlgItem(hDlgWnd, IDC_COMBO_YEAR); // 设置“年份”下拉框中的数据
            for(x=1900; x<2050; x++)    // 最老年份为1900年,最年轻的年份为2050年
            {
                sprintf(szText, "%04d", x);
                SendMessage(hCtrlWnd, CB_ADDSTRING, 0, (LPARAM)szText);
            }
            SendMessage(hCtrlWnd, CB_SETCURSEL, 76, 0);     // 设置当前默认值为1976年

            hCtrlWnd = GetDlgItem(hDlgWnd, IDC_COMBO_MONTH);// 设置“月份”下拉框中的数据
            for(x=1; x<=12; x++)    // 全年一共12个月份
            {
                sprintf(szText, "%02d", x);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -