C语言课程设计-学生饭卡管理系统.doc
《C语言课程设计-学生饭卡管理系统.doc》由会员分享,可在线阅读,更多相关《C语言课程设计-学生饭卡管理系统.doc(24页珍藏版)》请在咨信网上搜索。
(word完整版)C语言课程设计 学生饭卡管理系统 1.课程设计的目的 随着网络技术的发展,各种电子设备在人群中普及开来,人们的生活方式也发生了很大的变化。现金付款逐渐被方便、安全、卫生的刷卡消费所代替。例如校园餐厅的就餐卡的使用就让学生在方便的同时最大限地减少了疾病的传播。这就需要一个操作系统来管理餐卡数据。于是尝试用C语言编写了一个小的餐厅餐卡管理系统,希望对餐厅有所帮助,也可以参考使用。 本程序一共有六个选项,可以进行添加用户、查询用户、充值、消费、删除用户、退出系统等功能。能够实现学生在餐厅充值、刷卡消费、余额查询等活动。操作界面简洁,操作方法简单实用,足以帮助餐厅管理学生消费. 程序用了条件、循环、函数、结构体等知识点,综合了链表和文件的打开和保存编写的。本程序可运用于小的餐厅餐卡管理软件.本软件运用菜单实现交互式管理,用户轻松的按键既可实现对软件的操作,操作简单易懂,功能丰富,可以很好的满足餐厅工作人员的需要。 2.设计方案论证 2.1设计思路 建立一个函数,用来保存学生的学号、姓名、电话号码、班级、餐卡余额、密码等信息,完成餐厅就餐卡的功能.主函数可以调用六个子函数,分别完成添加用户、查询用户、充值、消费、删除用户、退出系统六个功能。在主函数中可以1、2、3、4、5、6数字键分别可以执行某个功能模块。 主要功能模块即如图1所示: 添加用户 查询用户 删除用户 充 值 收 费 主 菜 单 退出系统 图1. 就餐卡主要功能模块 开 始 2.2程序设计 ①main ()主函数: 读取文件 主函数十分简洁,定义了本程序 用到的各个变量及函数,然后读取文件后进 入主菜单, 显示函数各功能。 正确读取? 其运行的流程图如图2所示。 N Y 输出主菜单 结 束 图2. 就餐卡主函数运行流程图 ②select()主菜单[1],主菜单链接各个分菜单,其功能即如图1所示. addnewcard(),添加用户函数。 searchcard(),查询用户函数。 addbalance(),充值函数函数. charge(), 收费函数函数。 deletecard(),删除用户函数。 exit(0), 退出系统函数。 用户可以键入相应数字进入各个功能的操作界面.同时设置一个断点,即当返回值为“6”时运行exit(0)函数来结束程序,以免造成死循环。其运行流程图如图3所示。 开 始 输入 i N i=1? Y N Y i=2? N Y 调 用 addnewcard() i=3? N Y i=4? N 调 用 searchcard() Y i=5? Y 调 用 addbalance() 调 用 charge() 调 用 deletecard() 结 束 图3.就餐卡菜单函数流程图 ③newrecord()添加用户菜单。餐厅管理人员可以按需要根据提示来直接添加学生用户,每次添加完毕系统会询问“是否继续添加?(Y/N)"当返回值为“n"或不是系统要求输入数值时,系统自动保存数据并返回主菜单. ④searchcard()查询用户[2]。在主菜单输入“2"时自动进入查询学生信息,每次当输入卡号不存在时系统自动警告没有该用户。查询结束按任意键返回主菜单。其流程图如图4所示. ⑤addbalance()、charge(),充值/收费模块[3].这两个模块十分相似餐厅管理人员只要输入所要充值学生的学号,就可以对相应学生充值或者扣除相应金额,操作十分简单。充值或扣费结束后系统自动显示操作后该学生信息并自动保存。餐卡充值运行流程图如图5所示。收费流程图类似充值,不再重复。 ⑥deletecard()删除用户模块[5]。餐卡管理人员可以通过该模块选择删除需要注销的就餐卡。如果餐卡内余额不为零,系统则提示返还相应金额给学生. 开 始 输入学号n 开 始 输入学号n 输入学号n m=student[i].cardnumber i=0 m=student[i].cardnumber i=0 i=i+1 i=i+1 N m=n N m=n Y 输出该学生信息 Y 输入添加金额k 输出该学生信息 student[i].balance+=k 结 束 输出该学生信息 图4.查询用户流程图 结 束 图5.充值流程图 2.3.源程序 #include <stdio.h> #include 〈stdlib.h〉 #include <string.h> #include <conio。h> #include 〈math。h〉 struct record { char cardnumber[10]; char name[20]; char phone[20]; char classn[40]; char password[10]; int balance; } student[500]; int num=0; /*外部变量num为文件中的纪录数 */ FILE *fp; void select(); /* 主菜单 */ void addnewcard(); /*添加用户*/ void searchcard(); /*查询用户*/ void readfile(); /*读取文件*/ void deletecard(); /*删除用户*/ void addbalance(); /* 充值 */ void password(); /* 密码 */ void charge(); /* 收费 */ void main() /* 主函数 */ { readfile(); /*读取文件*/ while (1) { select(); /* 主菜单 */ } } void readfile() /*导入文件,打开欢迎进入界面*/ { if((fp=fopen(”student。bin","rb”))==NULL) { if ((fp=fopen(”student.bin",”wb"))==NULL) { exit(0); } else { getch(); return; } exit(0); } fseek(fp,0,2); if (ftell(fp)〉0) /*文件非空*/ { rewind(fp); for (num=0;!feof(fp) && fread(&student[num],sizeof(struct record),1,fp);num++); return; } } void select() /* 主菜单 */ { char choic; system(”cls"); printf("\n\t\t******************** 主菜单 ********************"); printf(”\n\t\t*********** 1-添加用户 2—查询用户 ************"); printf(”\n\t\t*********** 3- 充 值 4— 消 费 ************”); printf(”\n\t\t*********** 5-删除用户 6-退出系统 ************”); printf(”\n\t\t************************************************"); printf("\n\t\t请选择:"); choic=getch(); switch (choic) { case '1’:addnewcard();break; case ’2':searchcard();break; case ’3':addbalance();break; case '4':charge();break; case '5’:deletecard();break; case '6’:exit(0); default:select(); } } void addnewcard() /*添加用户*/ { printf(”\n\t\t*************** 请输入学生信息 ***************\n"); printf("\n\t\t输入学号:”); scanf("%s",&student[num].cardnumber); printf(”\n\t\t输入姓名:”); scanf("%s”,&student[num]。name); printf("\n\t\t输入电话号码:”); scanf("%s”,&student[num]。phone); printf("\n\t\t输入班级:”); scanf(”%s",&student[num].classn); printf("\n\t\t输入密码:"); scanf(”%s”,&student[num].password); printf("\n\t\t输入添加金额:"); scanf(”%d”,&student[num]。balance); num++; printf("\n\t\t是否继续添加?(Y/N):”); if (getch()=='y’) addnewcard(); return; } void searchcard() /*查询用户 */ { int mark=0; int i; int a=0; printf(”\n\t\t***************** 按学号查找 *****************\n"); char cardnumber[10]; printf("\n\t\t请输入学号:”); scanf("%s”,cardnumber); for(i=0;i<num;i++) { if (strcmp(student[i].cardnumber,cardnumber)==0) { printf("\n\t\t************** 以下是您查找的学生信息 **********"); printf("\n\t\t学号: %s",student[i].cardnumber); printf("\n\t\t姓名: %s",student[i]。name); printf(”\n\t\t电话: %s",student[i].phone); printf(”\n\t\t班级: %s”,student[i].classn); printf("\n\t\t余额: %d”,student[i].balance); printf(”\n\t\t密码: %s",student[i].password); printf(”\n\t\t************************************************"); printf("\n\t\t按任意键返回主菜单:"); mark++; getch(); return; } } if (mark==0) { printf(”\n\t\t没有改学生的信息"); printf(”\n\t\t按任意键返回主菜单”); getch(); return; } } void addbalance() /*充值*/ { int i; int m; int a=0; printf(”\n\t\t*************** 按学号添加金额 ***************\n"); char cardnumber[10]; printf("\n\t\t请输入学号:"); scanf("%s”,cardnumber); for(i=0;i〈num;i++) { if (strcmp(student[i]。cardnumber,cardnumber)==0) { printf(”\n\t\t************* 以下是您所选择学生信息 ***********"); printf(”\n\t\t学号: %s”,student[i]。cardnumber); printf(”\n\t\t姓名: %s”,student[i]。name); printf("\n\t\t电话: %s",student[i]。phone); printf("\n\t\t班级: %s”,student[i]。classn); printf(”\n\t\t余额: %d",student[i]。balance); printf("\n\t\t密码: %s”,student[i].password); printf("\n\t\t************************************************"); printf(”\n\t\t是否添加金额?(y/n)”); if (getch()=='y') { printf("\n\t\t请输入你要添加金额:”); scanf(”%d",&m); printf("\t\t确认添加%d元给%s(y/n)?",m,student[i].name); if (getch()==’y’) {student[i]。balance=student[i]。balance+m;} printf(”\n\t\t添加金额成功"); } printf("\n\t\t******** 以下是您选择学生添加金额后信息 ********”); printf(”\n\t\t学号: %s”,student[i]。cardnumber); printf(”\n\t\t姓名: %s",student[i].name); printf("\n\t\t电话: %s”,student[i]。phone); printf(”\n\t\t班级: %s",student[i]。classn); printf(”\n\t\t余额: %d”,student[i].balance); printf(”\n\t\t密码: %s",student[i].password); printf(”\n\t\t************************************************"); printf("\n\t\t按任意键返回主菜单”); getch(); return; } } } void charge() /*收费*/ { int i; int k; int a=0; printf(”\n\t\t***************** 按学号扣费 *****************\n"); char cardnumber[10]; printf(”\n\t\t请输入学号:”); scanf(”%s",cardnumber); for(i=0;i〈num;i++) { if (strcmp(student[i]。cardnumber,cardnumber)==0) { printf("\n\t\t************** 以下是您选择学生信息 ************"); printf("\n\t\t学号: %s”,student[i]。cardnumber); printf(”\n\t\t姓名: %s",student[i]。name); printf(”\n\t\t电话: %s”,student[i]。phone); printf(”\n\t\t班级: %s",student[i]。classn); printf("\n\t\t余额: %d”,student[i].balance); printf("\n\t\t密码: %s”,student[i]。password); printf(”\n\t\t************************************************”); printf(”\n\t\t是否扣除金额?(y/n)"); if (getch()=='y') { printf(”\n\t\t请输入你要扣除金额:”); scanf("%d”,&k); printf(”\t\t确认扣除%d元给%s?(y/n)”,k,student[i]。name); if (getch()=='y’) { student[i]。balance=student[i]。balance-k; } printf(”\n\t\t扣除金额成功”); } printf(”\n\t\t****** 以下是您所选择学生扣除金额后信息 ********"); printf("\n\t\t学号: %s”,student[i].cardnumber); printf("\n\t\t姓名: %s”,student[i].name); printf("\n\t\t电话: %s",student[i]。phone); printf("\n\t\t班级: %s",student[i].classn); printf("\n\t\t余额: %d”,student[i]。balance); printf(”\n\t\t密码: %s",student[i].password); printf("\n\t\t************************************************”); printf("\n\t\t按任意键返回主菜单”); getch(); return; } } } void deletecard() /*删除用户*/ { int i,j; int deletemark=0; char cardnumber[10]; printf("\n\t\t请输入要删除学生学号:”); scanf("%s”,cardnumber); if(num==0) { printf(”\n\t\t对不起,文件中无任何纪录"); printf(”\n\t\t按任意键返回主菜单”); getch(); return; } for (i=0;i<num;i++) { if (strcmp(student[i].cardnumber,cardnumber)==NULL) { printf("\n\t\t以下是您要删除的学生纪录:"); printf("\n\t\t学号: %s",student[i]。cardnumber); printf("\n\t\t姓名: %s”,student[i]。name); printf(”\n\t\t电话: %s”,student[i]。phone); printf("\n\t\t班级: %s”,student[i]。classn); printf("\n\t\t余额: %d”,student[i]。balance); printf(”\n\t\t密码: %s”,student[i]。password); printf(”\n\t\t是否删除?(y/n)"); if (getch()==’y') { printf(”\n\n\t\t!!!退还 %d 元给%s。!!!\n\n”,student[i]。balance,student[i]。name); for (j=i;j〈num-1;j++) /*纪录移动,从stud数组中删除*/ student[j]=student[j+1]; num—-; deletemark++; printf(”\n\t\t删除成功”); printf(”\n\t\t是否继续删除?(y/n)”); if (getch()==’y’) deletecard(); return; } else return; } continue; } if (deletemark==0) { printf("\n\t\t没有该同学的纪录"); printf(”\n\t\t是否继续删除?(y/n)”); if (getch()==’y’) deletecard(); return; } } void writetofile() /*保存文件*/ { int i; if ((fp=fopen(”student。bin”,"wb"))==NULL) { printf("\n\t\t文件打开失败”); } for (i=0;i<num;i++) { if (fwrite(&student[i],sizeof(struct record),1,fp)!=1) { printf("\n\t\t写入文件错误!\n”); } } fclose(fp); printf("\n\t\t餐卡系统文件已保存”); printf(”\n\t\t按任意键退出程序\n\t\t"); exit(0); } 3.设计结果与分析 ①在Microsoft Visual C++ 软件中输入源程序,在没有提示错误的情况下编译,生成相应的后缀为“jiucankaguanli.exe”的可执行文件。双击文件,可以看到如图6所示的界面。 图6.运行程序进入的主菜单界面 运行主函数时,首先调用readfile()读取文件[2],读取成功后运行select()主菜单函数,打开主菜单函数界面。函数使用switch语句实现各功能模块的转移。用getch()来获取餐厅工作人员的选择数据,分别调用相应的自定义函数.从而实现对各个函数的调用. ②在输入“1"后会提示“请输入学生信息"这时餐厅管理人员可以根据需要按照提示分别输入学生的学号、姓名、电话号码、班级、密码及充值金额。输入完毕后系统自动提示是不是继续添加学生信息。其运行效果图如图7所示。 图7.添加用户界面 这一函数实现了对字符串赋值的功能[3]。系统提示餐厅管理人员输入相应信息,然后用scanf函数获取输入数据。每次输入结束后,系统输出询问是否继续添加的信息,然后执行if语句,如果返回值是“y”,则继续执行addnewcard()函数添加用户,否则返回主菜单。 ③在主菜单界面输入数字“2”,执行searchcard()函数查询用户,系统会根据管理员输入数据查找相应学生的信息并输出。界面如图8所示。 图8.查询用户信息界面(1) 图8.查询用户信息界面(2) 这一函数提示餐厅管理人员输入卡号后,调用scanf函数获取输入信息,然后执行for语句,同餐卡库里第一个用户卡号比较[4],如果相等,则输出该学号学生的信息,如图8。查询用户信息界面(1)所示;如果不相等,则执行i++,同下一用户比较,以此循环,若找到目标用户则输出用户信息,而当没有发现相同学号学生时,则输出没有该学生的信息,即如图8.查询用户信息界面(2)所示。 ④在主菜单界面输入数字“3",执行addbalance()函数为就餐卡充值.为保险起见系统会询问两次以确认充值:“是否添加金额”、 “确认添加%d元给%s".其运行界面效果如图9所示。 图9。就餐卡充值界面 本函数首先根据管理者输入的数据来查询相应学生的信息,查到就输出征求确认,查不到则输出没有该学生的信息,界面和图8。查询用户信息界面(2)一样。征得确认后提示管理者输入添加金额,用scanf函数获得输入信息后征得再次确认。然后函数自动调用加法函数,通过 student[i].balance=student[i].balance+m 将输入的整型数值加上餐卡里原有的余额,并将添加金额后的学生信息输出. ⑤在主菜单界面输入数字“4”,执行charge()函数为就餐卡扣费以实现刷卡消费。同样为保险起见系统会询问两次以确认充值:“是否扣除金额”, “确认扣除%d元给%s”。其运行界面效果如图10所示。 图10。就餐卡充值界面 其执行方法与充值特别相似,不再重复说明。 ⑥在主菜单界面输入数字“5”,执行deletecard()函数删除用户.当管理者输入要删除学生的学号后,系统会搜索数据库并将搜索结果输出。然后征求确认。确认后系统会弹出退还餐卡里的余额给餐卡主人的提醒。每次删除成功后系统会询问是否继续删除,然后执行相应操作。其运行界面效果如图11所示。 图11。就餐卡删除用户界面 这个函数也是首先根据管理者输入的信息相应查找。在征得确认后自动移动数组中的元素,目标餐卡信息后面的纪录替代目标餐卡信息,后面的元素同样依次向前移动,原目标餐卡信息被移出餐卡数据库,从而实现移除。 ⑦在主菜单界面输入数字“8",执行exit(0),即保存操作并退出系统。 4.设计体会 通过对这个校园餐厅就餐卡管理系统的编辑和编译我有学会了很多东西,同时对C语言也有了更深的理解。 ①编辑程序前要先设计一个大体的框图,最好在稿纸上画下来,设出各个变量及所有能够用到的函数,这样才能保证编写程序有条不紊地进行,同时避免出现编写程序时因为时间长、函数多而混淆了定义的变量或函数. ②编写程序时要相信自己,不要被程序表面的复杂而吓倒.一步一步去完成各个分函数,那么整个程序便指日可待了. ③要相信自己能独立解决碰到的困难,但也要善于借助外力。争取独立解决问题,但有时候也要去图书馆等查找相关资料[5],帮助自己解决问题。有时候多问问同学,团结协作无论在什么方面都是很重要的。 ④C语言虽然在语法方面没有严格的规定,但在一些细节上要求十分严格,例如每个函数后的分号等,虽然错误不大,但少了就会造成程序运行失误甚至不能完成编译.另外编译时常常会因为一些很小的错误造成程序不能运行。但一般根据提示信息很容易改正. ⑤一个程序的每一步一般都有很多种方法去实现,但正确使用库函数可以有效减少编辑程序的复杂程度,使程序变的简练。同时可以减少很多不必要的麻烦,减少编译所用时间,同时能让我们更好地利用C语言。 5.参考文献 [1] 潭浩强,C语言程序设计[M] ,北京:清华大学出版社,2005; [2] 杨 浩 C语言入门经典(第4版)[M],北京:清华大学出版社,2008。4:461—488; [3] 曹衍龙,林瑞仲,徐慧,C语言实例解析精粹(第二版)[M],北京:人民邮电出版社,2007。2:63-68; [4] 潭明金,俞海英,C语言程序设计实例精粹[M],北京:电子工业出版社,2007。1:92-96; [5] 李虎军,姚易顺,C语言上机实验及等级考试指导[M],北京:清华大学出版社,2007。3:56-77; 沈 阳 大 学- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 课程设计 学生 管理 系统
咨信网温馨提示:
1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前自行私信或留言给上传者【二***】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时私信或留言给本站上传会员【二***】,需本站解决可联系【 微信客服】、【 QQ客服】,若有其他问题请点击或扫码反馈【 服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【 版权申诉】”(推荐),意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4008-655-100;投诉/维权电话:4009-655-100。
1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前自行私信或留言给上传者【二***】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时私信或留言给本站上传会员【二***】,需本站解决可联系【 微信客服】、【 QQ客服】,若有其他问题请点击或扫码反馈【 服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【 版权申诉】”(推荐),意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4008-655-100;投诉/维权电话:4009-655-100。
关于本文