C语言课程设计报告Word文档格式.docx
- 文档编号:22264657
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:129
- 大小:97.48KB
C语言课程设计报告Word文档格式.docx
《C语言课程设计报告Word文档格式.docx》由会员分享,可在线阅读,更多相关《C语言课程设计报告Word文档格式.docx(129页珍藏版)》请在冰豆网上搜索。
组长:
白军杰组员:
刘钊何杰
分工:
白军杰负责货物在仓库中的信息管理以及仓库存储区的信息管理中相应的数据结构及算法函数编写。
刘钊负责主菜单,各个输出输入页面和函数的编写,及整个函数的页面跳转和流程控制。
何杰负责用户登录及其相应的对系统功能使用权限管理的数据结构,算法及函数编写。
三个人大致的编程行数为白军杰:
900行,刘钊:
1000行,何杰:
1400行。
三程序主要功能
从整体上说,我们的程序是在分析了现实中仓储物流的过程中可能会遇到的问题及需要管理的信息及其操作的基础上有针对性地编制的,所以其中的功能在现实中都是比较实用的。
其功能主要包括:
货物的入仓,出仓,对某一批货物的精确查询,多重限制条件高级查询,对仓库中某一存储区域的使用情况的查询,每日的出入货记录,用户的登录及由其相应权限所决定的对程序中某些功能访问的限制,添加/删除用户,编辑自己的用户名和密码信息,良好的输入输出界面及菜单选择界面等等。
四程序流程图
五程序中一些主要函数及其功能介绍
1、仓库及货品管理的主要函数及功能:
进货单(GoodsIn):
由系统自动给出该批货品在仓库中唯一的货品编号,由用户输入要入仓的货品信息即可把该商品存入仓库记录中,不过同时也要在仓库存储区也增加相应的被占用空间。
出货单(GoodsOut):
由货品的编号把货品唯一地查询出来,如果查询不到,证明仓库中没有该货品,自然拒绝出货。
如果查询到了,但是仓库信息中的出货日期并不是当天,则系统仍将拒绝出货,并提示用户该货品未到期,如果用户仍想出货,则需要由有相应权限的管理人员修改该笔货品的出货日期信息。
在出货的同时更新仓储区信息。
修改货品信息(EditInfo):
输入要修改的货品编号,如果在仓库中找到该货品则给出要修改的货品信息,并可以在上面直接修改。
如果在仓库中找不到该货品,则给出提示:
找不到该货品。
精确查询(AccurateSearch):
输入某批货品的货品编号即可得到该批货品的详细信息。
高级查询(AdvancedSearch):
输入进货日期,出货日期,价格,规格,数目等条目上的限制条件之后即可得到符合所有已输入条件的货品列表,点击其中的任意一条货品条目即可得到关于该批货品的详细信息。
排序以生成的列表(SortByName,SortBySection):
对已生成的列表按照货品名称或存储区域排序,排序完成之后货品将按照货品名称或区域的字母表顺序把所有列表中货品重新排序。
今日进仓货品(InListToday):
显示今天进仓的货品列表,同样提供点击条目得到该批货物的详细信息及对列表按货品名称或存储区域的排序。
今日出仓货品(OutListToday):
显示今天出仓的货品列表,提供点击条目得到该批货物在仓库中存储时的详细信息及对列表按货品名称或存储区域的排序。
存储区查询(SearchStorage):
输入要查询的存储区号即可得到相应的存储区的使用信息,包括该存储区的总空间,已用空间和空间占用率。
2、用户管理的主要函数及功能:
固定框字符基本输入(getfield):
实现在图形界面下固定输入框的文字输入,传入固定框位置及输入字符存储的地址,就可以在固定位置显示所输入的字符串,同时存储在传入的地址中。
同时,为了方便密码输入的不可现,设计了可以传入参数0、1确定其显示类型——0表示不显示,以*号替代。
用户的登录(login):
进入程序的登陆界面,输入用户名及对应的用户密码,程序自动读出文件中所存储的用户信息进行用户核对。
同时,输入正确即可正确登录;
输入错误可重新输入,或者退出程序该程序同时读出当前用户信息存于程序中,并返回日期,供系统其他函数调用。
主菜单管理功能(manage):
从主菜单中点击进入,实现对系统管理功能的调用,包括,用户编辑,用户添加,用户删除,退出系统等。
点击所需功能项,进入对应功能,使用完毕后自动返回管理的主界面。
用户管理:
系统用户编辑(user_edit):
传入在登录中保存的当前用户信息,在编辑界面中输入修改后的用户名、密码,确认密码后点击即可保存当前信息,并随之写入存储用户信息的文件。
系统用户增加(user_add):
传入当前用户,然后判断structUser_Info结构的用户权限,若为管理员登录(即purview为“1”),可以进行添加,否则显示不能使用。
管理员使用:
输入所需添加用户名,用户密码,确认密码,然后输入所添加用户的权限(是管理员类型还是普通用户),输入完毕,保存,并立刻写入用户文件。
系统用户删除(user_delete):
传入当前用户信息,同时判断用户权限,管理员可以使用,否则显示不可用,退出。
管理员登录后,首先列出用户前14名的信息在列表中,选择所要删除的用户,点击“删除”,即可删除用户,并将即时文档写入用户文件。
需要查找的情况,点击“查找框”,输入所需用户名,若不存在显示“wrongname"
否则按当前查找用户依次往下排列在列表中,再进行删除。
3、界面主要函数及功能:
鼠标函数
voidinitmouse(intmin_x,intmin_y,intmax_x,intmax_y);
初始化在window下运行的鼠标,其中函数四个参量为鼠标的活动区域
intMouseOn(intp[4],intX,intY);
判断鼠标是否在p[4]所指向的区域,p[4]为一个int型数组,一次为一个矩形框的坐标,当鼠标的X,Y值在矩形框的范围内,返回1,否则返回0;
intMouseOn1(inta,intb,inta1,intb1,intX,intY);
功能同上,判断鼠标是否是在a,b,a1,b1的矩形区域内
voidMouse(intx,inty);
此函数的功能用于画鼠标,通过异或的形式使鼠标能够显示和消失;
voidStatus(int*X,int*Y,int*button);
用于取鼠标状态,用于Show函数里
voidShow(int*X,int*Y,int*button);
动态显示鼠标,并且获取鼠标信息。
调用Status函数,通过while循环显示鼠标,并取出任意时刻的坐标及按键状态,
功能辅助函数
voidChangeStrTo(GoodsInfo*entry,char(*string)[20]);
由于通过getfield();
函数得到的信息都是字符串的形式,而结构体里面的信息还有char,long,float型,因而必须通过函数把字符串分别转换成结构体所需的信息类型;
voidChangeEntryTo(GoodsInfo*entry,char(*string)[20]);
把结构体的信息转化成char型,用于字符串的输出
voidFloatTo(floatm,charstr[10]);
将浮点数转换成字符串。
//由于没有现有的函数将浮点数转换成字符串,根据需要,因而通过ltoa及其他函数将其转换成带一位小数的的字符串;
页面函数
voidImageMune(void);
主菜单页面
voidImageSearch(void);
查询页面
voidImageCommomlist(void);
报表信息页面
voidImageAccrute(void);
精确查询页面
voidImageAdvanced(void);
高级搜索页面
voidImageStorage(void);
查询库存页面
voidImagecode(intflag);
通过编号查询所需显示页面
voidImageDayList(intflag);
由于函数页面很多相似,只是需要将文字稍微改变,所以定义intflag来判断,进而显示不同的文字
voidImageGoodsInput(void);
物品信息输入时所显示页面
voidWarning(char*str);
提示页面//由于程序运行过程中会出现一些问题,需要对操作者进行提示,str为提示的内容,里面有一个while()循环,有按键就退出
voidImageGoodsInfo(void);
详细显示物品信息的页面
功能函数:
voidprocess(structUser_Infouser,chardate[]);
程序的最大功能函数,在进入此函数之前会传给用户信息及当天日期,其中用户信息来判断用户是否能执行(EditInfo)函数和(Manage)函数的部分功能。
函数通过鼠标点击来获取是否执行下一级别的函数,其中intf是用来判断页面是否已经被画过,避免由于循环带来的图形的闪烁,以下的intf1等数值均有类似功能
voidsearch();
函数是一个中等级别的功能函数,进入函数以后,可以选择三种查询方式,精确查找,高级搜索,库存查询。
voidcommon(chardate[]);
原理同上,能实现入库单据的填写,物品出库,当日物品进、出库信息的显示及详细显示
voidmanage(structUser_Info*nowuser_p);
输入函数:
Input函数实现在固定地方输入信息
intInputTwoEntry(ListEntry*entry1,ListEntry*entry2);
在高级搜索的函数中调用,输入部分或者全部选项,通过辅助函数将输入字符串转化为结构体,并将信息传递到高级搜索函数中,以供其查询;
定义为int型是为了判断函数是否执行完全,以便选择是否执行后面的函数。
当完全执行后返回值为1,否则为0。
下同
intInputEntry(ListEntry*entry,unsignedlongindate);
在进库单据的填写时候调用,在固定的对话框里输入物品信息,并将其转化为结构体数据类型;
intInputCode(intflag,charcode[]);
输入物品编号,实现编号在程序中的传递。
flag是由于要实现不同的功能,而在相似页面做稍微文字处理,从而显示不尽相同的页面。
函数在查找物品的时候调用,如精确查找,出库物品显示等
intInputSection(char*section);
输入物品的库区,并实现参数的传递,在查询库存信息的时候调用;
intModifyEntry(ListEntry*entry);
在修改信息的时候使用,类似与InputEntry();
有所改变,为了能在显示所有信息的同时实现修改
显示函数Dis函数:
在固定区域将物品的信息显示出来
voidDisList(ListNode*array[]);
显示含有多个查询结果的输出,由于可能有多个符合条件的物品信息,此函数只显示部分信息,列成表的形式。
将在DisArray函数中使用;
voidDisEntry(ListEntry*entry);
通过辅助函数的转换,显示物品的全部详细信息
voidDisStorage(StorInfo*storinfo);
显示查询库区的库存信息,有三个内容,包括所查询库区总容量,已用容量,利用率。
voidDisArray(intflag1,ListNode**array);
先调用DisList函数,列出所需显示物品的部分信息,通过点击,调用DisEntry函数,可以显示物品更加详细的信息。
在函数中,调用排序函数,能将结构指针按照Code(默认的顺序),Name,Section排序,并显示在DisList函数中。
函数具有判断值f1,用于防止while循环带来的页面循环。
里面定义数组p[17][4]是作为鼠标函数MouseOn所作用的范围.
六基本数据结构及算法思想
1、基本数据结构:
货品在仓库中的信息管理主要由一个单向链表和一个指针数组组成的数据结构来实现。
首先定义一个货品在仓库中存储时所需要的各项信息,包括进货日期,出货日期,该批商品的数量,规格(长、高、宽),单价等等,把所有这些信息定义为一个GoodsInfo的struct中,也叫ListEntry。
在平时这些数据都存放在以进货日期为文件名的文件中,在需要查询时从文件中读出,随即顺序组成一个单向链表,然后生成一个指针数组,数组的每一个元素都是指向ListNode的指针,这样由这个数组就可以达到随机访问链表中节点的目的,这样做是因为有更深的考虑,即:
把链表的插入删除十分灵活方便的优点和数组可以支持随机访问的优点结合起来,之所以要插入删除十分方便是因为货品有频繁的进出仓库的行为,需要进行频繁的插入删除操作,而之所以要支持对节点的随机访问是因为要对货品进行高等查询及排序等操作,排序的算法在数组中明显要比在链表中要来得快,而且把排序的结果存放在一个数组中可以使得链表保持原来的状态,这样便于对链表进行其他操作时造成出乎意料的影响。
在仓库信息的管理中除了仓库中的货品之外还有一个方面,就是仓库本身状态的信息,在这个程序中我们认为仓库存储信息主要包括仓库存储区的区号(A、B、C),仓库存储区的总空间,已用空间,和空间的利用率。
平时这些信息也都存储在文件中,以保证即使中途退出程序依旧可以在下次启动程序时得到这些信息。
这些信息也定义成为一个struct,也就是StorInfo。
在需要这些信息的时候(如进货,出货,修改仓库中货品的信息的时候)把它们从文件中读出,放在一个数组中,然后在用户做出相应操作的同时对这些信息予以相应的更新。
帐号管理主要用到了结构来存储用户信息,定义了结构体
structUser_Info{
charname[10];
//存储用户名
charpassword[15];
//存储用户密码
charpurview[4];
//存储用户权限(管理员或者普通用户)
}
2、主要算法:
仓库及货品管理算法:
在进货的时候从文件中读出当天文件,把这些当天进仓的货品组织在一个链表中。
由系统自动分配给该批进仓货物一个唯一的货品编号,此编号在整个仓库存储过程中不可更改,然后即可把该批货品的详细信息写入一个ListEntry中,再把它转化成链表节点插入链表中,最后把链表内容存入文件。
同时把仓库储存区的相应信息予以更新。
同进货单类似,读文件,生成链表,然后在链表中根据唯一的货品编号查找到相应的货品,把该节点删除,并写入存储已出仓货品的文件中,把修改后的链表存入原文件中,并更新相应的存储区信息。
与出货单相类似,读文件,生成相应链表,根据货品编号搜索相应的节点,但是并不删除该节点,而是直接更改该节点内entry的信息,最后把修改后的链表保存即达到了修改仓库货品信息的目的。
读文件,生成相应链表,遍历该链表,当搜索到编号与要搜索的编号一致时停止遍历,输出该货品信息。
由于输入的是多种限制条件,因此需要用到上面介绍过的指针数组来存储搜索结果,搜索是通过一遍又一遍的对指针数组的遍历来完成的。
首先生成对应整个链表的指针数组,然后一次以一个条件来根据数组中的指针来搜索符合相应的某个条件的节点,在查找到符合要求的节点之后把指向这些节点的指针赋到数组的最前面去,再找到一个符合条件的节点就把指向这个节点的指针赋到前一个符合条件的指针的后面去,最后在遍历到这个数组的结尾(以一个NULL指针为结束标志)时停止这次对数组的遍历,认为已经找到了数组中所有符合该条件的节点。
把最后一个符合条件的指针后面的一个位置赋为NULL指针,作为指针数组新的结束标志,就像字符串以'
\0'
为结束标志一样。
这样下一步对另一个条件的搜索将在上一次搜索确定的符合条件的范围中再进行筛选,这样,在经过对所有条件的搜索之后,得到的数组中指针指向的元素将是符合所有输入条件的货品的集合。
这样,根据指针数组中给出的结果输出即可得到高级查询的结果。
由于所有的以列表形式给出的结果都是根据指针数组得出的结果,所以对已生成列表中元素根据Name,Section的排序实际上也就是对指针数组的排序,具体的排序算法这里采用的是冒泡法,由于充分利用了数组可以随机访问的特点因此对列表的排序其运行速度还是相当迅速的。
读取今日的进货信息,生成链表,生成相应的指针数组,根据指针数组生成相应的列表输出。
从存储已出货商品的文件中读取所有的出货商品信息,生成相应链表及指针数组,根据出货日期找到今天出仓的货品,结果放在指针数组中以列表形式给出。
打开存放存储区信息的文件,把3个存储区的信息读入数组中,根据输入的存储区号找到相应的存储区,再给予输出。
用户管理算法:
在函数之前定义存储数组,将地址传入函数,在函数中利用字符数组的传递,利用循环不断的要求输入字符,并将当前输入字符显示,并且利用get_key(char*ch,char*ext)区分控制字符串和字符串,当响应回车(Enter)、换行符(Tab)时保存所输入字符并退出,当响应退出键(Esc)时不保存当前输入直接退出。
定义结构型数组(structUser_Infoalluser[MAX_NUM]),执行函数时首先读取文件用户信息存储于结构中,定义存储用户名、密码的字符数组,循环调用getfield并用循环判断的方式判断输入正确与否,并确定正确时的用户号(数组中第几个用户),要求输入错误可以重新输入。
在完全正确后方可执行完毕,否则循环输入或自动退出。
利用鼠标坐标(X,Y)确定鼠标位置信息,判断按键(button)来选择对应用户管理功能。
定义临时用户结构,用来接受用户修改的信息,点击确认修改时,将临时信息写入文件,同时设计结构指针接受当前用户信息,并做即时修改,保持当前用户的即时性。
在函数中同时需要在确认修改后读取用户信息文件,将修改信息用字符数组写入读取的结构数组,替换成功后重新将结构数组写入文件。
系统用户增加(user_add):
接受用户信息的结构指针,判断用户权限。
此后,定义临时结构存储添加用户信息,并写入全部结构数组中,等待确认写入文件。
同用户增加,首先判断权限。
读取所有用户信息的结构,定义长度数last_num,定义位置数postion显示用户前面用户在用户表列中。
此时,等待查找用户信息:
输入信息,按遍历的方法确认用户,并用outtextxy依次从查询用户的当前位置开始显示,利用数组alluser[now_usernum]输出。
默认状态下所有位置数均为1,即删除显示所在列表的首用户。
确认删除后,从当前用户开始,利用循环将数组后的用户依次向前移动一次,这样实现用户的删除,结束后写入文件。
七感想及思考
经过这样一个大程序的编写,我们深刻体会到了周纯杰老师一直向我们强调的程序编写的模块化和规范化的要求是多么地重要,在程序越编越大的时候,如果不把程序分成小的模块编写,那么完成编码任务将是极其艰难的,而且即使你编出了这样的程序,那么完成对它的调试也将是不可能完成的任务,更不用说去维护这样一个程序了.
把程序写成小的模块,一方面是正如周老师说的,把一个问题分成几口来吃,分完了还吃不下,怎么办?
接着分,总可以分到可以一口吃下的一小块.这样就是降低了编码的难度.另一方面,也是降低了调试和维护的难度,如果程序是一块一块的,那么维护人员添加一个模块,就可以扩充程序的功能,但是如果程序不是模块化的,而是一大堆的语句,那么对这个程序的扩充升级将是不可想象的.再提一下调试,实际上把程序编成小的模块事实上也把错误限制到了一个小的范围内,如果你发现了一个函数有错误,你可以设计有针对性的Driver(驱动)程序去测试调试这个函数,调试一个五十行以下的函数,明显比调试一个三百多行的大函数要简单得多,这样实际上把调试时的问题也分解成了一个一个的小问题.
总之,如果不进行这种模块化的分解,那么问题的难度上升的速度,将不是简单地按照与行数成比例的速度上升,而是几何速度飞速增长,一个区区上千行的程序既已如此,想想像Windows2000这样超过3000万行的编码是怎样作为一个整体良好地运行的.现在的WindowsXP,Vista呢?
正如周纯杰老师所说,要做大事,就必须要学会模块化的编程.
第二个感想是编码的规范化问题.现在也终于理解了我们的教材取名为<
标准C语言程序设计及应用>
的良苦用心了,在图书馆见了那么多关于C语言的书,却少有几本是把自己的名称中加入”标准”二字的.从一开始还没学会if语句老师就开始向我们讲要有规范化的书写,要写出清晰易懂的语句.现在深刻地体会到了良好风格对编程的重要性,如果写出的程序清晰易懂,那么调试的时候也容易找出相应的逻辑错误,如果写出的程序连自己都看不懂,看不清楚,那这个程序无疑是失败的.
八具体源代码
下面是由白军杰编写的仓库和货物管理部分和刘钊编写的界面和输入输出函数的源代码:
头文件DATA.h
#ifndefDATA_H
#defineDATA_H
#include<
stdio.h>
alloc.h>
stdlib.h>
conio.h>
dos.h>
string.h>
typedefstructgoodsinfo
{
charCode[13];
charName[14];
charSection;
unsignedlongInDate;
unsignedlongOutDate;
floatStandard[3];
floatPrice;
intNumber;
}GoodsInfo;
typedefGoodsInfoListEntry;
typedefstructlistnode
ListEntryentry;
structlistnode*next;
}ListNode;
typedefstructlist
ListNode*head;
ListNo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 课程设计 报告