Linux C/C++编程: 文件操作open/close、fopen与freopen/fclose

open是linux下的底层系统调用函数,fopen与freopen c/c++下的标准I/O库函数,带输入/输出缓冲。

linxu下的fopen是open的封装函数,fopen最终还是要调用底层的系统调用open。
所以在linux下如果需要对设备进行明确的控制,那最好使用底层系统调用(open)

  • open对应的文件操作有:close, read, write,ioctl 等。
  • fopen 对应的文件操作有:fclose, fread, fwrite, freopen, fseek, ftell, rewind等。
  • freopen用于重定向输入输出流的函数,该函数可以在不改变代码原貌的情况下改变输入输出环境,但使用时应当保证流是可靠的

open和fopen的区别:

  • fread是带缓冲的,read不带缓冲.
  • fopen是标准c里定义的,open是POSIX中定义的.
  • fread可以读一个结构.read在linux/unix中读二进制与普通文件没有区别.
  • fopen不能指定要创建文件的权限.open可以指定权限.
  • fopen返回文件指针,open返回文件描述符(整数).
  • linux/unix中任何设备都是文件,都可以用open,read.

1、open、close系统调用(linux)

理论

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 	
/*
* 返回:若成功则为新文件描述符,若出错为-1
*/
int open( const char * pathname, int oflags);			
int open(char *filename, int flags, mode_t mode); 
						

#include <unistd.h> 
/*
* 返回:若成功则为 o, 若出错则为 -1(关闭一个已关闭的描述符会出错)
*/
int close(int fd);
						

1、功能:open 函数将 filename 转换为一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中当前没有打开的最小描述符

2、参数:
pathname 是待打开/创建文件的路径名
flags 参数指明了进程打算如何访问这个文件:

• O_RDONLY: 只读
• O_WRONLY: 只写。
• O_RDWR: 可读可 写。

以上三者是互斥的,即不可以同时使用。至少得使用上述三个常量中的一个

以读的方式打开一个已存在的文件:

fd = open("foo.txt", O_RDONLY, 0);

flags 参数也可以上面的一个 | 下面的零个或者多个:
• O_CREAT: 如果文件不存 ,就创建它的一个截断的 (truncated) (空)文件
• O_TRUNC: 如果文件巳经 在,就截断它
• O_APPEND: 在每次 操作前,设置文件位置到文件的结尾处

打开一个已存在文件,并在后面添加一些数据:
fd = open("foo .txt", O_ ONLYIO_APPEND, 0);

mode 参数仅当创建新文件时才使用(而且必须用),用于指定文件的访问权限。
在这里插入图片描述
作为上下文的一部分,每个进程都会有一个umask、它是通过调用unmask函数来设置的。

当进程通过带某个 mode 参数的 open 函数调用来创建一个新文件时,文件的访问权
限位被设置为 mode & ~ umask

2、返回值:

成功则返回文件描述符,否则返回 -1。 返回文件描述符(整型变量0~255)。由open 返回的文件描述符一定是该进程尚未使用的最小描述符。只要有一个权限被禁止则返回-1。

错误代码:

  • EEXIST 参数pathname 所指的文件已存在,却使用了O_CREAT和O_EXCL旗标。

  • EACCESS 参数pathname所指的文件不符合所要求测试的权限。

  • EROFS 欲测试写入权限的文件存在于只读文件系统内。

  • EFAULT 参数pathname指针超出可存取内存空间。

  • EINVAL 参数mode 不正确。

  • ENAMETOOLONG 参数pathname太长。

  • ENOTDIR 参数pathname不是目录。

  • ENOMEM 核心内存不足。

  • ELOOP 参数pathname有过多符号连接问题。

  • EIO I/O 存取错误。

实践

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main ()
{
    int fd1, fd2;

    fd1 = open("a.txt", O_RDONLY, 0);
    printf("fd1 = %d\n", fd1);
    close(fd1);
    fd2 = open("b.txt", O_RDONLY, 0);
    printf("fd2 = %d\n", fd2);
    close(fd2);
    return(0);
}

现象: 如果文件不存在,返回-1。
如果文件存在,返回3
在这里插入图片描述

分析: Linux shell创建的每个进程开始时都有三个打开的文件:标准输入(描述符为 0) 、标准输出(描述符为 1) 和标准错误(描述符为 2), open返回的描述符总是在进程中当前没有打开的最小描述符。

fopen、freopen、fclose库函数

理论

#include<stdio.h>
/*
* 作用: 使用给定的模式 mode 打开 filename 所指向的文件
* 参数:
* 	filename -- 这是 C 字符串,包含了要打开的文件名称。
*   mode -- 这是 C 字符串,包含了文件访问模式
* 返回值: 该函数返回一个 FILE 指针。否则返回 NULL,且设置全局变量 errno 来标识错误。
*/
FILE *fopen(const char *filename, const char *mode)

/*
* 作用:把一个新的文件名 filename 与给定的打开的流 stream 关联,同时关闭流中的旧文件。
* 参数:
* 	filename -- 这是 C 字符串,包含了要打开的文件名称。
*   mode -- 这是 C 字符串,包含了文件访问模式
*   stream -- 这是指向 FILE 对象的指针(文件指针),该 FILE 对象标识了要被重新打开的流。通常使用标准流文件(stdin/stdout/stderr)
* 返回值: 如果成功则返回该指向该stream的指针,否则为NULL。
*/
FILE *freopen(const char *filename, const char *mode, FILE *stream)

/*
* 作用:  关闭流 stream。刷新所有的缓冲区。
* 参数:  stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了要被关闭的流。
* 返回值: 如果流成功关闭,则该方法返回零。如果失败,则返回 EOF
*/
int fclose(FILE *stream)

mode取值
在这里插入图片描述

  • “r"或"rb” 以只读方式打开文件,该文件必须存在。
  • “w"或"wb” 以写方式打开文件,并把文件长度截短为零。
  • “a"或"ab” 以写方式打开文件,新内容追加在文件尾。
  • "r+"或"rb+“或"r+b” 以更新方式打开(读和写)
  • "w+"或"wb+“或"w+b” 以更新方式打开,并把文件长度截短为零。
  • "a+"或"ab+“或"a+b” 以更新方式打开,新内容追加在文件尾。

字母b表示文件时一个二进制文件而不是文本文件。(linux下不区分二进制文件和文本文件)

实践

freopen使用

#include <stdio.h>
#include <string.h>

int main ()
{
    FILE *fp;

    printf("该文本重定向到 stdout \n");

    fp = freopen("file.txt", "w+", stdout); // 关联标准输出 STDOUT 到文件 file.txt

    printf("该文本重定向到 file.txt dddddddddddddd\n");
    fclose(fp);
    return(0);
}

在这里插入图片描述

fclose封装

void Fclose(FILE *fp)
{
    if (fclose(fp) != 0){
        printf("fclose error");
        exit(0);
    }
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
餐饮管理系统 一、需求分析 随着社会服务行业的发展,餐饮业对自身服务的质量和能力也有了更高的要求。餐饮管理系统正是在这样的情况之下越来越受到重视。餐厅的内部服务项目众多,既需要完成前台的服务工作,还需要完成后台的管理工作,如果没有一套可靠的餐饮管理系统,单凭手工操作,不仅效率低,而且会极大地影响到酒店的服务质量。 设计的目标:实现餐饮管理的科学化、自动化,提高各个模版的办公效率,为高质量的餐饮服务提供保证。 系统功能概述 民以食为天,随着人民生活水平的提高,餐饮业在服务行业中占有越来越重要的地位。经过多年发展,餐饮管理已经逐渐由定性管理,进入到重视定量管理的科学阶段。众所周知,在定量管理的具体实现方法和手段方面,最有效的工具就是计算机管理。 传统的手工操作管理存在着许多无法避免的问题,例如: 人工计算机账单金额出现差错; 收银工作中跑单、漏单、偷钱现象普遍; 个别服务员作弊、改单、宰客情形时有发生; 客人消费单据难以保存和查询。 如果借助计算机来管理,就可以轻松的解决处理这些问题。一个餐饮管理信息系统应该包括基本的餐厅的服务管理、管理人员信息的维护等,以及与之相应的操作。所以整个餐饮管理信息系统分为两个大部分,即后台的数据管理维护和前台的操作。后台数据库的管理能保证系统各项功能正常运行,前台操作能提供给客户尽可能方便快捷的服务。 功能模块划分 1. 前台操作系统 订餐管理模块:点菜(输入桌台代码和食物代码)、加菜、下单。 结账管理模块:结账(输入桌台代码)、结账方式选择(包括现金结账、信用卡结账、支票结账、签单等)。 交班管理模块:统计当班数据(包括桌台数、人民币结账金额以及总金额等),为下班操作作准备。 2. 后台管理维护系统 用户权限设置:可以查询员工的基本资料(姓名、性别、年龄、出生年月、籍贯、家庭住址等),员工登录名称、密码、员工操作权限等,可以根据需要进行设置。 菜谱设置:新菜单录入(包括菜式名称、代码、类型、价格、成本等)、菜式修改、删除等菜式维护。 付款方式设置:分为人民币付款、信用卡、支票签单等,可以根据需要进行添加和删除。 系统流程分析 系统流程图1所示。当用户进入系统主界面以后,新用户经过注册后才能凭借其用户名和密码登录,老用户可以直接登录。用户登录以后,系统自动判断出其操作权限。操作权限包括普通员工和管理人员。新用户的操作权限默认为是普通员工。普通员工只能进行订餐、结账操作,而管理人员除此之外还可以进行系统设置与营业分析。 • 图1 当有顾客订餐的时候,员工输入桌台号和食物代码即可进行点菜,在结账以前,加菜是允许的。当顾客结账的时候,员工输入桌台号,选择顾客的付款方式,即可完成结账。 在下班时间,员工可以统计当班期间的消费情况。这样,员工注销此次登录,退出系统,一天的工作就到此结束。 管理人员可以随时进行系统设置,包括菜谱设置、用户权限设置、付款方式设置等。 功能模块调用 餐饮管理系统调用了以下功能模块: 用户注册模块、用户登录模块、数据显示模块。 二、概念设计 图2 给出了餐饮管理系统的E-R实体关系图。收银员、餐桌、菜单三者之间的关系是订餐,其中订餐关系包括的属性有:餐桌编号、菜肴编号、菜肴名称、菜肴单价、菜肴数量、菜肴价格、菜肴折扣、是否结账、结账时间。 三、逻辑设计 将E-R关系模型转化为二维表。本系统主要需要6个表,分别为用户信息表(UserInfo)、菜谱信息表(MenuInfo)、订餐信息表(OrderInfo)、桌台信息表(DeskInfo)、付款方式表(PayModeInfo)、当班统计表(CaldayInfo),各个表中字段的类型以及说明如表1-表6所示。 表1 用户信息表 表2 菜谱信息表 表3 订餐信息表 表4 桌台信息表 表5 付款方式表 表6 当班统计表 其中,用户信息表主要存储用户的基本信息,权限项决定了用户的操作权限。菜谱信息表存储食物的基本信息。价格项为结账与结算提供依据。桌台信息表存储各个桌台的消费情况,如消费金额、是否结账等。订餐信息表存储各个桌台的点菜情况。付款方式表存储了基本的付款方式,供结账时选择。当班统计表存储员工当班期间的营业情况。 四、数据库设计 数据库管理系统采用Microsoft SQL Server 2000作为后台数据库。首先,在企业管理器中建立一个名为MenuManageSys的数据库,然后建立以上6个数据库表,并设定主键、长度。这样,数据库的设计已经完成。 五、详细设计 本餐饮管理系统采用Visual C++ + SQL Server来开发。利用ADO技术调用后台数据库,使用了两个ADO智能指针_ConnectionPtr和_RecordsetPtr,其中_ConnectionPtr用来连接后台SQL Server数据库,_RecordsetPtr指针用来对数据库的表中的记录集进行操作。工程使用的是基于对话框的程序,每个对话框为一个类,父类为CDialog,实现的一些功能都封装在类的函数中,体现了面向对象编程语言C++的特性。 导入ADO接口:在工程的stdafx.h文件里直接引入符号#import引入ADO库文件,加入下面一行代码,以使编译器能正确编译: #import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename ("EOF","adoEOF") 用_ConnectionPtr指针连接数据库:在CmenuManageSysApp类的BOOL InitInstance()函数中加入以下代码: m_pConnection.CreateInstance("ADODB.Connection"); try { m_pConnection->ConnectionTimeout = 8; m_pConnection->PutCursorLocation(adUseClient); m_pConnection->Open("driver={SQL Server};Server=172.29.130.47; DATABASE=MenuManageSys;UID=;PWD=","","",adModeUnknown); } catch(_com_error e) { AfxMessageBox("数据库连接失败!"); return FALSE; } 1.设计工程框架 餐饮管理系统的框架是一个对话框类型的操作界面,用户注册、登录后,可对餐饮管理的各个功能模块进行操作。 1.1设置主界面 系统主界面如图3: 图3 每个事件的对应代码如下: (1) 单击“注册”菜单,弹出“注册”对话框,代码如下: void CMenuManageSysDlg::OnRegister() { CRegisterDlg dlg(this); dlg.DoModal(); } (2) 单击“登录”菜单,弹出“登录”对话框,代码如下: void CMenuManageSysDlg::OnLogin() { CLoginDlg dlg(this); dlg.DoModal(); } (3) 单击“订餐”菜单,判断用户是否登录,代码如下: void CMenuManageSysDlg::OnUpdateOrderSystem(CCmdUI* pCmdUI) { if(theApp.m_Level==0||theApp.m_Level==1) { pCmdUI->Enable(true); } else { pCmdUI->Enable(false); AfxMessageBox("请您先登录"); } } (4) 如果用户已经登录,弹出“餐桌信息”对话框,否则提示用户登录,代码如下: void CMenuManageSysDlg::OnOrderSystem() { CDeskDlg dlg; dlg.DoModal(); } (5) 单击“结账”菜单,判断用户是否登录,代码如下: void CMenuManageSysDlg::OnUpdatePayCheck(CCmdUI* pCmdUI) { if(theApp.m_Level==0||theApp.m_Level==1) { pCmdUI->Enable(true); } else { pCmdUI->Enable(false); AfxMessageBox("请您先登录"); } } (6) 如果用户已经登录,弹出“结账”对话框,否则提示用户先登录,代码如下: void CMenuManageSysDlg::OnPayCheck() { CPayDlg dlg; dlg.DoModal(); } (7) 单击“下班”菜单,判断用户是否登录,代码如下: void CMenuManageSysDlg::OnUpdateChangeDuty(CCmdUI* pCmdUI) { if(theApp.m_Level==0||theApp.m_Level==1) { pCmdUI->Enable(true); } else { pCmdUI->Enable(false); AfxMessageBox("请您先登录"); } } (8) 如果用户已经登录,弹出“交接班”对话框,否则提示用户先登录,代码如下: void CMenuManageSysDlg::OnChangeDuty() { COffdutyDlg dlg; dlg.DoModal(); } (9) 单击“用户权限设置”菜单,判断用户是否登录及其权限,代码如下: void CMenuManageSysDlg::OnUpdateSetLevel(CCmdUI* pCmdUI) { if(theApp.m_Level==1) { pCmdUI->Enable(true); } else if(theApp.m_Level==0) { pCmdUI->Enable(false); AfxMessageBox("您无权进行用户级别设置"); } else { pCmdUI->Enable(false); AfxMessageBox("请您先登录"); } } (10) 如果权限是管理人员,弹出“权限设置”对话框,如果是普通员工会提示无权进行用户级别设置,代码如下: void CMenuManageSysDlg::OnSetLevel() { CLevelDlg dlg; dlg.DoModal(); } (11) 单击“菜谱设置”菜单,判断用户是否登录及其权限,代码如下: void CMenuManageSysDlg::OnUpdateSetMenu(CCmdUI* pCmdUI) { if(theApp.m_Level==1) { pCmdUI->Enable(true); } else if(theApp.m_Level==0) { pCmdUI->Enable(false); AfxMessageBox("您无权进行菜谱设置"); } else { pCmdUI->Enable(false); AfxMessageBox("请您先登录"); } } (12)如果权限是管理人员,弹出“菜谱设置”对话框,如果是普通员工会提示无权进行用户级别设置,代码如下: void CMenuManageSysDlg::OnSetMenu() { CMenuSetDlg dlg; dlg.DoModal(); } (13)单击“付款方式设置”菜单,判断用户是否登录及其权限,代码如下: void CMenuManageSysDlg::OnUpdatePaymodeSet(CCmdUI* pCmdUI) { if(theApp.m_Level==1) { pCmdUI->Enable(true); } else if(theApp.m_Level==0) { pCmdUI->Enable(false); AfxMessageBox("您无权进行付款方式设置"); } else { pCmdUI->Enable(false); AfxMessageBox("请您先登录"); } } (14)如果权限是管理人员,弹出“设置付款方式”对话框,如果是普通员工会提示无权进行用户级别设置,代码如下: void CMenuManageSysDlg::OnPaymodeSet() { CSetPaymodeDlg dlg; dlg.DoModal(); } (15)单击“注销”菜单,提示用户本次登录已注销,代码如下: void CMenuManageSysDlg::OnLogout() { if(MessageBox("您确定要注销吗","注销询问",MB_OKCANCEL|MB_ICONQUESTION)==IDOK) { theApp.m_Level=-1; AfxMessageBox("本次登录已注销"); } } (16)单击“退出系统”,在确定退出后,关闭系统,代码如下: void CMenuManageSysDlg::OnExitSystem() { if(MessageBox("真的要退出系统吗","退出询问",MB_OKCANCEL|MB_ICONQUESTION)==IDOK) { CDialog::OnOK(); } } 1.2设计注册模块 注册模块如图4: 图4 注册模块 在输入了完整的信息,按下“确定”按钮后,如果没有重复用户,则注册成功,代码如下: void CRegisterDlg::OnRegisterBtn() { // TODO: Add your control notification handler code here UpdateData(TRUE); if(!m_strUserName.IsEmpty()&&!m_strUserNative.IsEmpty() &&!m_strUserAdddress.IsEmpty() &&!m_strUserPwd.IsEmpty()&& !m_strUserPwdAgain.IsEmpty() && !m_strUserNum.IsEmpty() &&m_nUserAge != 0) { if(m_strUserPwd.CompareNoCase(m_strUserPwdAgain) != 0 ) { MessageBox("密码有误,请重新输入密码。","系统注册"); } else { try { m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open("SELECT*FROMUserInfo",_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText); } catch(_com_error e) { CString temp; temp.Format("连接数据库错误信息:%s",e.ErrorMessage()); AfxMessageBox(temp); return; } m_pRecordset->AddNew(); m_pRecordset->PutCollect("UserName",_variant_t(m_strUserName)); m_pRecordset->PutCollect("UserPwd",_variant_t(m_strUserPwd)); m_pRecordset->PutCollect("UserNative",_variant_t(m_strUserNative)); m_pRecordset->PutCollect("UserAddress",_variant_t(m_strUserAdddress)); m_pRecordset->PutCollect("UserNum",_variant_t(m_strUserNum)); CString str; if(m_nUserSex==0) { m_pRecordset->PutCollect("UserSex",_variant_t("男")); } else m_pRecordset->PutCollect("UserSex",_variant_t("女")); str.Format("%d",m_nUserAge); m_pRecordset->PutCollect("UserAge",_variant_t(str)); str.Format("%d",0); m_pRecordset->PutCollect("UserLevel",_variant_t(str)); m_pRecordset->Update(); m_pRecordset->Close(); m_pRecordset = NULL; MessageBox("恭喜您注册成功","系统注册"); CDialog::OnOK(); return; } } else { MessageBox("请输入完整注册信息","系统注册"); } } 登录模块如图5: 图5 登录模块 输入完整信息,并单击“确定”按钮后,如果用户名不存在,则重新输入;如果密码错误,则重新输入,在重新输入三次密码后还不正确,则退出登录界面,登录失败。代码如下: void CLoginDlg::OnOK() { UpdateData(TRUE); if(!m_strUserName.IsEmpty() && !m_strPassword.IsEmpty()) { try { CString sql,str; // str.Format("%d",m_nUserNum); sql = "SELECT * FROM UserInfo WHERE UserName='"+m_strUserName+"' and UserNum='"+m_strUserNum+"' and UserPwd = '"+m_strPassword+"' "; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText); if(m_pRecordset->adoEOF) { m_pRecordset->Close(); sql= "SELECT * FROM UserInfo WHERE UserName='"+m_strUserName+"' AND UserNum='"+m_strUserNum+"' "; try { m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText); if(m_pRecordset->adoEOF) { MessageBox("此用户不存在!","登录系统"); } else { if(count>=2) { MessageBox("登录次数过多,系统关闭","系统登录错误",MB_OK|MB_ICONWARNING); CDialog::OnOK(); } else { MessageBox("密码错误!","登录系统"); count++; } return; } } catch(_com_error e)///捕捉异常 { CString temp; temp.Format("连接数据库错误信息:%s",e.ErrorMessage()); AfxMessageBox(temp); return; } } else { theApp.m_Level = m_pRecordset->GetCollect("UserLevel").lVal; theApp.m_name = m_strUserName; MessageBox("登录成功!","登录系统",MB_OKCANCEL|MB_ICONQUESTION); CDialog::OnOK(); return; } } catch(_com_error e)///捕捉异常 { CString temp; temp.Format("连接数据库错误信息:%s",e.ErrorMessage()); AfxMessageBox(temp); return; } m_pRecordset->Close(); m_pRecordset = NULL; } else { MessageBox("请输入用户名和密码","登录系统"); } } 到此,注册模块与登录模块就设计完成。新用户注册以后,凭借其用户名和密码可以登陆,从而对系统进行操作。 3.功能模块设计 根据功能模块划分,可以将餐饮管理系统的功能模块划分为值班员管理模块、菜谱管理模块、用户管理模块、订餐模块、结账模块,下面对工程各个功能进行介绍。 3.1订餐模块设计 订餐模块的功能是员工输入桌台号码和食物代码进行点菜、根据需要加菜、下单。订餐模块如图6所示: 图6 订餐模块 为对话框类添加3个数据集对象: _RecordsetPtr m_pRecordset_Desk; _RecordsetPtr m_pRecordset_Order; _RecordsetPtr m_pRecordset_Menu; 对话框类的各成员函数的代码如下: CDeskDlg::CDeskDlg(CWnd* pParent /*=NULL*/) : CDialog(CDeskDlg::IDD, pParent) { //{{AFX_DATA_INIT(CDeskDlg) m_nOrderDeskNumber = 0; m_nOrderFoodNumber = 0; m_nOrderFoodRebate = 100; m_nOrderFoodAcount = 1; //}}AFX_DATA_INIT } BOOL CDeskDlg::OnInitDialog() //对话框初始化函数 { CDialog::OnInitDialog(); GetDlgItem(IDOK)->EnableWindow(FALSE); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CDeskDlg::OnOrderBtn() //点菜消息按钮 { UpdateData(TRUE); CString str; CString sql; if(m_nOrderDeskNumber == 0) { AfxMessageBox("请输入餐桌编号"); return; } if(m_nOrderFoodNumber != 0 ) { str.Format("%d",m_nOrderFoodNumber); sql = "SELECT * FROM MenuInfo WHERE FoodNum = "+str+" "; m_pRecordset_Menu.CreateInstance("ADODB.Recordset"); m_pRecordset_Menu->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset_Menu->GetRecordCount()==0) { AfxMessageBox("该菜肴编号不存在,请重新输入编号"); return; } else { int m_nTempPrice; CString m_strTempName; m_nTempPrice = m_pRecordset_Menu->GetCollect("FoodPrice").lVal;//食物价格 m_strTempName = m_pRecordset_Menu->GetCollect("FoodName").bstrVal;//食物名称 m_pRecordset_Menu->Close(); str.Format("%d",m_nOrderDeskNumber);//桌子编号 sql = "SELECT * FROM OrderInfo WHERE DeskNum = "+str+" "; m_pRecordset_Order.CreateInstance("ADODB.Recordset"); m_pRecordset_Order->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_pRecordset_Order->AddNew(); str.Format("%d",m_nOrderDeskNumber); m_pRecordset_Order->PutCollect("DeskNum" ,_variant_t(str));//餐桌编号 str.Format("%d" , m_nOrderFoodNumber); m_pRecordset_Order->PutCollect("FoodNum" ,_variant_t(str));//食物编号 str.Format("%d",m_nTempPrice); m_pRecordset_Order->PutCollect("FoodSignalPrice" ,_variant_t(str));//食物单价 str.Format("%d",m_nOrderFoodAcount); m_pRecordset_Order->PutCollect("FoodAcount" ,_variant_t(str));//食物数量 m_nTempPrice *=m_nOrderFoodAcount; str.Format("%d",m_nTempPrice); m_pRecordset_Order->PutCollect("FoodPrice" ,_variant_t(str));//食物价格 str.Format("%d",m_nOrderFoodRebate); m_pRecordset_Order->PutCollect("FoodRebate" ,_variant_t(str));//食物折扣 int m_nTempRePrice; m_nTempRePrice = (int)m_nTempPrice*m_nOrderFoodRebate/100; str.Format("%d",m_nTempRePrice); m_pRecordset_Order->PutCollect("FoodRePrice" ,_variant_t(str)); //折后价格(小计) m_pRecordset_Order->PutCollect("FoodName" ,_variant_t(m_strTempName));//食物名称 int m_nTempCheck; m_nTempCheck = 0; str.Format("%d",m_nTempCheck); m_pRecordset_Order->PutCollect("FoodCheck" ,_variant_t(str));//是否结帐 CString paytime; CTime now=CTime::GetCurrentTime(); paytime=now.Format(_T("%Y-%m-%d %H:%M:%S")); m_pRecordset_Order->PutCollect("FoodTime",_variant_t(paytime));//点菜时间 m_pRecordset_Order->Update(); m_pRecordset_Order ->Close(); str.Format("%d",m_nOrderDeskNumber); CString str1; str1.Format("%d" , 0); sql = "SELECT * FROM OrderInfo WHERE DeskNum = "+str+" and FoodCheck = "+str1+" "; m_pRecordset_Order.CreateInstance("ADODB.Recordset"); m_pRecordset_Order->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_dbFood.SetRefDataSource(NULL); m_dbFood.SetRefDataSource((LPUNKNOWN)m_pRecordset_Order); m_dbFood.SetColumnHeaders(2) ; m_dbFood.Refresh(); GetDlgItem(IDOK)->EnableWindow(TRUE); } } else { AfxMessageBox("请输入菜肴编号"); return; } } void CDeskDlg::OnOK() //下单消息按钮 { CString str,sql,str1; int m_nTempRePrice; m_nTotalPrice = 0; while(!m_pRecordset_Order->adoEOF) { m_nTempRePrice=m_pRecordset_Order->GetCollect("FoodRePrice").lVal; m_nTotalPrice += m_nTempRePrice; m_pRecordset_Order->MoveNext(); } if(m_nTotalPrice>0) { int temp=0; str1.Format("%d",temp); str.Format("%d",m_nOrderDeskNumber); sql = "SELECT * FROM DeskInfo WHERE DeskNum = "+str+" and DeskCheck = "+str1+""; m_pRecordset_Desk.CreateInstance("ADODB.Recordset"); m_pRecordset_Desk->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset_Desk->GetRecordCount()==0) { m_pRecordset_Desk->AddNew(); str.Format("%d",m_nOrderDeskNumber); m_pRecordset_Desk->PutCollect("DeskNum",(_variant_t)str); str.Format("%d",m_nTotalPrice); m_pRecordset_Desk->PutCollect("DeskPrice",(_variant_t)str); temp = 0; str.Format("%d" , temp); m_pRecordset_Desk->PutCollect("DeskCheck",(_variant_t)str); } else { str.Format("%d",m_nTotalPrice); m_pRecordset_Desk->PutCollect("DeskPrice",(_variant_t)str); } m_pRecordset_Desk->Update(); m_pRecordset_Desk->Close(); } CDialog::OnOK(); } void CDeskDlg::OnUpdateOrderDeskNumber() //根据餐桌号自动将原来已点的食物信息绑定到数据列表 { UpdateData(TRUE); CString str,sql; str.Format("%d",m_nOrderDeskNumber); CString str1; int temp=0; str1.Format("%d" , temp); sql = "SELECT * FROM OrderInfo WHERE DeskNum = "+str+" and FoodCheck = "+str1+" "; m_pRecordset_Order.CreateInstance("ADODB.Recordset"); m_pRecordset_Order->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_dbFood.SetRefDataSource(NULL); m_dbFood.SetRefDataSource((LPUNKNOWN)m_pRecordset_Order); m_dbFood.SetColumnHeaders(2) ; m_dbFood.Refresh(); } 3.2结账模块设计 结账模块的功能是员工输入桌台代码进行结账、选择结账方式(包括现金结账、信用卡结账、支票结账、签单等)、自动找零。结账模块如图7所示: 图7 结账模块 为对话框类添加3个数据集对象,代码如下: _RecordsetPtr m_pRecordset_Paymode; _RecordsetPtr m_pRecordset_Order; _RecordsetPtr m_pRecordset_Desk; 对话框类的各成员函数的代码如下: CPayDlg::CPayDlg(CWnd* pParent /*=NULL*/) : CDialog(CPayDlg::IDD, pParent) { //{{AFX_DATA_INIT(CPayDlg) m_strPaymode = _T(""); m_strPayUserName = _T(""); m_nPayDeskNumber = 0; m_nPayTotalPrice = 0; m_nPayRealPrice = 0; m_nPayRePrice = 0; m_timePay = COleDateTime::GetCurrentTime(); //}}AFX_DATA_INIT } BOOL CPayDlg::OnInitDialog() //对话框初始化函数 { CDialog::OnInitDialog(); m_strPayUserName=theApp.m_name; CString sql; sql="SELECT * FROM PayModeInfo"; m_pRecordset_Paymode.CreateInstance("ADODB.Recordset"); m_pRecordset_Paymode->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset_Paymode->GetRecordCount()!=0) { while(!m_pRecordset_Paymode->adoEOF) { m_coPaymode.AddString((LPCTSTR)(_bstr_t)m_pRecordset_Paymode->GetCollect("NAME")); m_pRecordset_Paymode->MoveNext(); } m_pRecordset_Paymode->Close(); m_coPaymode.SetCurSel(0); } UpdateData(FALSE); return TRUE; } void CPayDlg::OnUpdatePayDeskNumber() //自动将对应桌号的点菜信息以及消费情况显示在桌面上 { UpdateData(TRUE); CString sql,str,str1; int temp=0; str.Format("%d",m_nPayDeskNumber); str1.Format("%d",temp); sql="SELECT * FROM DeskInfo WHERE DeskNum="+str+" AND DeskCheck="+str1+" "; m_pRecordset_Desk.CreateInstance("ADODB.Recordset"); m_pRecordset_Desk->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset_Desk->GetRecordCount()!=0) { m_nPayTotalPrice=m_pRecordset_Desk->GetCollect("DeskPrice").lVal; } m_pRecordset_Desk->Close(); sql="SELECT * FROM OrderInfo WHERE DeskNum="+str+" AND FoodCheck="+str1+" "; m_pRecordset_Order.CreateInstance("ADODB.Recordset"); m_pRecordset_Order->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_dbPay.SetRefDataSource(NULL); m_dbPay.SetRefDataSource((LPUNKNOWN)m_pRecordset_Order); m_dbPay.SetColumnHeaders(1); m_dbPay.Refresh(); UpdateData(FALSE); } void CPayDlg::OnUpdatePayRealprice() //根据实收金额自动计算找零金额 { UpdateData(TRUE); m_nPayRePrice=m_nPayRealPrice-m_nPayTotalPrice; UpdateData(FALSE); } void CPayDlg::OnOK() //确定按钮消息函数,将数据写回DESK表和ORDER表,结账完成 { UpdateData(TRUE); if(!m_strPaymode.IsEmpty()&&m_nPayRealPrice!=0) { CString sql,str,str1; int temp=0; str.Format("%d",m_nPayDeskNumber); str1.Format("%d",temp); sql="SELECT * FROM DeskInfo WHERE DeskNum="+str+" AND DeskCheck="+str1+" "; m_pRecordset_Desk.CreateInstance("ADODB.Recordset"); m_pRecordset_Desk->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset_Desk->GetRecordCount!=0) { temp=1; str.Format("%d",temp); m_pRecordset_Desk->PutCollect("DeskCheck",(_variant_t)str); int selmode; selmode=m_coPaymode.GetCurSel(); m_coPaymode.GetLBText(selmode,m_strPaymode); m_pRecordset_Desk->PutCollect("DeskPaymode",_variant_t(m_strPaymode)); CString paytime; CTime now=CTime::GetCurrentTime(); paytime=now.Format(_T("%Y-%m-%d %H:%M:%S")); m_pRecordset_Desk->PutCollect("DeskDateTime",(_variant_t)paytime); m_pRecordset_Desk->PutCollect("DeskName",(_variant_t)m_strPayUserName); } m_pRecordset_Desk->Update(); m_pRecordset_Desk->Close(); str.Format("%d",m_nPayDeskNumber); sql="SELECT * FROM OrderInfo WHERE DeskNum="+str+" AND FoodCheck="+str1+" "; m_pRecordset_Order.CreateInstance("ADODB.Recordset"); m_pRecordset_Order->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset_Order->GetRecordCount()!=0) { temp=1; str.Format("%d",temp); while(!m_pRecordset_Order->adoEOF) { m_pRecordset_Order->PutCollect("FoodCheck",(_variant_t)str); m_pRecordset_Order->Update(); m_pRecordset_Order->MoveNext(); } } m_pRecordset_Order->Close(); str.Format("%d",m_nPayDeskNumber); str+="号桌已结账"; AfxMessageBox(str); CDialog::OnOK(); } else { AfxMessageBox("请输入完整信息"); } } 到此,结账模块已经设计完成。 3.3交接班模块设计 交接班模块的功能是管理员统计当班数据(包括桌台数、人民币结账金额以及总金额等),为下班操作做准备。交接班模块如图8所示: 图8 交接班模块 为对话框类添加两个数据集对象,代码如下: _RecordsetPtr m_pRecordset_Off; _RecordsetPtr m_pRecordset_Desk; 对话框类的各成员函数的代码如下: COffdutyDlg::COffdutyDlg(CWnd* pParent /*=NULL*/) : CDialog(COffdutyDlg::IDD, pParent) { //{{AFX_DATA_INIT(COffdutyDlg) m_strDayName = _T(""); m_nTotalAcount = 0; m_timeDay = 0; //}}AFX_DATA_INIT } BOOL COffdutyDlg::OnInitDialog() //对话框初始化 { CDialog::OnInitDialog(); m_timeDay=CTime::GetCurrentTime(); m_strDayName=theApp.m_name; UpdateData(FALSE); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void COffdutyDlg::OnCalDayBtn() //统计按钮,负责当班统计 { CString sql,str; int temp=1; str.Format("%d",temp); sql="SELECT * FROM DeskInfo WHERE DeskCheck="+str+" AND DeskName='"+m_strDayName+"' "; m_pRecordset_Desk.CreateInstance("ADODB.Recordset"); m_pRecordset_Desk->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); int renminbi_jine=0,qita_jine=0,total_jine=0,acount=0; if(m_pRecordset_Desk->GetRecordCount!=0) { while(!m_pRecordset_Desk->adoEOF) { str=m_pRecordset_Desk->GetCollect("DeskPaymode").bstrVal; if(str.CompareNoCase("人民币")==0) { renminbi_jine+=m_pRecordset_Desk->GetCollect("DeskPrice").lVal; } else { qita_jine+=m_pRecordset_Desk->GetCollect("DeskPrice").lVal; } acount++; m_pRecordset_Desk->MoveNext(); } } m_pRecordset_Desk->Close(); total_jine=renminbi_jine+qita_jine; m_pRecordset_Off.CreateInstance("ADODB.Recordset"); m_pRecordset_Off->Open("SELECT * FROM CalDayInfo",_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset_Off->GetRecordCount!=0) { while(!m_pRecordset_Off->adoEOF) { m_pRecordset_Off->Delete(adAffectCurrent); m_pRecordset_Off->Update(); m_pRecordset_Off->MoveNext(); } } m_pRecordset_Off->AddNew(); m_pRecordset_Off->PutCollect("mode",_variant_t("人民币")); str.Format("%d",renminbi_jine); m_pRecordset_Off->PutCollect("money",_variant_t(str)); m_pRecordset_Off->AddNew(); m_pRecordset_Off->PutCollect("mode",_variant_t("其他")); str.Format("%d",qita_jine); m_pRecordset_Off->PutCollect("money",_variant_t(str)); m_pRecordset_Off->AddNew(); m_pRecordset_Off->PutCollect("mode",_variant_t("合计")); str.Format("%d",total_jine); m_pRecordset_Off->PutCollect("money",_variant_t(str)); m_dbTotalDay.SetRefDataSource(NULL); m_dbTotalDay.SetRefDataSource((LPUNKNOWN)m_pRecordset_Off); m_dbTotalDay.SetColumnHeaders(2); m_dbTotalDay.Refresh(); m_pRecordset_Off->Update(); m_nTotalAcount=acount; UpdateData(FALSE); } 3.4用户权限管理模块设计 用户权限模块的功能是方便管理人员查询员工的基本资料,设置员工的操作权限。用户权限设置模块的设计如图9: 图9 权限设置模块 对话框类的各成员函数的代码如下: CLevelDlg::CLevelDlg(CWnd* pParent /*=NULL*/) : CDialog(CLevelDlg::IDD, pParent) { //{{AFX_DATA_INIT(CLevelDlg) m_strUserName = _T(""); m_strUserNum = _T(""); m_strLevelSelect = _T(""); //}}AFX_DATA_INIT } BOOL CLevelDlg::OnInitDialog() { CDialog::OnInitDialog(); m_coLevelSelect.AddString("管理员"); m_coLevelSelect.AddString("用户"); GetDlgItem(IDC_LEVEL_SELECT)->EnableWindow(FALSE); GetDlgItem(IDC_CONFIRM)->EnableWindow(FALSE); UpdateData(FALSE); CString sql; sql="SELECT * FROM UserInfo "; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_dbUserInfo.SetRefDataSource(NULL); m_dbUserInfo.SetRefDataSource((LPUNKNOWN)m_pRecordset); m_dbUserInfo.SetColumnHeaders(2); m_dbUserInfo.Refresh(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CLevelDlg::OnChange() { GetDlgItem(IDC_LEVEL_SELECT)->EnableWindow(TRUE); GetDlgItem(IDC_CONFIRM)->EnableWindow(TRUE); UpdateData(TRUE); CString sql; sql="SELECT UserName,UserNum,UserLevel,UserPwd FROM UserInfo WHERE UserName='"+m_strUserName+"' AND UserNum='"+m_strUserNum+"' "; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_dbUserInfo.SetRefDataSource(NULL); m_dbUserInfo.SetRefDataSource((LPUNKNOWN)m_pRecordset); m_dbUserInfo.SetColumnHeaders(2); m_dbUserInfo.Refresh(); } void CLevelDlg::OnConfirm() { UpdateData(TRUE); if(!m_strLevelSelect.IsEmpty()) { if(m_strLevelSelect.CompareNoCase("管理员")==0) { CString str,sql; int temp=1; str.Format("%d",temp); sql="SELECT UserName,UserNum,UserLevel,UserPwd FROM UserInfo WHERE UserName='"+m_strUserName+"' AND UserNum='"+m_strUserNum+"' "; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_pRecordset->PutCollect("UserLevel",_variant_t(str)); m_pRecordset->Update(); m_dbUserInfo.SetRefDataSource(NULL); m_dbUserInfo.SetRefDataSource((LPUNKNOWN)m_pRecordset); m_dbUserInfo.SetColumnHeaders(2); m_dbUserInfo.Refresh(); AfxMessageBox("权限修改成功"); GetDlgItem(IDC_LEVEL_SELECT)->EnableWindow(FALSE); GetDlgItem(IDC_CONFIRM)->EnableWindow(FALSE); } else { CString str,sql; int temp=0; str.Format("%d",temp); sql="SELECT UserName,UserNum,UserLevel,UserPwd FROM UserInfo WHERE UserName='"+m_strUserName+"' AND UserNum='"+m_strUserNum+"' "; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_pRecordset->PutCollect("UserLevel",_variant_t(str)); m_pRecordset->Update(); m_dbUserInfo.SetRefDataSource(NULL); m_dbUserInfo.SetRefDataSource((LPUNKNOWN)m_pRecordset); m_dbUserInfo.SetColumnHeaders(2); m_dbUserInfo.Refresh(); AfxMessageBox("权限修改成功"); GetDlgItem(IDC_LEVEL_SELECT)->EnableWindow(FALSE); GetDlgItem(IDC_CONFIRM)->EnableWindow(FALSE); } } else { AfxMessageBox("请选择权限"); } } void CLevelDlg::OnShowAll() { CString sql; sql="SELECT * FROM UserInfo "; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_dbUserInfo.SetRefDataSource(NULL); m_dbUserInfo.SetRefDataSource((LPUNKNOWN)m_pRecordset); m_dbUserInfo.SetColumnHeaders(2); m_dbUserInfo.Refresh(); GetDlgItem(IDC_LEVEL_SELECT)->EnableWindow(FALSE); GetDlgItem(IDC_CONFIRM)->EnableWindow(FALSE); } 至此,权限设置模块设计完成。 3.5菜谱管理模块设计 菜谱管理模块的功能是管理人员进行新菜式的录入、菜式修改、删除等菜式维护。菜谱管理模块如图10: 图10 菜单管理模块 对话框类的各成员函数的代码如下: CMenuSetDlg::CMenuSetDlg(CWnd* pParent /*=NULL*/) : CDialog(CMenuSetDlg::IDD, pParent) { //{{AFX_DATA_INIT(CMenuSetDlg) m_nInputNum = 0; m_nCost = 0; m_strName = _T(""); m_nNum = 0; m_nPrice = 0; m_strRemark = _T(""); m_strType = _T(""); //}}AFX_DATA_INIT } BOOL CMenuSetDlg::OnInitDialog() //对话框初始化 { CDialog::OnInitDialog(); GetDlgItem(IDC_MODIFYSAVE)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_NUM)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_NAME)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_TYPE)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_PRICE)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_COST)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_REMARK)->EnableWindow(FALSE); GetDlgItem(IDC_DEL)->EnableWindow(FALSE); GetDlgItem(IDC_INQUIRY)->EnableWindow(FALSE); GetDlgItem(IDC_MODIFY)->EnableWindow(FALSE); GetDlgItem(IDC_ADDSAVE)->EnableWindow(FALSE); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CMenuSetDlg::OnUpdateEditInputNum() { UpdateData(TRUE); if(m_nInputNum!=0) { GetDlgItem(IDC_INQUIRY)->EnableWindow(TRUE); GetDlgItem(IDC_MODIFY)->EnableWindow(FALSE); GetDlgItem(IDC_DEL)->EnableWindow(FALSE); GetDlgItem(IDC_MODIFYSAVE)->EnableWindow(FALSE); } } void CMenuSetDlg::OnInquiry() //查询 { UpdateData(TRUE); CString sql,str; str.Format("%d",m_nInputNum); sql="SELECT * FROM MenuInfo WHERE FoodNum="+str+" "; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset->GetRecordCount()!=0) { m_nInputNum=0; m_nNum=m_pRecordset->GetCollect("FoodNum").lVal; m_strName=m_pRecordset->GetCollect("FoodName").bstrVal; m_strType=m_pRecordset->GetCollect("FoodType").bstrVal; m_nPrice=m_pRecordset->GetCollect("FoodPrice").lVal; m_nCost=m_pRecordset->GetCollect("FoodCost").lVal; m_strRemark=m_pRecordset->GetCollect("FoodRemark").bstrVal; GetDlgItem(IDC_EDIT_NUM)->EnableWindow(FALSE); GetDlgItem(IDC_DEL)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_NAME)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_TYPE)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_PRICE)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_COST)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_REMARK)->EnableWindow(FALSE); GetDlgItem(IDC_INQUIRY)->EnableWindow(FALSE); GetDlgItem(IDC_MODIFY)->EnableWindow(TRUE); GetDlgItem(IDC_ADDSAVE)->EnableWindow(FALSE); } else { // m_nInputNum=0; AfxMessageBox("您所查找的菜肴不存在"); GetDlgItem(IDC_DEL)->EnableWindow(FALSE); GetDlgItem(IDC_INQUIRY)->EnableWindow(FALSE); GetDlgItem(IDC_MODIFY)->EnableWindow(FALSE); GetDlgItem(IDC_ADDSAVE)->EnableWindow(FALSE); } UpdateData(FALSE); } void CMenuSetDlg::OnAddNew() //新增 { m_nCost = 0; m_strName = _T(""); m_nNum = 0; m_nPrice = 0; m_strRemark = _T(""); m_strType = _T(""); GetDlgItem(IDC_ADDSAVE)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_NUM)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_NAME)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_TYPE)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_PRICE)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_COST)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_REMARK)->EnableWindow(TRUE); GetDlgItem(IDC_MODIFYSAVE)->EnableWindow(FALSE); GetDlgItem(IDC_INQUIRY)->EnableWindow(FALSE); GetDlgItem(IDC_MODIFY)->EnableWindow(FALSE); GetDlgItem(IDC_DEL)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_INPUT_NUM)->EnableWindow(TRUE); UpdateData(FALSE); } void CMenuSetDlg::OnAddSave() //保存所增加项 { UpdateData(TRUE); if(m_nCost!=0 && m_nNum!=0 && m_nPrice!=0 && !m_strName.IsEmpty() && !m_strRemark.IsEmpty() && !m_strType.IsEmpty()) { GetDlgItem(IDC_EDIT_NUM)->EnableWindow(FALSE); GetDlgItem(IDC_ADDSAVE)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_NAME)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_TYPE)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_PRICE)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_COST)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_REMARK)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_INPUT_NUM)->EnableWindow(TRUE); CString str,sql; str.Format("%d",m_nNum); sql="SELECT * FROM MenuInfo WHERE FoodNum="+str+""; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset->GetRecordCount()!=0) { AfxMessageBox("菜肴号码已存在"); } else { m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open("SELECT * FROM MenuInfo",_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_nNum==0) { AfxMessageBox("菜肴号码不能为0"); return; } else { m_pRecordset->AddNew(); str.Format("%d",m_nNum); m_pRecordset->PutCollect("FoodNum",_variant_t(str)); m_pRecordset->PutCollect("FoodName",_variant_t(m_strName)); m_pRecordset->PutCollect("FoodType",_variant_t(m_strType)); str.Format("%d",m_nPrice); m_pRecordset->PutCollect("FoodPrice",_variant_t(str)); str.Format("%d",m_nCost); m_pRecordset->PutCollect("FoodCost",_variant_t(str)); m_pRecordset->PutCollect("FoodRemark",_variant_t(m_strRemark)); m_pRecordset->Update(); m_pRecordset->Close(); AfxMessageBox("已保存"); m_nCost = 0; m_strName = _T(""); m_nNum = 0; m_nPrice = 0; m_strRemark = _T(""); m_strType = _T(""); UpdateData(FALSE); } } } else AfxMessageBox("请输入完整信息"); } void CMenuSetDlg::OnModify() //修改 { GetDlgItem(IDC_EDIT_NUM)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_NAME)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_TYPE)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_PRICE)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_COST)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_REMARK)->EnableWindow(TRUE); GetDlgItem(IDC_MODIFYSAVE)->EnableWindow(TRUE); GetDlgItem(IDC_DEL)->EnableWindow(FALSE); m_nCost = 0; m_nPrice = 0; m_strRemark = _T(""); m_strType = _T(""); UpdateData(FALSE); } void CMenuSetDlg::OnModifysave() //保存修改 { UpdateData(TRUE); if(!m_strType.IsEmpty()&&m_nPrice!=0&&m_nCost!=0&&!m_strRemark.IsEmpty()) { CString str,sql; str.Format("%d",m_nNum); // m_pRecordset->PutCollect("FoodNum",_variant_t(str)); // m_pRecordset->PutCollect("FoodName",_variant_t(m_strName)); m_pRecordset->PutCollect("FoodType",_variant_t(m_strType)); str.Format("%d",m_nPrice); m_pRecordset->PutCollect("FoodPrice",_variant_t(str)); str.Format("%d",m_nCost); m_pRecordset->PutCollect("FoodCost",_variant_t(str)); m_pRecordset->PutCollect("FoodRemark",_variant_t(m_strRemark)); m_pRecordset->Update(); AfxMessageBox("修改成功"); GetDlgItem(IDC_MODIFY)->EnableWindow(FALSE); GetDlgItem(IDC_MODIFYSAVE)->EnableWindow(FALSE); } else { AfxMessageBox("请输入完整信息"); } } void CMenuSetDlg::OnDel() { m_pRecordset->Delete(adAffectCurrent); m_pRecordset->Close(); AfxMessageBox("删除成功"); GetDlgItem(IDC_DEL)->EnableWindow(FALSE); GetDlgItem(IDC_MODIFY)->EnableWindow(FALSE); } 至此,菜谱管理模块设计完成。 3.6付款方式设置模块设计 付款方式设置模块如图11: 图11 付款方式模块 对话框类的各成员函数的代码如下: CSetPaymodeDlg::CSetPaymodeDlg(CWnd* pParent /*=NULL*/) : CDialog(CSetPaymodeDlg::IDD, pParent) { //{{AFX_DATA_INIT(CSetPaymodeDlg) m_strPaymode = _T(""); //}}AFX_DATA_INIT } BOOL CSetPaymodeDlg::OnInitDialog() //对话框初始化 { CDialog::OnInitDialog(); m_bAdd=FALSE; m_bDel=FALSE; m_sInputPaymode.ShowWindow(SW_HIDE); m_editPaymode.ShowWindow(SW_HIDE); m_btnSure.ShowWindow(SW_HIDE); CString sql; sql="SELECT * FROM PayModeInfo"; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_dbPaymode.SetRefDataSource(NULL); m_dbPaymode.SetRefDataSource((LPUNKNOWN)m_pRecordset); m_dbPaymode.SetColumnHeaders(1); m_dbPaymode.Refresh(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CSetPaymodeDlg::OnPaymodeAddBtn() //单击按钮后,开始新增 { m_sInputPaymode.ShowWindow(SW_SHOW); m_editPaymode.ShowWindow(SW_SHOW); m_btnSure.ShowWindow(SW_SHOW); m_bAdd=TRUE; m_bDel=FALSE; } void CSetPaymodeDlg::OnPaymodeDelBtn() //单击按钮后,开始删除 { m_sInputPaymode.ShowWindow(SW_SHOW); m_editPaymode.ShowWindow(SW_SHOW); m_btnSure.ShowWindow(SW_SHOW); m_bAdd=FALSE; m_bDel=TRUE; } void CSetPaymodeDlg::OnOK() //确定添加或者删除 { UpdateData(TRUE); if(!m_strPaymode.IsEmpty()) { if(m_bAdd==TRUE) { CString str; BOOL flag=0; m_pRecordset->MoveFirst(); while(!m_pRecordset->adoEOF) { str=m_pRecordset->GetCollect("NAME").bstrVal; if(str.CompareNoCase(m_strPaymode)==0) { MessageBox("您输入的付款方式已存在","输入错误",MB_OK|MB_ICONWARNING); flag=1; break; } else m_pRecordset->MoveNext(); } /* CString sql; sql="SELECT * FROM PayModeInfo WHERE NAME='"+m_strPaymode+"' "; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset->GetRecordCount()==0) { MessageBox("您输入的付款方式已存在","输入错误",MB_OK|MB_ICONWARNING); flag=1; } */ if(flag==0) { m_pRecordset->MoveLast(); m_pRecordset->AddNew(); m_pRecordset->PutCollect("NAME",_variant_t(m_strPaymode)); m_pRecordset->Update(); m_dbPaymode.SetRefDataSource(NULL); m_dbPaymode.SetRefDataSource((LPUNKNOWN)m_pRecordset); m_dbPaymode.SetColumnHeaders(1); m_dbPaymode.Refresh(); m_bAdd=FALSE; } } if(m_bDel==TRUE) { BOOL flag=0; UpdateData(TRUE); CString str; int newid; /* m_pRecordset->MoveFirst(); while(!m_pRecordset->adoEOF) { str=m_pRecordset->GetCollect("NAME").bstrVal; if(str.CompareNoCase(m_strPaymode)==0) { flag=1; m_pRecordset->Delete(adAffectCurrent); m_pRecordset->Update(); break; } else m_pRecordset->MoveNext(); } */ CString sql; sql="SELECT * FROM PayModeInfo WHERE NAME='"+m_strPaymode+"'"; m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open((_variant_t)sql,_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); if(m_pRecordset->GetRecordCount()!=0) { flag=1; m_pRecordset->Delete(adAffectCurrent); m_pRecordset->Update(); m_pRecordset.CreateInstance("ADODB.Recordset"); m_pRecordset->Open("SELECT * FROM PayModeInfo",_variant_t((IDispatch *)theApp.m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText); m_dbPaymode.SetRefDataSource(NULL); m_dbPaymode.SetRefDataSource((LPUNKNOWN)m_pRecordset); m_dbPaymode.SetColumnHeaders(1); m_dbPaymode.Refresh(); m_bDel=FALSE; } if(flag==0) { MessageBox("您输入的付款方式不存在,请查询后确认","输入错误",MB_OK|MB_ICONWARNING); } m_dbPaymode.Refresh(); m_bDel=FALSE; } m_editPaymode.SetWindowText(""); m_sInputPaymode.ShowWindow(SW_HIDE); m_editPaymode.ShowWindow(SW_HIDE); m_btnSure.ShowWindow(SW_HIDE); } else { AfxMessageBox("请输入付款方式"); } } 至此,付款方式设置模块设计完成。 六、系统演示 系统设计并编写完成后,编译运行程序,初始界面如图12所示: 图12 1. 系统登录 单击“登录”菜单,弹出登录界面,在登陆界面输入框中分别输入用户编号、用户名和密码,如图13所示。 如果用户名和密码都正确,那么就可以登陆系统,系统提示如图14所示。 图13 图14 如果用户名不存在或密码输入不正确,系统提示如图15和图16所示,将无法进入系统。 图15 图16 如果未登录就进行其他操作,系统提示如图17所示。只有登录后才能操作其他功能。单击“注册”菜单,弹出注册对话框如图18所示。 按要求填写完注册信息,如果注册名未被注册,并且前后两次输入的密码一致,那么系统给出如图19所示提示。 如果前后两次输入密码不一致,系统给出如图20所示提示,此时注册不成功。 图19 图20 2.订餐操作 系统登录后,单击“订餐”菜单,弹出“餐桌信息”对话框,如图21所示。 餐桌第一次订餐时,输入餐桌编号、食物编号、数量以及折扣,单击“点菜”按钮,在右侧点菜信息栏中列举了该餐桌所点的菜肴,如图22所示。 图21 图22 如果餐桌已经订过餐,但是还没有结账,则在餐桌编号输入框输入餐桌号,在点菜信息栏中显示该桌已点的菜。 单击“下单”按钮,即可把点菜信息记录下来。 3.结账操作 单击“结账”菜单,弹出“结账单”对话框。输入桌台号,自动显示对应的点菜信息以及消费金额。选取付款方式和实收金额后,界面会自动显示找零金额,结果如图23所示。 图23 4.用户权限设置 单击“管理”|“用户权限设置”,弹出“权限设置”对话框,如图24所示,所有用户的信息都显示在数据列表中。 输入要查询的用户编号和名称,单击“更改”,该用户的信息就显示在列表中,结果如图25所示。 图24 图25 选择权限,单击确定后,如图26所示,用户权限已被修改。 图26 单击“显示全部”,结果如图27所示。 图27 5.菜谱管理 单击“管理”|“菜谱设置”菜单,弹出“菜谱设置”对话框,如图28所示。 图28 在“菜谱设置”对话框中可以对菜谱进行查找、添加、删除、修改等操作。 6.付款方式设置 单击“管理”|“付款方式设置”菜单,弹出“付款方式”对话框,如图29所示。 单击“新增”或“删除”按钮,显示新增付款方式文本框和“确定”按钮,如图30所示。 图29 图30 在文本框中输入要增加/删除的付款方式,并单击“确定”按钮,将新增或删除所选择的付款方式。 7.注销用户 单击“注销”菜单,弹出“注销询问”对话框如图31所示。选择“确定”,注销成功,如图32所示。 图31 图32 8.系统退出 单击“退出系统”菜单,弹出“退出询问”对话框如图33所示。选择“确定”,则系统退出。 图33 至此,系统的全部功能已经演示完毕。 七、结束语 经过两个多星期的时间,终于完成了本系统的设计。虽然本系统有一些漏洞和不完善的地方,但是本系统结合餐饮管理的实际情况,基于数据库设计通用的模块,对餐饮管理的前台和后台操作进行功能模块的设计,实现了餐饮管理的基本功能。 在设计的过程中,遇到了很多的技术上的问题。例如,第一次接触ADO数据库访问技术,对用ADO来连接数据库不是很了解,出现了很多的问题,设计受到了很大的阻碍。经过向专业指导老师请教和参阅了有关书籍后,终于把一些问题解决了。在本次设计中,我懂得了“书到用时方恨少”的道理,发现了自己在专业方面还有很多要提高的地方,在今后的学习中,我一定努力进步! 参考文献: [1] 萨师煊,王珊.数据库系统概论[M]第3版.北京:高等教育出版社,2000 [2] 侯其锋,李晓华,李莎.Visual C++数据库通用模块开发与系统移植.北京:清华大学出版社,2007 致 谢 在这次课程设计中,戴小鹏老师给了我很大的帮助。他对我的精心指导和关心,使我在设计的过程中受到了很大的启发。特别是他的那份耐心和责任心,使我在今后的学习和工作中受益匪浅。在此,特向戴小鹏老师表示衷心的感谢!
在C/C++中,对文件操作可以通过文件指针和文件流来实现。下面是文件指针和文件流的详细介绍以及如何进行文件操作的示例代码。 1. 文件指针 文件指针是一个指向文件的位置指针,可以用来定位文件中的特定位置。在C/C++中,文件指针的类型为FILE *,通过调用fopen()函数打开文件来获取文件指针,通过fclose()函数关闭文件来释放文件指针。 示例代码: ```c++ #include <stdio.h> int main() { FILE *fp; // 声明文件指针 char str[100]; fp = fopen("test.txt", "r"); // 打开文件 if (fp == NULL) { printf("文件打开失败\n"); return 1; } fgets(str, 100, fp); // 读取文件内容 printf("文件内容:%s\n", str); fclose(fp); // 关闭文件 return 0; } ``` 在上面的示例代码中,我们使用了fopen()函数打开了一个名为test.txt的文件,并将返回的文件指针赋值给了fp变量。然后使用fgets()函数读取了文件中的内容,并将其输出到控制台上。最后使用fclose()函数关闭文件并释放文件指针。 2. 文件文件流是C++中对文件进行操作的一种方式,通过定义一个文件流对象来实现对文件的读写操作。在C++中,文件流对象有三种类型:ifstream(输入文件流)、ofstream(输出文件流)和fstream(读写文件流)。通过调用open()函数打开文件来获取文件流,通过调用close()函数关闭文件来释放文件流。 示例代码: ```c++ #include <iostream> #include <fstream> #include <string> using namespace std; int main() { ifstream infile; // 声明输入文件流对象 string str; infile.open("test.txt"); // 打开文件 if (!infile.is_open()) { cout << "文件打开失败" << endl; return 1; } getline(infile, str); // 读取文件内容 cout << "文件内容:" << str << endl; infile.close(); // 关闭文件 return 0; } ``` 在上面的示例代码中,我们使用了ifstream对象作为输入文件流,并通过open()函数打开了一个名为test.txt的文件。然后使用getline()函数读取了文件中的内容,并将其输出到控制台上。最后使用close()函数关闭文件并释放文件流。 总之,文件指针和文件流都是C/C++中进行文件操作的常用方式,具体使用哪种方式取决于不同的应用场景和个人喜好。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值