分类

课内:
不限
类型:
不限 毕业设计 课程设计 小学期 大作业
汇编语言 C语言 C++ JAVA C# JSP PYTHON PHP
数据结构与算法 操作系统 编译原理 数据库 计算机网络 软件工程 VC++程序设计
游戏 PC程序 APP 网站 其他
评分:
不限 10 9 8 7 6 5 4 3 2 1
年份:
不限 2018 2019

资源列表

  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端Android Studio实现的2048游戏

    1 需求分析1.1 背景与意义1.1.1 手机应用市场发展现状随着4G越来越普及以及手机应用的日益丰富还有智能水平的不断提高,从便携性和随身性这两方面来考虑,电脑所带来的体验已经不能跟手机相提并论了,它已经完美的超越了电脑。
    现如今Android、苹果等各智能手机已经基本占领整个手机市场,从而使得更多应用的出现,而手机游戏应用在其中占领主要位置。
    随着Android智能手机的普及以及游戏种类的多元化,使得Android手机游戏用户规模保持着稳步增长之势。
    1.1.2 国内外现状目前国内外的Android开发还是主要以应用开发为主,主要分成三类:企业应用、通用应用及游戏应用。企业应用的开发主要是一些大公司为了自己的品牌而开发的;通用应用主要是一些创业型公司或者独立开发者为了自己盈利开发的应用;游戏应用目前和通用应用相同。
    2048小游戏是一款最近风靡全球的手机游戏,简单的游戏模式和趣味的玩法,几乎游戏下载排行榜的前20名都可以看到“它的身影”。
    1.1.3 此游戏的意义现如今,手机游戏已在我们的生活中占据一席之地,并在一步步的壮大。可以说,随着它的迅猛发展,现今的手机游戏已经不单单是一种缓解压力的工具,而是形成了一种文化现象。随着游戏软件在市场的一步步壮大,与其有关的文化也随之传播。
    2048游戏的制作属于电子游戏中益智类小游戏,它做到了娱乐性、趣味性、教育性相统一。益智类的游戏即是需要去开动大脑思考从而获得游戏的胜利。简单的益智类游戏可以使玩家在娱乐中不断地开发大脑。这样一来就实现了在娱乐中学习。
    1.2 系统需求分析1.2.1 系统功能需求分析系统主要实现以下的几个功能:呈现游戏界面、重新开始游戏、当前分数和最高分数、游戏帮助等功能。
    重新开始游戏是当玩家无法满足当前进度时点击此按钮就会重新开始游戏,如果玩家处于不同关卡时提示重新开始游戏还是停留在此关卡。游戏帮助是当新手玩此游戏时无法知道游戏玩法时给予相应的提示。呈现游戏界面是游戏开始时主界面在游戏区域会生成4x4的矩阵同时在矩阵里面随机生成两个2或4的游戏卡片。当前分数和最高分数是显示此局玩家所获得的分数和历史上最高的分数,如果当前的分数超过最高的分数,那么最高分数显示当前的分数。如下图所示:

    1.2.2 游戏的基本规则在开始游戏后玩家通过滑动屏幕来操控卡片的移动方向,当卡片滑动中如果有两张卡片相同且他们中间也没有其他卡片时,在滑动的过程中这两张卡片会合并,显示为这两张卡片之和。在滑动过程中有三张卡片相同时只会合并向滑动方向两张卡片。在滑动中如果有两张卡片一样同时又有一张卡片的值跟这两张卡片相加的值时,滑动只会使那两张相同的卡片合并而不会接着让合并后的卡片和另一张卡片合并。
    2 系统分析与设计2.1 系统流程设计游戏进入开始页面,能够进入游戏的主界面并开始普通开局,从主界面能够重新开始游戏、查看帮助和进入关卡选择界面。当玩家点击重新开始按钮会弹出相应的对话框让玩家选择,如果玩家选择“是”时则重新开始游戏,如果选择“否”则返回游戏界面不做任何处理。在开始界面按返回按钮时则会退出游戏。
    游戏流程如下图所示:

    2.2 系统模块设计从总体出发,将该系统划分为三大模块:“菜单设计”、“界面设计”和“算法设计”。
    2.2.1 菜单设计菜单的实现是在游戏界面,可进一步划分为三个模块,分别是:“重新开始”、“退出游戏”、“游戏帮助”,如图所示:

    2.2.2 界面设计


    开始界面
    游戏界面









    2.2.3 算法设计当有两张卡片相同时,向它们可以碰撞的方向滑屏,卡片会移动到最底边并生成其两倍数字的卡片,并且生成一个“2”或者“4”的卡片。如图所示:



    生成2
    生成4









    当有两张卡片相同时,且在它们相同的方向有张跟他们之和的卡片,向它们可以碰撞的方向滑屏,相同的卡片会移动到无法移动的位置并生成其两倍数字的卡片,但合成的方向不会跟那两张数字的卡片合并,并且生成一个“2”或者“4”的卡片。如图所示:



    生成2
    生成4









    当界面上没有空位并且两两相邻的卡片不相同时游戏结束。如图所示:

    2.3 本章小结本章主要对游戏所实现的功能进行需求分析,分析了图形的特点和实现的可行性。对系统的性能进行了详细的分析。对系统的流程,系统所需的图形文件,系统的总体架构和系统用例进行了设计。通过本章的分析、设计能更加具体的了解系统功能,对系统所要实现的功能和图形文件有了更深的认识。为下一章系统功能的具体实现提供了可靠的参考依据。
    3 系统实现3.1 开始界面的实现游戏的主界面是按钮,只是为了实现界面的跳转,当玩家点击开始游戏就会调用loginActivity.java,此函数让页面跳转到游戏界面开始游戏,代码及图片如下所示:
    public class loginActivity extends MainActivity { protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.login); }}

    3.2 游戏界面的实现游戏界面主要是在activity_main.xml中当前分数、最高分数、重新开始按钮、退出游戏按钮、游戏帮助按钮、帮助按钮,当跳转到游戏界面时就会调用并执行MainActivity.java函数来展示游戏界面,代码及图片如下所示:
    protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);}

    3.3 游戏滑动卡片移动的实现当玩家滑动屏幕时,主要通过GameView函数来监听玩家手指滑动的位置,先通过获取开始坐标和结束坐标,然后通过比较结束坐标跟开始坐标的差值来判断玩家是怎么滑动屏幕的。判断出玩家的滑动轨迹后,通过调用swipeLeft、swipeRight、swipeUp、swipeDown方法来实现卡片的移动,代码及图片如下所示:
    private void initGameView(){ setColumnCount(4); //将面板设置成4列 setBackgroundColor(0xffbbada0); System.out.println("initGameView"); setOnTouchListener(new View.OnTouchListener() { /* * startX:手机刚开始在屏幕上的X坐标 * startY:手机刚开始在屏幕上的Y坐标 * offsetX,offsetY,分别是手指在屏幕上的X,Y上的偏移量 */ private float startX,startY,offsetX,offsetY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); break; case MotionEvent.ACTION_UP: offsetX = event.getX() - startX; offsetY = event.getY() - startY; if(Math.abs(offsetX) > Math.abs(offsetY)){ if(offsetX < -5){ swipeLeft(); System.out.println("Left"); }else if(offsetX > 5){ swipeRight(); System.out.println("Right"); } } else{ if(offsetY < -5){ swipeUp(); System.out.println("Up"); }else if(offsetY > 5){ swipeDown(); System.out.println("Down"); } } break; } return true; } });}//向左滑动public void swipeLeft(){ boolean meger = false; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { for (int x1 = x+1; x1 < 4; x1++) { if(cardsMap[x1][y].getNum()>0){ if(cardsMap[x][y].getNum()<=0){ /* * 将下标为(x,y)所在位置的卡片上的数字 * 设置为,坐标为(x1,y)所在位置的卡片上的值; * 第二步,将坐标(x1,y)所在位置的卡片上的数字 * 设置为0 * (即:变成空卡片) */ cardsMap[x][y].setNum( cardsMap[x1][y].getNum()); cardsMap[x1][y].setNum(0); x--; meger =true; break; }else if(cardsMap[x][y].equals(cardsMap[x1][y])){ cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2); cardsMap[x1][y].setNum(0); MainActivity.getMainActivity(). addScore(cardsMap[x][y].getNum()); meger = true; } break; } } } } if(meger){ addRandomNum(); checkComplete(); }}//向右滑动public void swipeRight(){ boolean meger = false; for (int y = 0; y < 4; y++) { for (int x = 3; x >=0; x--) { for (int x1 = x-1; x1 >= 0; x1--) { if(cardsMap[x1][y].getNum()>0){ if(cardsMap[x][y].getNum()<=0){ /* * 将下标为(x,y)所在位置的卡片上的数字 * 设置为,坐标为(x1,y)所在位置的卡片上的值; * 第二步,将坐标(x1,y)所在位置的卡片上的数字 * 设置为0 * (即:变成空卡片) */ cardsMap[x][y].setNum( cardsMap[x1][y].getNum()); cardsMap[x1][y].setNum(0); x++; meger =true; break; }else if(cardsMap[x][y].equals(cardsMap[x1][y])){ cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2); cardsMap[x1][y].setNum(0); MainActivity.getMainActivity(). addScore(cardsMap[x][y].getNum()); meger =true; }break; } } } } if(meger){ addRandomNum(); checkComplete(); }}//向上滑动public void swipeUp(){ boolean meger = false; for (int x= 0; x< 4; x++) { for (int y = 0; y < 4; y++) { for (int y1 = y+1; y1 < 4; y1++) { if(cardsMap[x][y1].getNum()>0){ if(cardsMap[x][y].getNum()<=0){ /* * 将下标为(x,y)所在位置的卡片上的数字 * 设置为,坐标为(x1,y)所在位置的卡片上的值; * 第二步,将坐标(x1,y)所在位置的卡片上的数字 * 设置为0 * (即:变成空卡片) */ cardsMap[x][y].setNum( cardsMap[x][y1].getNum()); cardsMap[x][y1].setNum(0); y--; meger =true; break; }else if(cardsMap[x][y].equals(cardsMap[x][y1])){ cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2); cardsMap[x][y1].setNum(0); MainActivity.getMainActivity(). addScore(cardsMap[x][y].getNum()); meger =true; } break; } } } } if(meger){ addRandomNum(); checkComplete(); }}//向下滑动public void swipeDown(){ boolean meger = false; for (int x = 0; x< 4; x++) { for (int y = 3; y>= 0;y--) { for (int y1 = y-1; y1 >=0; y1--) { if(cardsMap[x][y1].getNum()>0){ if(cardsMap[x][y].getNum()<=0){ /* * 将下标为(x,y)所在位置的卡片上的数字 * 设置为,坐标为(x1,y)所在位置的卡片上的值; * 第二步,将坐标(x1,y)所在位置的卡片上的数字 * 设置为0 * (即:变成空卡片) */ cardsMap[x][y].setNum( cardsMap[x][y1].getNum()); cardsMap[x][y1].setNum(0); y++; meger =true; break; }else if(cardsMap[x][y].equals(cardsMap[x][y1])){ cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2); cardsMap[x][y1].setNum(0); MainActivity.getMainActivity(). addScore(cardsMap[x][y].getNum()); meger =true; } break; } } } } if(meger){ addRandomNum(); checkComplete(); }}



    效果1
    效果2









    3.4 重新开始游戏功能的实现当玩家点击游戏界面的重新开始游戏时,会弹出给玩家选择的对话框,让玩家选择“是”时游戏会重新开始,代码及图片如下所示:
    public void onClick(View view){ AlertDialog.Builder dialog3 = new AlertDialog.Builder(this); dialog3.setTitle("提示:"); dialog3.setMessage("你确定重新开始吗?"); dialog3.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog3.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog3.show(); }

    3.5 退出游戏功能的实现当玩家中途有事想退出游戏时会弹出给玩家选择的对话框,让玩家选择“是”时游戏会退出,代码及图片如下所示:
    public void onClick(View view){ AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setTitle("提示:"); dialog.setMessage("你确定要离开吗?"); dialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { System.exit(0); } }); dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog.show(); }

    3.6 游戏帮助功能的实现当新玩家进入到游戏且不知道此游戏玩法时,玩家可以点击游戏帮助按钮来了解游戏玩法,点击按钮时游戏会弹出对话框显示游戏玩法,代码及图片如下所示:
    public void onClick(View view){ AlertDialog.Builder dialog2 = new AlertDialog.Builder(this); dialog2.setTitle("hey,guy!"); dialog2.setMessage("这么简单的游戏你确定需要帮助?"); dialog2.setNegativeButton("继续玩~", new DialogInterface.OnClickListener({ @Override public void onClick(DialogInterface dialog, int which) { } }); dialog2.show();}

    3.7 本章小结本章主要阐述本游戏相关功能的实现,详细的讲述了主界面的实现和各按钮功能的实现。
    4 测试本章主要对系统的功能进行测试,此次测试只是进行简单的调试,来确定游戏的各项功能是否能够正常运行。
    4.1 游戏流程测试该测试主要验证游戏能否实现场景的切换,当界面在开始界面时只显示按钮画面,当玩家点击此界面的开始按钮时跳转到游戏界面,如图所示:



    效果1
    效果2









    4.2 游戏模式该测试主要是测试游戏能否正常运行,当玩家滑动屏幕时能否正常的移动和当卡片相同时是否能够相加,还有就是测试游戏是否能正常结束。



    效果1
    效果2









    4.3 本章小结本章是对游戏系统进行简单的测试,通过测试可以看出此游戏可以正常的工作,同时一些功能也能够实现。
    5 总结本次课程设计的内容大部分都是参照课堂所讲以及一些网站给出的各种建议写的,在写的过程中遇到了很多问题,学到了很多东西。期间大概是因为基础不够好,只是找错误就花了很长时间。不过正因为这些错误,才能学到更多的知识,才能把知识点掌握的更牢靠,对于一些没有实现的功能,之后我一定会多花费些时间研究出来。我的课程设计优化的空间还相当大,希望老师能给出指导!
    6 评论 352 下载 2018-12-20 18:49:18 下载需要8点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端C#实现的电影院售票管理系统

    一、引言1.1选题背景随着互联网和电子商务的快速发展,网上购物已经成了现代人生活中很重要的一种方式,如:数码产品、生活用品、化妆品护肤品等,只要是人们需要到的东西,基本都可以在网上购买。除了购买各种物品,现代人的生活也不再向过去一样单调,除了学习和工作之余,人们的娱乐生活也逐渐丰富,最普遍的娱乐休闲方式之一就是到电影院看电影,那么传统的电影订票窗口显然已经不能满足人们的需要了,所以开发一个电影院网上订票系统是非常必要和可行的。以前传统的电影票订票方法是去电影院的购票窗口查看电影的上映时间、场次、可选座位等信息再进行购票,人们往往需要排队才能买到电影票,这样不仅浪费了人们宝贵的时间,而且电影院工作人员的工作量也很大,对于这种低效率、浪费时间的事情,完全可以以网上购票的方式来改变。
    为了提高劳动的效率、节约成本、提高服务质量,我们小组开发了此款系统,用以方便影院的售票和客户的购买,通过这个系统,可以很快的实现会员注册、登录、购票,后台管理员可以新增影片、排片等基本操作。
    二、需求分析2.1 用户需求需要在网上购买电影票的用户可使用本系统,进行会员的注册登陆之后可以进行网上查询电影、购买电影票等操作,省去了去电影院实体窗口排队买票的繁 琐程序。
    2.2 系统功能分析
    新用户的注册、登录,用户数据能存在后台数据库中
    电影的录入、删除、查询、修改
    电影的排片
    管理员查询会员级别等信息
    会员查询影片信息
    会员购买电影票

    2.3 条件与限制系统可以实现一些基本的购票功能,但系统较简单,尚存在很多缺陷,不能实现完善和全面的功能。
    缺陷:

    首先要使用admin进行登录才能开始注册会员
    购票后无法查看购票信息
    不可以支持选座
    购票时不能通过搜索影片名字等来查找影片

    三、模块设计3.1 系统流程图系统流程图如图一所示:

    系统功能图如图二所示:

    3.2 系统使用指南对于用户
    首先,系统使用者先通过admin登录,进入到新用户注册页面,以管理员的身份为用户注册一个新的会员账号,已注册好的账号密码自动保存在后台数据库中,用户下次可以直接使用已注册的会员账号登录本系统进行电影的查询、购票等操作。
    对于管理员
    首先,管理员可以为新用户注册不同级别的会员账号、查看会员的信息。其次,管理员可在系统后台做电影的录入、删除、查询、修改等基本操作,除此之外,添加好影片后可以对电影进行的排片。
    四、数据库设计及实现4.1 系统E-R图E-R图如图三所示:

    4.2 逻辑结构设计(关系数据库设计)
    顾客(Cus、CusCard、CusType、CusTel(key))
    登陆(UserName、UsePwd、UserType)
    电影(Mname(key)、MBZ、MLanguage、MTYPE、MDirector、MACT、MTime)
    排片(MName(key)、MPrice、MRoom、Mcount、MTime、MBRQ、MERQ)
    上映(ID(key)、MName、MPrice、MRoom、MCount、MTime、MRQ)
    购票(PID(key)、Cname、GPCount、GPJE、MName、SYRQ、FYT、GPRQ、CZY)

    4.3 数据库主要代码及触发器会员信息
    CREATE TABLE [dbo].[Cus]( [CusTel] VARCHAR(50) NOT NULL PRIMARY KEY, [CusName] VARCHAR(50) NOT NULL, [CusCard] VARCHAR(50) NULL, [CusType] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[InsertULogin] on [dbo].[Cus]after insertasdeclare @username varchar(50)declare @userpwd varchar(50)select @username=CusTel from inserted select @userpwd= right(CusCard,6) from inserted insert into ULogin values(@username,@userpwd,'C')
    购票信息
    CREATE TABLE [dbo].[GP]( [PID] VARCHAR(50) NOT NULL PRIMARY KEY, [CName] VARCHAR(50) NOT NULL, [GPCount] INT NULL, [GPJE] FLOAT NULL, [MName] VARCHAR(50) NULL, [SYRQ] VARCHAR(50) NULL, [GPRQ] VARCHAR(50) NULL, [CZY] VARCHAR(50) NULL, [FYT] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[UpdatePP] on [dbo].[GP]after insertasdeclare @MName varchar(50)declare @SYRQ varchar(50)declare @count intselect @MName= MName,@SYRQ=SYRQ,@count=GPCount from inserted update MovieSY set mcount=mcount-@count where MName=@MName and MRQ=@SYRQ
    电影信息
    CREATE TABLE [dbo].[Movie]( [MName] VARCHAR(50) NOT NULL PRIMARY KEY, [MLanguage] VARCHAR(50) NOT NULL, [MDirector] VARCHAR(50) NULL, [MAct] VARCHAR(50) NULL, [MName] INT NULL, [MBZ] VARCHAR(255) NULL, [MType] VARCHAR(50) NULL)
    上映信息
    CREATE TABLE [dbo].[MovieSY]( [ID] INT NOT NULL PRIMARY KEY, [MName] VARCHAR(50) NOT NULL, [MRoom] INT NULL, [MCount] varchar(50) NULL, [MName] INT NULL, [MTime] VARCHAR(50) NULL, [MRQ] VARCHAR(50) NULL)
    排片信息
    CREATE TABLE [dbo].[PP]( [MName] VARCHAR(50) NOT NULL PRIMARY KEY, [MPrice] INT NOT NULL, [MRoom] VARCHAR(50) NULL, [MCount] INT NULL, [MTime] VARCHAR(50) NULL, [MBRQ] VARCHAR(50) NULL, [MERQ] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[InsertPP] on [dbo].[PP]after insertasdeclare @MName varchar(50)declare @BRQ varchar(50)declare @ERQ varchar(50)declare @MTime varchar(50)declare @MRoom varchar(50)declare @MPrice intdeclare @MCount intdeclare @MBRQ datetimedeclare @MERQ datetimedeclare @RQ varchar(50)select @MName= MName,@BRQ=MBRQ,@ERQ=MERQ,@MTime=MTime,@MRoom=MRoom,@MPrice=MPrice, @MCount=MCount from inserted set @MBRQ=CONVERT (datetime,@BRQ)set @MERQ=CONVERT (datetime,@ERQ)while @MBRQ<=@MERQbegin set @rq=CONVERT(varchar(50), @MBRQ, 112)insert into MovieSY values(@MName,@MPrice,@MRoom,@MCount,@MTime,@RQ) set @MBRQ=DATEADD(DAY,1,@MBRQ)endCREATE TABLE [dbo].[MovieSY]( [UserName] VARCHAR(50) NOT NULL PRIMARY KEY, [UserPwd] VARCHAR(50) NOT NULL, [UserType] VARCHAR(50) NULL)
    五、系统设计与实现5.1系统开发环境
    硬件环境

    Intel Pentium 166MHz或以上;内存:需要至少512MHZ;
    软件环境

    运行于Windows2010版的操作系统之上;SQL Server2008数据库;Visual Studio2013;

    5.2 功能模块
    输入功能模块
    查询显示功能模块
    查询、售票功能模块
    登录、注册功能模块

    5.3 系统主要页面展示登录、注册页面

    登陆后的页面

    会员注册页面

    会员信息查询页面

    添加影片页面

    查询修改影片页面

    排片页面

    “排片”页面通过连接数据库,可以搜索影片的名字、导演、主演来选择影片,再输入票价,放映大厅,座位数,放映时间等信息,最后确认排片。
    购票页面

    购票页面通过对获得的已经被排片的电影进行选择而进行购票这一操作。在购票前需填入购票数量、联系电话,系统会自动计算合计金额。之后点击购票按钮则能进行购票操作。但一旦购票成功则不能进行退票操作,也不能查看所购买的电影票。
    数据库页面

    六、主要特色6.1 系统实用性系统首先可以进行新用户的注册,用户数据能存在后台数据库中。管理员可以进行电影的录入、删除、查询、修改,添加好影片后进行电影的排片。退出登录后再使用之前注册的会员登录,可以购买电影票。
    6.2 突出优势和特色(创新点)
    购票时可以看到影片的导演、主演等信息
    用户分为钻石用户,白金用户和普通用户,对用户进行了分类

    7 小结数据库技术课程设计是一次对课堂所学知识的灵活应用,是理论知识与实践的相结合。经过了一周的课程设计,本系统基本达到了当初的设计要求,设计上也基本合理。我们不仅对数据库系统的认识更加深入,同时也掌握了面向实体的系统分析的基本方法,对VS也有了新的认识,也知道了要有坚持不懈,不惧困难的精神,才能取得成功。一个简单的系统,每一个细节都需要在实践中去挖掘并进行进一步的修改完善。本次课设让我们受益匪浅,在分析问题以及解决问题等方面的能力有所提高,也是一次很好的同学之间交流合作的机会。数据库技术的用途很广,还有很多值得我们学习,希望今后能有更多这样的机会。
    10 评论 107 下载 2019-01-01 18:20:12 下载需要18点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端c++的哈夫曼编码

    c++实现哈夫曼编码,本例中采取了相对简单易懂的构建方式,与其他相类似的代码相比,更为直观和简练。
    C++实现的哈夫曼编码与解码:

    统计某电文中字符出现的频率(假设电文中只含有大小写英文字母)
    把字符出现的频率作为权值建立哈夫曼树,进行哈夫曼编码,并输出每个字符的编码结果
    对电文进行哈夫曼编码
    把电文的哈夫曼编码进行译码,输出对应电文的内容

    网上有很多说明都不是很清楚,接下来我来仔细说明,对新手很有帮助。这里我只说重要的思路,剩余的代码需要大家认真看懂。
    第一是要做准备工作,现在有一个字符串,字符与编码是一一对应的,而对应的条件取决于出现的次数,所以我们应该考虑做两个数组,长度一样,一个存储字符,一个存储次数。由于要保证他们的顺序,我们再拿来两个队列,这样就可以保证顺序了!
    第二,我们要找的是出现的字符,要保证不重不漏,还要找相对应的出现次数,fan函数就是这个用处
    int fan(char x,queue<char> s1)//保证a字符串中下一个字符不重复,将不重复字符入队列 { char a[10];int i=0; while(!s1.empty()) { if(x!=s1.front()) { a[i]=s1.front(); i++; s1.pop(); } else { for(int j=0;j<=i;j++) { s1.push(a[j]); } return 0;break; //有一样的字符返回值为0 } } for(int j=0;j<=i;j++) { s1.push(a[j]); } return 1; //与队列中的字符都不一样则返回1 }
    到第三步,开始编码工作,这时候,我们有两个数组,一个存储着字符,一个存储着相应的出现次数,以此为新的起点。因为是每两个最小的数组合在一起,作为一棵树的两个子节点,我们要找数组的两个最小值,把对应的值相加,形成一棵树,并重新放入数组,以此类推最后就可以形成一棵完整的树了。在知道原理后,编码与解码工作就不难了。
    顺便强调,我们需要注意的是,HuffmanTree类型的huffmen数组的长度是2*k-1,是要让Huffman[i]对应Huffman[k+i+1]也就是后面多出的是作为父节点存在的,使每一个节点都有与之对应的父节点。
    2 评论 14 下载 2019-05-25 19:25:35 下载需要3点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端C语言的校运动会项目管理系统

    前言随着计算机技术的普及与提高,越来越多的人使用计算机,计算机以其强大的性能价格优势给人们的工作、学习和生活带来极大的方便.计算机代替人工处理一些事务已成为必然。整个人类社会已进入高度信息化,人们对信息和数据的利用和处理已经进入自动化、网络化和社会化的阶段。如在查找资料、处理日常办公事务、科研生产等方面,无不需要利用大量的信息资源。因此,如何有效地进行数据信息的管理和利用,已经成为人们普遍关注的课题。信息在不同的领域里有着不同的概念,在管理科学领域中,通常认为信息是经过加工处理后的一种数据形式,是一种有次序的符号排列,它是系统传输和处理的对象。处在信息时代的今天,信息的作用越来越为人们所重视。制定成绩计划,研究投资策略,都离不开对信息的充分利用。
    在当今社会上,体育运动越来越普及,参与运动会的人越来越多,素质越来越高。传统的运动会,一般是以人手组织为主,运动员的报名、赛事的安排、比赛场地的安排和成绩的记录等操作全都由人手操作,参加人数越多,运动会的规模就越大,管理工作就更加费时费力,而且容易出错。学校田径运动会管理系统则为组织者提供一个简捷方便的方式来组织管理运动会,学校田径运动会管理系统是一种“人机交互系统”,通过简单的键盘输入与鼠标点击来完成烦琐的记录与安排工作,保证运动会的正常流畅的进行。学校田径运动会管理系统是典型的数据库应用系统,可完成田径运动会管理中的运动员基本信息录入,竞赛成绩处理及公告,成绩统计.信息查询等事务处理功能。根据学校田径运动会的一般进程,本系统分为数据修改、查询、删除、统计等四个工具模块来完成所期望的功能。依据关系型数据库理论设计数据库的结构。使用该系统可以极大地减小工作人员的劳动量,同时还可大大提高工作效率、可靠性和正确性。本次我会使用C语言来进行校运动会管理系统程序的编写,同时也作为本学期的c语言课程设计。下面我会简单的谈谈本次课程设计使用的一些方法。

    利用单链表结构实现学生成绩管理,深入了解数据库管理的基本功能,掌握c语言中的结构体、指针、函数(系统函数、自定义函数)、文件操作等知识。
    充分运用学过的各种C语言知识,同时加深对c语言的理解,更深入地接触c语言的难点知识,如指针变量作函数参数、函数值为指向结构体的指针以及单链表结构应用等
    掌握c语言的编程和调试的基本技能
    掌握利用c语言进行简单软件设计的基本思路和方法
    提高运用c语言解决实际问题的能力
    掌握书写实验设计说明文档的能力

    第一章 概述1.1 课程设计目的与要求为了迎接校运动会的到来,为了能够更好地展现运动健儿的风姿,为了更加客观的评定运动员的成绩,为了更加直观的了解到每个运动员的运动水平,我小组建立运动会管理系统,通过这个系统,用户能够实时查询运动员的相关信息、裁判员的基本信息,并且能够通过这个系统查询运动会项目信息,系统管理员也可通过该系统更新运动员的相关成绩体现比赛的公开、公正、公平的原则。同时巩固已学习的内容,复习程序设计和上机调试的基本方法方法。通过学习一个综合程序的设计与编写,使学生能够在较短的时间内掌握综合程序设计的基本步骤和方法。通过学习课本上的习题,举一反三,学会构建程序的柜架以及部分常用的算法代码的收发室。在加强的基础上,动手两个程序的完整设计与编写。
    1.1.1 题目要求
    建立n个结点(结点数据域的值由键盘输入)构成的单链表
    统计某学院的所有比赛项目数,查找所有名次为第一次的结点记录并输出
    删除指定比赛的所有结点
    设计校际运动会管理系统,实现学校、运动员信息和运动项目的录入,比赛结果的输入,各个学校比赛结果的查询,生成团体总分报表,查看参赛学校信息和比赛项目信息。要求功能选择用菜单实现

    1.1.2 系统要求
    基本信息输入:输入学校,运动员基本信息
    查询运动员的参赛项目和获取名次
    学院名称的记录
    运动员个人相关信息

    1.2 选题内容使用一个单链表建立一个校运动会项目管理表,每个记录包括:学院名称,比赛项目和名次。
    1.3 设计过程通过对题目以及相关要求做了简单分析,然后通过上网搜寻资料完成了整体的大纲设计。引用《C语言》,谭浩强 等编着,清华大学出版社;《C++面向对象程序设计教程》,郑莉 董渊 何江舟编着,清华大学出版社;
    1.4 开发环境本运动会管理系统是在Visual C++6.0的环境下设计和调试的。

    第二章 需求分析建立运动员信息系统,包括运动员、裁判员以及运动信息的成绩管理,运动员信息为编号、姓名、身份信息、参加的比赛项目等;姓名、身份信息、运动会信息包含各个比赛项目的信息、、比赛成绩等。
    运动会作为全校的盛会,受到学生与校领导的广泛关注,为了体现信息公开化,保证比赛的公平,我编写此运动会信息管理系统,为了给运动会的负责人一些便利。其主要功能如下:
    输入功能
    可以从键盘中一次性输入多条信息例如学院名称,比赛项目等,还有
    1:输入运动会各院各比赛项目的比赛结果 2:统计某学院的所有比赛项目数 3.查找某院所有的比赛结果 4.查找取得各比赛项目第一的学院信息 5.查找某个比赛项目各院的排名情况 6.删除指定比赛项目的信息 7.删除指定院系的参赛信息 8.修改某学院的比赛结果 9.增加比赛信息输出功能
    可以将运动员以及比赛信息输出。
    循环功能
    菜单可以多次操作,返回菜单,可以根据个人需要再次进行信息查询
    第三章 系统设计3.1 总体设计
    3.2 详细设计该系统总共分为2个模块,分别为运动员信息管理、、比赛信息查询;其中系统主要功能体现在运动员信息管理模块;该系统主要功能由以下各函数实现。
    3.2.1 系统主要函数void Welcome();Ath* Create_Athlete();void Output_Athlete(Ath *head);Ath* Add_Athlete(Ath*head);void Find_Athlete_num(Ath*head);Ath* Updata_Athlete_num(Ath*head);void Find_Athlete_name(Ath*head);Re* Create_Referee();void Output_Referee(Re* head);void Input_Match_Information();Ath *SortLinkedlist_Athlete(Ath *head);void Output_Match_Information();Ath *Insert(Ath *head,Ath *pNode);void Output_Match_Name();
    3.2.2 模块1:运动员信息管理系统由Create_Athlete函数创建运动员链表信息,返回链表头指针,可以实现的功能,如:
    1:输出全部运动员信息;调用Output_Athlete函数,从Menu函数中接收链表头指针,从首至尾输出运动员的所有信息。
    2:增加运动员信息;调用Add_Athlete函数,从Menu函数中接收链表头指针,并且将需要链接到链表中的数据加入链表尾部,最后返回链表头指针;。
    3:按号码查运动员信息;调用Find_Athlete_num函数,从Menu函数中接收链表头指针,并从键盘录入所需要查询的运动员的号码信息,将其与链表中的数据进行数据对比,如果查询到与之相符的数据,将其输出,否则输出“查无此人”。
    4:按姓名查询运动员信息;调用Find_Athlete_name函数,从Menu函数中接收链表头指针,并从键盘录入所需要查询的运动员的姓名信息,将其与链表中的数据进行数据对比,如果查询到与之相符的数据,将其输出,否则输出“查无此人”。
    5:按号码修改运动员信息;调用Updata_Athlete_num函数,从Menu函数中接收链表头指针,并从键盘录入所需要查询的运动员的号码信息,将其与链表中的数据进行数据对比,如果查询到与之相符的数据,将其输出,并重新录入相关信息,返回链表头指针。
    6:按姓名修改运动员信息;调用Updata_Athlete_name函数,从Menu函数中接收链表头指针,并从键盘录入所需要查询的运动员的姓名信息,将其与链表中的数据进行数据对比,如果查询到与之相符的数据,将其输出,并重新录入相关信息,返回链表头指针。
    7:按号码删除运动员信息;调用Delete_Athlete函数,从Menu函数中接收链表头指针,并从键盘录入所需要查询的运动员的号码信息,将其与链表中的数据进行数据对比,如果查询到与之相符的数据,将其删除,否则输出“查无此人”。
    3.2.3 模块二:比赛信息查询8:输出全部比赛项目;调用Output_Match_Information函数,从Menu函数中接收链表头指针,从首至尾输出运动员的所有信息。
    9:输出单项比赛项目;调用Find_Single_Match_Information函数,从Menu函数中分别接收运动员链表和裁判员链表的头指针,再由Find_Single_Match_Information函数嵌套调用Output_Match_Name函数,输出所有的运动项目供用户选择,获取运动项目信息后嵌套调用Output_SingleMatch_AthleteInformation(Ath*head,char NAME[])函数和Output_SingleMatch_RefereeInformation(Re*head,char NAME[])函数,分别输出参与该项运动的运动员和裁判员,由Find_Single_Match_Information函数体输出比赛时间和地点。
    第四章 运行与调试输入指令进人操作页面

    录入比赛结果

    比赛信息查询



    第六章 总结本运动会管理系统是在Visual C++6.0的环境下设计和调试的。经过调试证明:

    本系统能满足学校运动会信息管理的需求,在录入的运动员信息和比赛项目信息数据准确的情况下,就能保证结果准确。不需要反复核对,减少了大量重复操作
    软件功能齐全,基本能满足学校运动会各种信息的管理,能够保证实时的数据处理,满足用户随时信息查询的需求
    由于水平和时间有限,本系统可能还存在不足之处,欢迎各位读者和同行提出批评意见和建议
    0 评论 1 下载 2019-12-24 16:30:36 下载需要6点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端ASP.NET和Sql Server实现的读书平台网站

    1 课程设计目的综合运用软件工程思想、面向对象分析和设计方法、ASP.NET、数据库等基础知识,完成一个B/S架构的Web应用程序,掌握应用ASP.NET技术开发中小型网站的相关知识和技术。
    2 课程设计内容针对一个咸鱼读书网系统项目需求,利用数据库管理系统(Microsoft Sql Server 2012),构建项目数据库系统。利用 Visual Studio 集成开发环境,采用ASP.NET技术、C#语言、WEB Forms窗体设计技术、LINQ数据访问技术、三层架构等,完成系统界面设计和功能开发,并对系统进行功能测试。
    3 课程设计工具和平台
    Microsoft Sql Server 2012
    Microsoft Visual Studio 2013
    Windows 7操作系统
    PC机一台
    实验/课程设计项目指导书和相关参考书籍,网络资源等

    4 项目开发步骤逻辑层的逻辑判断和数据层的部分判断。大致有用户登录信息的匹配,用户注册是否重复,用户留言是否多次对同一本留言,按时间或者评分对图书的排序,评分的计算方法,留言内容的写入。
    一开始的时候只想到数据层访回图书类组给逻辑层,但是没想到当查询数量为空时的返回值,所以当时我就走去在数据层自己写几个关于结果为空时的返回函数,这也是分工前对自己的需求不明确导致后来大家都有点乱和耽误了进度。
    4.1 需求分析(功能模块分析与数据库设计)4.1.1 系统功能分析从实体类中得知类的类名和有关的数据类型,完成以下逻辑功能。
    当进入页面的导航栏有三个有关按序查书的功能


    读书:按数据库的默认查询排序
    最新书籍:按图书的上传时间排序(由大到小)
    精彩书籍:按图书的评分排序(由高到低)

    其中首页中的图书显示也是根据这两个排序取靠前几个来完成展示:最新书籍的六本流水形式展示的图书是按照最新书籍的类组的前六个类组显示,同理,精彩图书则按照精彩书籍的类组的前三个类组显示。
    用户登录与留言评分
    在查询书本信息之前需要登录用户,评论的信息将会存到一个表中,如果重复评论打分一本书则会出现相应的提示。

    图书信息

    通过页面反馈ISBN码进行图书信息查询,获得图书类,图片显示和作品简介都是以文件路径的形式在数据库储存,所以获取之后还要进行一番读文件流。

    按需查询书籍
    通过LINQ进行模糊查询,自动适应书名、作者或者ISBN的关键字查询功能。

    4.1.2 数据库和表设计建立构建数据库:主要有书籍信息表,留言表和用户表。

    书籍信息表:书名,作者,出版社,时间,页数,价格,ISBN,图片地址,评分,简介地址。



    字段名
    数据类型
    备注




    BookName
    varchar(50)
    主键


    Writer
    varchar(50)



    PublishingHouse
    varchar(50)



    Time
    date



    Page
    int



    price
    float



    ISBN
    char(15)



    Photo
    varchar(500)



    Score
    float



    Introduction
    varchar(500)



    留言表:有ISBN码标识所留言的书本,留言板会显示用户名,留言信息,时间和打分分数,最后在设置一个自增的number,如果没有这个自增number作为主键。起初使用UserID为主键,可能所有书都存在都一表中,所以写留言到数据库留言表的时候,会发生主键冲突,所以设置这个自增量number。



    字段名
    数据类型
    备注




    ISBN
    char(40)



    UserID
    char(5)



    TextContent
    char(100)



    PostTime
    date



    Score
    float



    number
    int
    主键



    用户表:用户的账号和密码,其中可填写Email。



    字段名
    数据类型
    备注




    UserID
    char(5)
    主键


    PassWord
    char(15)



    Email
    char(20)
    允许为空



    在最后一天整合代码时发生一个关于图片的路径的问题,因为我在逻辑层写函数使用GridView控件调试数据,在GridView中图片路径使用“~\img\xxxx.jpg”带有波浪号形式的路径是可以在GridView中正确显示相对路径的图片,但在前端的src上就显示不了,得使用“\img\xxx.jpg”去掉“~”的形式才能正确找到相对路径的图片。
    数据库导入关系和各表的主键设计

    4.2 系统设计与实现4.2.1 用户逻辑的实现用户登录与注册的信息判断(ID和密码匹配,注册账号不重复)。
    从数据库中通过LINQ 在表中查询是否存在匹配的信息,返回return或者false用户处理信息。相关代码如下:
    public class UserOperation{ //登录操作 public bool Sign_in(Customer register) { UserData user = new UserData(); //判断登录是否成功 if (user.JudgeUser(register)) { return true; } else { return false; } } //注册操作 public bool Sign_up(Customer register) { UserData user = new UserData(); //账号或者密码不能为空 if(String.IsNullOrEmpty(register.UserID) || String.IsNullOrEmpty(register.PassWord)) { return false; } //当前账号不存在时 if (user.JudgeRegister(register)) { user.Add(register); return true; } else { } }
    4.2.2 图书排序的实现图书的排序(最新图书和精彩图书)
    //时间比较int CompareTime(BookMessage a, BookMessage b){ return b.Time.CompareTo(a.Time);}//评分比较int CompareScore(BookMessage a,BookMessage b){ return b.Score.CompareTo(a.Score);}
    4.2.3 模糊查询的实现模糊查询

    相关代码如下:
    //模糊查询(ISBN,书名,作者)public IList<BookMessage> Fuzzy_Search(string text){ List<BookMessage> search_books = new List<BookMessage>(); //定义书本数组 //根据书本的ISBN、书名、作者 关键字 进行查询 var result = from r in BookDB.Book where (r.ISBN.Contains(text)) || (r.BookName.Contains(text)) || (r.Writer.Contains(text)) select r; foreach(var r in result) { BookMessage bookmessage = new BookMessage(); bookmessage.ISBN = r.ISBN; //ISBN bookmessage.BookName = r.BookName; //书名 bookmessage.Writer = r.Writer; //作者 bookmessage.Time = r.Time; //上传时间 bookmessage.Page = r.Page; //页数 bookmessage.PublishingHouse = r.PublishingHouse; //出版社 bookmessage.Price = (float)r.price; //价钱 ??(不强转float报错)?? bookmessage.Photo = r.Photo; //书本图片路径 bookmessage.Introduction = r.Introduction; //简介 bookmessage.Score = (float)r.Score; //评分默认为0 search_books.Add(bookmessage); //增加这个书本到数组 } return search_books; //返回书本BookMessage的数组}
    4.2.4 留言评分的实现发送留言以及分数计算

    相关代码如下:
    //发送留言public void PostLWord(LWord lword){ string LwordContent = lword.Leave_word; float LwordScore = lword.Score; string LwordISBN = lword.Getbook.ISBN; string LwordUserID = lword.Getcustomer.UserID; string LwordEmai = lword.Getcustomer.Email; DateTime LwordPostTime = new DateTime(); LwordPostTime = DateTime.Now; (new UserData()).PostLeaveWord(lword); (new BookData()).Average_Score((new BookData()).GetBook(LwordISBN)); //更新书本评分}//评分计算public void Average_Score(BookMessage book){ var result = from r in BookDB.LeaveWord where r.ISBN == book.ISBN select r; float sum = 0; //总分 float aver; //平均分 foreach(var r in result) { sum = sum + (float)r.Score; } aver = sum / (result.Count()); //算出平均分数 //找出图书 var result_book = from r in BookDB.Book where r.ISBN == book.ISBN select r; foreach(Book r in result_book) { r.Score = aver; //修改评分 } BookDB.SubmitChanges();}
    5 系统运行结果及测试分析成功完成咸鱼读书网系统的开发,并对系统进行了功能测试,系统运行和测试结果如下:

    留言系统能够正确录入数据库,但是时间获取失败。
    按需查询排序能够正确显示:

    原本打算读取文本在逻辑层完成,但是be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端实力原因在相对路径问题上出现些解决不了的问题,在逻辑层的相关测试代码如下:
    // 读取书本简介文本转换string类型public string GetIntroductionByISBN(string isbn){ string content = ""; BookMessage getbook = (new BookData()).GetBook(isbn); // 获取书本信息 string filepath = getbook.Introduction; // 获取文本路径 using (FileStream fs = new FileStream(filepath, FileMode.open, FileAccess.Read)) { interface fsLen = (int)fsLen.Length; byte[] heByte = new byte[fsLen]; int r = fsLen.Read(heByte, 0, heByte.Length); content = System.Text.Encoding.UTF8.GetString(heByte); } return content; }protected void Button1_Click(object sender, EventArgs e){ BookOperation introduction = new BookOperation(); string i = introduction.GetIntroductionByISBN("9787510862885"); Response.Write(i);}
    不知道出于什么原因,相对路径是在IIS的路径下,但当这些代码在.aspx中写的时候,便能正确访问相对路径,最终我们将代码写在aspx以实现功能,其原因还在探讨。

    6 总结和展望这次的ASP.NET程序设计实训,虽然时间比较紧凑,却让我所学到了很多实际运用的技能和拓展了很多课外的知识,特别是我第一次用三层架构形式小组合作,虽然在结合功能那天我们出现了一些因为沟通的漏缺和主键的问题的Bug,但是我们都积极修改代码一起合作将网站以最好的形式展现,在修改的时候更能发现小组合作的重要性,只要沟通理解正确,他们在改前端或数据库的同时我只要知道哪个值需求有更改就去改哪个值和返回什么值,在这种合作的形式下很多Bug都修好了。
    虽然这次的实训实现的功能未能如期实现,例如用户的收藏图书功能和管理员增删改图书的功能,因为这些代码在合并时都出现未能及时解决的Bug,这也是一种遗憾未能将我们的读书网以更好的形式展示,但是从中我也体会到合作成员之间明确的需求沟通重要性,在项目开始之前我们必须清楚自己需要什么参数,需要得到什么类型的值,需要返回什么类型的值等等。这些本来可以避免的问题最终还是出现了,经一事长一智,我相信通过本次三层架构的小组合作,在以后的合作实训项目会变得更好更清楚自己需要什么自己要做什么。
    1 评论 33 下载 2019-03-19 10:28:59 下载需要15点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端QT和websocket协议的多线程文件传输

    一、目的与要求
    做两个程序,实现文件收发
    发送端放两个按钮,点击后打开电脑目录选择所要传输的文件,选好以后,把文件名和路径显示在界面上,点击第二个按钮,把文件传到远程机器(或者虚拟机)上由接收端接收
    编写一接收端,把文件接收下来,存进指定的某个目录里
    要能测试通过三个发送端同时发100M的文件,接收端能分别接收
    使用多线程实现

    二、工具/准备工作
    Qt开发环境
    websocket传输协议库
    Win10_x64

    三、分析UI界面设计,使用qtdesigner工具,设计界面如下:
    Server端

    Client端


    多线程实现
    Qt中提供了创建线程的基类,并且新创建dialog默认为多线程,利用此特性,可以实现通过创建多个dialog从而实现多个client与服务器同时传输文件。
    文件传输协议
    使用Websocket协议,实现客户端与服务端的长连接,并且可以双方相互主动推送文本消息或文件流。
    四、实现步骤
    创建项目
    编写客户端主线程程序,为按钮添加创建窗口消息相应事件



    子线程程序


    文件传输协议代码
    /********************************************************************************************************************************************************/#include "sslechoclient.h"#include <QtCore/QDebug>#include <QtWebSockets/QWebSocket>#include <QCoreApplication>#include <iostream>#include <QDebug>#include <QFile>#include <QJsonObject>#include <QJsonDocument>#include <QMessageBox>#include <QTextStream>#include <QPushButton>#include <QFileInfo>using namespace std;QT_USE_NAMESPACE//! [constructor]SslEchoClient::SslEchoClient(const QUrl &url, QObject *parent) : QObject(parent){ ssl_dia.show(); QCoreApplication::processEvents(); connect(&m_webSocket, &QWebSocket::connected, this, &SslEchoClient::onConnected); typedef void (QWebSocket:: *sslErrorsSignal)(const QList<QSslError> &); connect(&m_webSocket, static_cast<sslErrorsSignal>(&QWebSocket::sslErrors), this, &SslEchoClient::onSslErrors); m_webSocket.open(QUrl(url));}void SslEchoClient::onConnected(){ m_webSocket.sendTextMessage(QStringLiteral("Hello, world! Server,I'am client!")); connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &SslEchoClient::onTextMessageReceived); connect(ssl_dia.m_pushButton, &QPushButton::clicked,this, &SslEchoClient::sendMessage); connect(ssl_dia.m_pushButton_2, &QPushButton::clicked,this, &SslEchoClient::sendFile);}void SslEchoClient::onTextMessageReceived(QString message){ ssl_dia.m_textEdit->setPlainText(message);}void SslEchoClient::onSslErrors(const QList<QSslError> &errors){ Q_UNUSED(errors); // WARNING: Never ignore SSL errors in production code. // The proper way to handle self-signed certificates is to add a custom root // to the CA store. qDebug() << "ssl Error!"; m_webSocket.ignoreSslErrors();}void SslEchoClient::sendMessage(){ QString message = ssl_dia.m_textEdit->toPlainText(); m_webSocket.sendTextMessage(message);}void SslEchoClient::sendFile(){ try{ QString path = QFileDialog::getOpenFileName(&ssl_dia, tr("Select File To Send"),".",tr("File(*)")); if(path.length()<1) return; QFileInfo info(path); QString file_name = info.fileName(); //文件发送消息标记协议 m_webSocket.sendTextMessage("f:" + file_name); QFile file(path); if(!file.open(QIODevice::ReadOnly)) { qDebug() << "Can't open file for writing"; return; }// out.setVersion(QDataStream::Qt_5_8); qDebug() << "read"; QByteArray byte = file.readAll(); m_webSocket.sendBinaryMessage(byte); qDebug() << "send"; file.close(); }catch(exception e){ e.what(); }}

    服务端消息发送预处理程序
    /********************************************************************************************************/#include "sslechoclient.h"#include <QtCore/QDebug>#include <QtWebSockets/QWebSocket>#include <QCoreApplication>#include <iostream>#include <QDebug>#include <QFile>#include <QJsonObject>#include <QJsonDocument>#include <QMessageBox>#include <QTextStream>#include <QPushButton>#include <QFileInfo>using namespace std;QT_USE_NAMESPACE//! [constructor]SslEchoClient::SslEchoClient(const QUrl &url, QObject *parent) : QObject(parent){ ssl_dia.show(); QCoreApplication::processEvents(); connect(&m_webSocket, &QWebSocket::connected, this, &SslEchoClient::onConnected); typedef void (QWebSocket:: *sslErrorsSignal)(const QList<QSslError> &); connect(&m_webSocket, static_cast<sslErrorsSignal>(&QWebSocket::sslErrors), this, &SslEchoClient::onSslErrors); m_webSocket.open(QUrl(url));}void SslEchoClient::onConnected(){ m_webSocket.sendTextMessage(QStringLiteral("Hello, world! Server,I'am client!")); connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &SslEchoClient::onTextMessageReceived); connect(ssl_dia.m_pushButton, &QPushButton::clicked,this, &SslEchoClient::sendMessage); connect(ssl_dia.m_pushButton_2, &QPushButton::clicked,this, &SslEchoClient::sendFile);}void SslEchoClient::onTextMessageReceived(QString message){ ssl_dia.m_textEdit->setPlainText(message);}void SslEchoClient::onSslErrors(const QList<QSslError> &errors){ Q_UNUSED(errors); // WARNING: Never ignore SSL errors in production code. // The proper way to handle self-signed certificates is to add a custom root // to the CA store. qDebug() << "ssl Error!"; m_webSocket.ignoreSslErrors();}void SslEchoClient::sendMessage(){ QString message = ssl_dia.m_textEdit->toPlainText(); m_webSocket.sendTextMessage(message);}void SslEchoClient::sendFile(){ try{ QString path = QFileDialog::getOpenFileName(&ssl_dia, tr("Select File To Send"),".",tr("File(*)")); if(path.length()<1) return; QFileInfo info(path); QString file_name = info.fileName(); //文件发送消息标记协议 m_webSocket.sendTextMessage("f:" + file_name); QFile file(path); if(!file.open(QIODevice::ReadOnly)) { qDebug() << "Can't open file for writing"; return; }// out.setVersion(QDataStream::Qt_5_8); qDebug() << "read"; QByteArray byte = file.readAll(); m_webSocket.sendBinaryMessage(byte); qDebug() << "send"; file.close(); }catch(exception e){ e.what(); }}
    五、测试服务器窗口

    客户端主程序窗口

    客户端简历连接后窗口

    建立多个线程

    选择发送文件

    文件发送成功

    六、总结
    熟悉了网络传输协议WEBSOCKET,该协议可以在客户端与服务器之间建立长连接,并且可以双方互发信息,相比于HTTP协议,该协议更适合用于作为如聊天工具、视频直播等数据交互的领域
    进一步熟悉了QT编程,大一的时候使用过VC编写图形化界面,相比之下,QT更简单高效,并且轻量化,个人更倾向于使用QT编程
    2 评论 22 下载 2018-10-31 10:27:43 下载需要11点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端C++的库存管理系统设计与实现

    一 需求分析1.1 总体要求运用面向对象程序设计知识,利用C++语言设计和实现一个“库存管理系统设计”,主要完成对商品的销售、统计和简单管理。在实现过程中,需利用面向对象程序设计理论的基础知识,充分体现出C++语言关于类、继承和封装等核心概念,每一个类应包含数据成员和成员函数。
    1.2 功能分析超市中商品分为四类,分别是食品、化妆品、日用品和饮料。每种商品都包含商品名称、价格、库存量和品牌等信息。
    本系统要求具备如下主要功能:
    1.2.1 商品简单管理功能
    添加功能:主要完成商品基本信息的添加
    查询功能:可按商品类别、商品名称、生产厂家、进货日期进行查询。若存在相应信息,输出所查询的信息,若不存在该记录,则提示“该记录不存在!”
    修改功能:可根据查询结果对相应的记录进行修改
    删除功能:主要完成商品信息的删除。先输入商品类别,再输入要删除的商品名称,根据查询结果删除该物品的记录,如果该商品不在物品库中,则提示“该商品不存在”

    1.2.2 进货功能按要求添加相应商品的信息到库存中。可按要求输入商品编号,商品名称,生产厂家,商品价格,商品数量,商品类别,入库时间等商品基本信息。
    1.2.3 出货功能出货时可按照商品名称查找相应商品,显示相关商品库存量等基本信息。若有库存量则输入出售数量,出售价格以及出库时间,计算销售额,利润。如果库存量不足则提示出货失败,结束出货。
    1.2.4 统计功能输出当前库存中所有商品的总数及详细信息;能统计每种商品一周时间内的销售额和利润;能统计每类商品的一周时间内的销售额和利润。输出统计信息时,要按从大到小进行排序。(根据个人能力,至少实现一种统计功能)
    二 程序设计与实现2.1 概要设计在定义商品的类别时采用了枚举类型,并定义Food=1,因此在程序中阿拉伯数字1,2,3,4即分别代表食品,化妆品,日用品,饮料这四种商品。
    系统类的关系图如下所示:

    2.1.1 系统的类层次在定义商品基本信息时采用了结构体类型,即定义了一个structGoods,其中包含类别,名称,品牌,价格,数量等信息,同时包含struct Date表示入库时间,包含enum GoodsType表示商品类别。
    定义class GoodsManage包含各成员函数进行对商品信息的管理,其中包含DisplayMainMenu(),AddGoodsInfo(),DisplayGoodsInfo(),SearchByCode()等成员函数。
    系统的类层次关系图如下图所示:


    2.1.2 主程序流程如下图所示:

    2.2 详细设计2.2.1 各类的描述商品类别
    //商品类别enum GoodsType{ Food=1, //食品 Cosmetic, //化妆品 Commodity, //日用品 Drink //饮料};
    入库时间
    //入库时间struct Date{ int year; int month; int day;};
    ((商品基本信息**
    //商品基本信息struct Goods{ string code; //商品编号 string name; //商品名称 string brand; //生产厂家 double price; //商品价格 int num; //商品数量 GoodsType type;//商品类别 Date date; //入库时间 Goods *next;};
    商品售出信息
    //商品售出信息struct SellRecord{ Goods sellGoods; //已出售的商品 int sellNum; //出售数量 double sellPrice;//出售价格 Date date; //出库日期 SellRecord *next;};
    商品管理
    //商品管理class GoodsManage{public: GoodsManage(); ~GoodsManage(){} void DisplayMainMenu(); //主菜单显示 void AddGoodsInfo(); //添加商品信息 void DisplayGoodsInfo();//浏览商品信息 void SearchByCode(); //按照商品编号搜索商品信息 void SearchByName(); //按照商品名称搜索商品信息 void SearchByType(); //按照商品类别搜索商品信息 void SearchByBrand(); //按照商品品牌搜索商品信息 void EditGoodsInfo(); //编辑商品信息 void DeleteGoodsInfo(); //删除商品信息 void SellGoodsInfo(); //出售商品信息 void SaveGoodsInfo(); //保存商品信息private: int amount; //商品量 int DeleteAmount; Goods *head; Goods *DeleteHead;};
    2.2.2 成员函数定义构造函数
    //定义构造函数GoodsManage::GoodsManage(){ amount=0; DeleteAmount=0; head=new Goods; head->next=NULL; DeleteHead=new Goods; DeleteHead->next=NULL;}
    2.主菜单显示函数
    //定义主菜单函数void GoodsManage::DisplayMainMenu(){ cout<<" ━═☆┈━═☆┈━═☆┈━═☆┈━═☆┈━═☆┈━═☆┈━═☆━═☆\n"; cout<<" ┋ ┋\n"; cout<<" ┋ 欢迎使用商品库存管理系统 ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ 【商品进货】…(a) ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ 【商品编辑】…(b) ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ 【商品删除】…(c) ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ ┋【按照编号查询】…(d) ┋\n"; cout<<" ┋ ┋ ┋\n"; cout<<" ┋ ┋【按照名称查询】…(e) ┋\n"; cout<<" ┋ 【商品查询】┋ ┋\n"; cout<<" ┋ ┋【按照类别查询】…(f) ┋\n"; cout<<" ┋ ┋ ┋\n"; cout<<" ┋ ┋【按照品牌查询】…(g) ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ 【商品出货】…(h) ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ 【商品统计】…(i) ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ 【信息保存】…(j) ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ ┋\n"; cout<<" ┋ 退出系统…(k) ┋\n"; cout<<" ┋ ┋\n"; cout<<" ━═☆┈━═☆┈━═☆┈━═☆┈━═☆┈━═☆┈━═☆┈━═☆━═☆\n"; cout<<"\n 请输入你要进行的操作编号:";}
    添加商品信息函数
    //定义添加商品信息函数voidGoodsManage::AddGoodsInfo(){ char c,c1; Goods tail=head,p; bool flag; cout<<" ☆☆☆☆☆☆现在进行商品信息的添加☆☆☆☆☆☆ "<<endl; while(tail->next!=NULL) tail=tail->next; do { flag=0; p=new Goods; cout<<"请选择商品类别:"<<endl; cout<<"1.食品 2.化妆品3.日用品 4.饮料"<<endl; cout<<"请输入相应编号:"; do { cin>>c1; if(c1>='1'&&c1<='4')//判断用户输入编号是否存在 flag=1; else { cout<<"您输入的编号不存在!"<<endl; cout<<"请选择正确的商品类别:"<<endl; } }while(flag==0);//输入编号存在时跳出循环 if(c1=='1') p->type=Food; if(c1=='2') p->type=Cosmetic; if(c1=='3') p->type=Commodity; if(c1=='4') p->type=Drink; cout<<"商品类别("<<p->type<<")"<<endl;//表示商品类别 cout<<"请输入商品编号: "; cin>>p->code; do { Goods *q=head->next; while(q!=NULL&&q->code!=p->code) q=q->next; if(q==NULL) flag=1; else { cout<<"存在该编号的货物!!!请重新输入编号:"; cin>>p->code; } }while(flag==0); cout<<"请输入商品名称:"; cin>>p->name; cout<<"请输入生产厂家:"; cin>>p->brand; cout<<"请输入商品价格:"; cin>>p->price; cout<<"请输入商品数量:"; cin>>p->num; cout<<"请输入入库时间(年/月/日):"; cin>>p->date.year>>p->date.month>>p->date.day; tail->next=p; p->next=NULL; tail=p; amount++;//商品量加一 cout<<"数据输入成功!!!想继续添加吗(y/n):"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!!!<请输入y/n>"<<endl; cout<<"数据添加成功!!!想继续输入吗(y/n):"; cin>>c; } }while(c=='y'); cout<<endl; cout<<"……信息处理完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar();}
    统计商品信息函数
    //定义商品信息浏览函数void GoodsManage::DisplayGoodsInfo(){ Goods *p=head; cout<<" ☆☆☆☆☆☆现在进行商品信息的浏览☆☆☆☆☆☆ "<<endl; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; while(p->next!=NULL) { p=p->next; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; } cout<<endl; cout<<"……信息统计完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar();}
    按照编号查找商品信息函数
    //按照商品编号查找商品信息void GoodsManage::SearchByCode(){ char c; Goods *p; bool flag; string FoundCode; cout<<" ☆☆☆☆☆☆现在进行商品信息的查找☆☆☆☆☆☆ "<<endl; do { p=head; flag=0; cout<<"请输入您要查找的商品编号:"; cin>>FoundCode; while(p->next!=NULL) { p=p->next; if(p->code==FoundCode) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; break; } if(flag==0) { cout<<"对不起,您查询的商品不存在!!!"<<endl; cout<<"您想要继续查找吗(y/n):"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!<请输入y/n>:"<<endl; cout<<"您想要继续查找吗(y/n):"; cin>>c; } } } }while(c=='y'); cout<<endl; cout<<"……信息查找完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar();}
    按照名称查找商品信息函数
    //按照商品名称查找商品信息void GoodsManage::SearchByName(){ char c; Goods *p; bool flag; string FoundName; cout<<" ☆☆☆☆☆☆现在进行商品信息的查找☆☆☆☆☆☆ "<<endl; do { p=head; flag=0; cout<<"请输入您要查找的商品名称:"; cin>>FoundName; while(p->next!=NULL) { p=p->next; if(p->name==FoundName) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; break; } if(flag==0) { cout<<"对不起,您查询的商品不存在!!!"<<endl; cout<<"您想要继续查找吗(y/n):"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!<请输入y/n>:"<<endl; cout<<"您想要继续查找吗(y/n):"; cin>>c; } } } }while(c=='y'); cout<<endl; cout<<"……信息查找完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar();}
    按照类别查找商品信息函数
    //按照商品类别查找商品信息void GoodsManage::SearchByType(){ char c; Goods *p; bool flag; int FoundType; cout<<" ☆☆☆☆☆☆现在进行商品信息的查找☆☆☆☆☆☆ "<<endl; do { p=head; flag=0; cout<<"请输入您要查找的商品类别:"; cin>>FoundType; while(p->next!=NULL) { p=p->next; if(FoundType==1&&p->type==Food) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; } else if(FoundType==2&&p->type==Cosmetic) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; } else if(FoundType==3&&p->type==Commodity) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; } else if(FoundType==4&&p->type==Drink) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; } if(flag==0) { cout<<"对不起,您查询的商品不存在!!!"<<endl; cout<<"您想要继续查找吗(y/n):"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!<请输入y/n>:"<<endl; cout<<"您想要继续查找吗(y/n):"; cin>>c; } } } }while(c=='y'); cout<<endl; cout<<"……信息查找完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); etchar();}
    按照品牌查找商品信息函数
    //按照品牌查找商品信息void GoodsManage::SearchByBrand(){ char c; Goods *p; bool flag; string FoundBrand; cout<<" ☆☆☆☆☆☆现在进行商品信息的查找☆☆☆☆☆☆ "<<endl; do { p=head; flag=0; cout<<"请输入您要查找的商品品牌:"; cin>>FoundBrand; while(p->next!=NULL) { p=p->next; if(p->brand==FoundBrand) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; break; } if(flag==0) { cout<<"对不起,您查询的商品不存在!!!"<<endl; cout<<"您想要继续查找吗(y/n):"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!<请输入y/n>:"<<endl; cout<<"您想要继续查找吗(y/n):"; cin>>c; } } } }while(c=='y'); cout<<endl; cout<<"……信息查找完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar();}
    编辑商品信息函数
    //定义编辑商品信息函数void GoodsManage::EditGoodsInfo(){ char c; Goods *p; bool flag=0; string EditCode; cout<<" ☆☆☆☆☆☆现在进行商品信息的编辑☆☆☆☆☆☆ "<<endl; do { p=head->next; flag=0; cout<<"请输入您要修改的货物编号:"; cin>>EditCode; while(p->next!=NULL&&p->code!=EditCode) p=p->next; if(p->code==EditCode) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; cout<<"确认修改吗?<y/n>"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!!<请输入y/n>:"; cin>>c; } if(c=='y') { cout<<"请输入商品名称:"; cin>>p->name; cout<<"请输入生产厂家:"; cin>>p->brand; cout<<"请输入商品价格:"; cin>>p->price; cout<<"请输入商品数量:"; cin>>p->num; cout<<"请输入入库时间(年/月/日):"; cin>>p->date.year>>p->date.month>>p->date.day; cout<<"修改成功!"<<endl; } else cout<<"取消成功!"<<endl; } if(flag==0) { cout<<"对不起,您修改的货物不存在!!"<<endl; } cout<<"您想要继续修改吗?(y/n):"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!<请输入y/n>:"<<endl; cout<<"您想要继续修改吗?(y/n):"; cin>>c; } }while(c=='y'); cout<<endl; cout<<"……信息编辑完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar();}
    删除商品信息函数
    //定义商品信息删除函数void GoodsManage::DeleteGoodsInfo(){ Goods q=head,p,*tail=DeleteHead; p=new Goods; char c; string Dename; bool flag=0; while(tail->next!=NULL) tail=tail->next; cout<<" ☆☆☆☆☆☆现在进行商品信息的删除☆☆☆☆☆☆ "<<endl; do { cout<<"请输入您要删除的商品名称:"; cin>>Dename; while(q->next!=NULL&&q->next->name!=Dename) q=q->next; if(q->next!=NULL) { flag=1; cout<<"确认删除吗?<y/n>"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!!<请输入y/n>:"; cin>>c; } if(c=='y') { p=q->next; q->next=q->next->next; tail->next=p; tail=p; tail->next=NULL; DeleteAmount++; amount--; cout<<"删除成功!!"<<endl; } else cout<<"取消成功!!!"<<endl; } if(flag==0) { cout<<"对不起,您删除的商品不存在!!!"<<endl; } cout<<"您想要继续删除吗?(y/n):"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!<请输入y/n>:"<<endl; cout<<"您想要继续删除吗?(y/n):"; cin>>c; } flag=0; q=head; }while(c=='y'); cout<<endl; cout<<"……信息删除完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar();}
    出售商品信息函数
    //定义商品出库函数void GoodsManage::SellGoodsInfo(){ int sellNum,year,month,day; doublesellPrice,sum=0.0,profit=0.0; char c; Goods *p; bool flag=0; string EditName; cout<<" ☆☆☆☆☆☆现在进行商品的出售☆☆☆☆☆☆ "<<endl; do { p=head->next; flag=0; cout<<"请输入您要出售的商品名称:"; cin>>EditName; while(p->next!=NULL&&p->name!=EditName) p=p->next; if(p->name==EditName) { flag=1; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; cout<<"确认出售吗?<y/n>"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!!<请输入y/n>:"; cin>>c; } if(c=='y') { cout<<"请输入出售的商品数量:"; cin>>sellNum; if(sellNum<=p->num) { p->num=p->num-sellNum; cout<<"请输入出售的商品价格:"; cin>>sellPrice; cout<<"请输入出货日期:"; cin>>year>>month>>day; sum=sellNum*sellPrice; profit=sellNum*(sellPrice-p->price); cout<<"此次销售额为: "<<sum<<endl; cout<<"此次利润为: "<<profit<<endl; cout<<"出货日期为:"<<year<<"/"<<month<<"/"<<day<<endl; } else { cout<<"库存不足!出库失败!"<<endl; } } else cout<<"取消成功!"<<endl; } if(flag==0) { cout<<"对不起,您出售的货物不存在!!"<<endl; } cout<<"您想要继续出售吗?(y/n):"; cin>>c; while(c!='y'&&c!='n') { cout<<"指令错误!!!<请输入y/n>:"<<endl; cout<<"您想要继续出售吗?(y/n):"; cin>>c; } }while(c=='y'); cout<<endl; cout<<"……出库完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar();}
    保存商品信息函数
    //定义商品信息保存函数void GoodsManage::SaveGoodsInfo(){ Goods *p=head; cout<<" ☆☆☆☆☆☆现在进行商品信息的保存☆☆☆☆☆☆ "<<endl; ofstream output("货物信息.txt",ios::out);//定义输出文件"货物信息.txt" if(!output) { cerr<<"打开文件<货物信息.txt>失败!!!"<<endl; } output<<amount<<"\n"; cout<<setiosflags(ios::left)<<setw(10)<<"编号"<<setw(16)<<"名称"<<setw(10)<<"生产厂家"<<setw(10)<<"价格"<<setw(10)<<"商品类别"<<setw(10)<<"数量"<<setw(10)<<"入库时间"<<endl; while(p->next!=NULL) { p=p->next; output<<p->code<<"\t"<<p->name<<"\t"<<p->brand<<"\t"<<p->price<<"\t"<<p->num<<"\t"<<p->type<<"\t"<<p->date.year<<"\t"<<p->date.month<<"\t"<<p->date.day<<"\n"; cout<setiosflags(ios::left)<<setw(10)<<p-code<<setw(16)<<p->name; cout<<setw(10)<<p->brand<<setw(10)<<p->price<<setw(10)<<p->type; cout<<setw(10)<<p->num<<p->date.year<<"/"<<p->date.month<<"/"<<p->date.day<<endl; } cout<<endl; cout<<"成功将货物信息保存到<货物信息.txt>"<<endl; cout<<"……信息保存完毕……"<<endl; cout<<"……按任意键返回主菜单……"<<endl; getchar(); getchar(); output.close();//关闭输出文件}
    2.2.3 算法流程图添加商品信息函数流程如下所示:

    浏览商品信息函数流程如下所示:

    按照商品编号搜索商品信息函数流程如下所示:

    按照商品名称搜索商品信息函数流程如下所示:

    按照商品类别搜索商品信息函数流程如下所示:

    按照商品品牌搜索商品信息函数流程如下所示:

    编辑商品信息函数流程如下所示:

    删除商品信息函数流程如下所示:

    出售商品信息函数流程如下所示:

    保存商品信息函数流程如下所示:

    三 运行测试程序主菜单

    添加商品信息

    编辑商品信息

    删除商品信息

    按照编号搜索商品信息

    按照类别搜索商品信息

    按照名称搜索商品信息

    按照品牌搜索商品信息

    出售商品信息

    保存商品信息

    统计商品信息
    5 评论 82 下载 2018-10-18 22:21:00 下载需要14点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端C#和SQL SERVER的汽车配件仓储管理系统

    摘 要汽车配件信息管理网站建设是汽车配件信息进行有效管理的重要工具。本次设计以建设汽车配件信息管理网站为目标,同时结合现今对信息管理相关网站建设方面的需求,建设相关后台数据库及相应的交互性界面。
    为了实现有效率的对汽车配件信息进行管理,本论文以网站建设为主体架构,详细的介绍了汽车配件信息管理网站的需求,具体描述了整个网站的开发过程,分析了汽车配件信息管理网站的功能。并以业务流程图的形式详细的介绍了系统的各个功能的模块及各个模块的数据库表,并详细的记录了各个功能测试的情况信息。对于汽车配件管理系统迅速发展的信息化时代,通过规范、统一的网站式管理对相关信息进行整合,不仅方便了管理,而且提高了工作效率。
    本毕业设计的内容是设计并且实现一个汽车配件信息管理网站设计,用Microsoft Visual Studio作为开发工具,以SQLServer作为数据库,使用C#语言开发。该系统界面友好、操作简单,容易维护,适合公司管理者以及员工使用。
    关键词:汽车配件信息;网站式管理;MicrosoftVisual Studio;SQL Server
    AbstractThe construction site is automobile fittings information management of autoparts information to efficient management. The design of the construction ofauto parts information management website as the goal, combined with thecurrent information management related to website construction needs, theconstruction of relevant background database and the corresponding interactiveinterface.
    In order to realize the efficient management of auto parts information, thewebsite construction as the main structure, detailed introduces the auto partsinformation management needs of the site, the specific description of thedevelopment process of the entire site, analysis of the auto parts information managementfunctions of the website. And the business process diagram in the form ofdetailed description of the module and each module of the system each functionof the database table, and detailed records of each function test information.In the information age, the rapid development of auto parts management systemthrough the website management standard, unified integration of relevantinformation, not only convenient management, but also improve the workEfficiency at
    The content of this graduation design is to design and implement an autoparts information management website design, using Microsoft Visual Studio as adevelopment tool, using SQL as the database Server, using C# languagedevelopment. The system has a friendly interface, simple operation, easymaintenance, suitable for company managers and employees.
    Key words: auto partsinformation; Web site management; Microsoft Visual Studio; SQL Server
    引言随着计算机技术的快速发展,许多企业事业单位的管理都实现了办公自动化,这种自动化管理方式不仅管理简单,而且效率非常高。为了能够高效而且有效地管理汽车配件的管理信息,汽车配件经营者提出使用计算机进行汽车配件信息的管理,使汽车配件管理科学化,最大限度地减少信息损失,提高汽车配件的利益。
    使用计算机管理汽车配件相对人工记录,有很多的有点。首先,用计算机进行金额计算时速度快,可信度高。而且查询时不必要逐个查找,只需要输入相关信息就可快速得到结果。然后,汽车配件信息存储在计算机,可以作到数据的永久保存,安全可靠。最重要的是,汽车配件数据存储在计算机中,由于计算机存储容量非常大,所以清单的内容在输入电脑后,对数据的操作是非常方便的,而且避免了频繁的使用清单。
    汽车部件仓储管理已经渐渐的走向稳定发展的趋势,更加具有企业化的概念,在体制上,汽车部件仓储管理已经开始慢慢的健全它的体制,对公司人员进行培训,将业务进行熟练化,这样大大的提高了汽车部件管理在世界中的发展,并且使它的地位明显的上升,也进一步的满足了大家的需求。为了更好的发展,企业渐渐的从整体中分离开来建立自己的发展模块,不断的寻求发展模式,扩大自己的经营模式。
    本网站使用.net+Microsoft Visual Studio+SQL Server的组合,使用计算机浏览器实现了网站的基本功能,网站对汽车配件的信息进行管理,不但可以使用工程的、规范的管理过程,而且可以有效的提高了工作人员的工作效率,直观的、科学的管理汽车配件信息,进而完成公司的业务,这对汽车配件信息的管理的发展及信息化的管理具有极其重要的意义。
    第1章 绪 论1.1 论文背景1.be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端汽车配件管理的相关背景
    汽车配件管理系统的目的是为企业提供一个计算机化的管理平台,实践企业内部科学有效的管理,促进企业管理信息化,规范化,将能使管理人员从繁琐的杂务工作中解脱出来,真正从事管理工作。
    目前汽车配件销售企业大多数在其连锁店的管理还是手工进行,随着汽车配件行业的迅速发展,手工管理的种种弊端暴露无疑,给销售企业的发展带来了不必要的麻烦。为了规范企业内部管理,提高企业业务管理水平,更好的为客户服务,应采用计算机来管理汽车配件的进销存业务。
    汽车部件仓储管理已经渐渐的走向稳定发展的趋势,更加具有企业化的概念,在体制上,汽车部件仓储管理已经开始慢慢的健全它的体制,对公司人员进行培训,将业务进行熟练化,这样大大的提高了汽车部件管理在世界中的发展,并且使它的地位明显的上升,也进一步的满足了大家的需求。为了更好的发展,企业渐渐的从整体中分离开来建立自己的发展模块,不断的寻求发展模式,扩大自己的经营模式。
    2.数据管理技术
    随着互联网发展进程的加快, 信息资源网络化成为一大潮流。与传统信息资源相比, 网络信息资源在 数量、结构、内涵、类型、载体形态、分布和传播范围、控制机制、传递手段等方面都与传统信息资源有显着的差异, 呈现出许多新的特点。这些新的特点赋予网 络环境下信息资源管理许多新的内涵。网络信息资 源管理建立在新的社会基础结构即信息网络的基础之上, 适应了信息化社会信息组织和管理的需要是一个新的生长点。
    数据管理技术就是指人们对数据进行收集、组织、存储、加工、传播和利用的一系列活动的总和,经历了人工管理、文件管理、数据库管理三个阶段[4]。每一阶段的发展以数据存储冗余不断减小、数据独立性不断增强、数据操作更加方便和简单为标志,各有各的特点。其中现今就处于数据库管理为主流的阶段,节省的大量的人力资源,对于信息化网络化的现在数据库管理技术的共享性、大量数据存储显示、数据处理快速而且具有很高的安全性和完整性,其并发控制和恢复性都不会让数据轻易丢失
    3..NET技术
    ASP.NET是由微软在.NET Framework框架中所提供,开发Web应用程序的类库,封装在System.Web.dll文件中,显露出System.Web名字空间,并提供ASP.NET网页处理、扩充以及HTTP通道的应用程序与通信处理等工作,以及Web Service的基础架构。ASP.NET是ASP技术的后继者,但它的发展性要比ASP技术要强大许多。
    ASP.NET可以运行在安装了.NET Framework的IIS服务器上,若要在非微软的平台上运行,则需要使用Mono平台[2],ASP.NET在2.0版本已经定型,在.NET Framework 3.5上则加上了许多功能,像是ASP.NET AJAX、ASP.NET MVC Framework、ASP.NET Dynamic Data与Microsoft Silverlight的服务器控件等。
    很多人都把 ASP.NET 当做是一种编程语言,但它实际上只是一个由 .NET Framework提供的一种开发平台 (development platform),并非编程语言。也可认为ASP.NET是.NET组件,任何.NET语言,例如C#,可以引用该组件,创建网页或Web服务。
    为了因应云化所诱发的多作业平台集成与开发能力,微软特别开发一个新一代的 ASP.NET,称为 ASP.NET vNext,并于 2014 年命名为 ASP.NET 5,但随后于 2016 年将它更名为 ASP.NET Core,由于架构上的差异颇大,因此未来 ASP.NET 与 ASP.NET Core 将是分别发展与维护,Windows 平台的 ASP.NET 4.6 以上版本仍维持 Windows Only,但 ASP.NET Core 则是具有跨平台 (Windows, Mac OSX 与 Linux) 的能力。
    1.2 系统开发的意义随着计算机技术的快速发展,许多企业事业单位的管理都实现了办公自动化,这种自动化管理方式不仅管理简单,而且效率非常高。为了能够高效而且有效地管理汽车配件的管理信息,汽车配件经营者提出使用计算机进行汽车配件信息的管理,使汽车配件管理科学化,最大限度地减少信息损失,提高汽车配件的利益。
    使用计算机管理汽车配件相对人工记录,有很多的优点。首先,用计算机进行金额计算时速度快,可信度高。而且查询时不必要逐个查找,只需要输入相关信息就可快速得到结果。然后,汽车配件信息存储在计算机,可以作到数据的永久保存,安全可靠。最重要的是,汽车配件数据存储在计算机中,由于计算机存储容量非常大,所以清单的内容在输入电脑后,对数据的操作是非常方便的,而且避免了频繁的使用清单。
    1.3 研究现状和发展趋势1.研究现状
    现在我国的企业特别是汽车配件企业的管理水平还停留在纸介质或半自动(由电脑处理一部分数据,由人工处理一部分数据)的基础上,这样的机制已经不能适应时代的发展,因为它浪费了许多人力和物力,在信息时代这种传统的管理方式必然会被以计算机为基础的信息管理所取代。软件作为一项有力的工具,只能当此种工具,与我们的实践相结合起来的时候,才具有重大的社会价值及使用价值。因此根据企业目前实际的汽车配件管理系统情况开发一套汽车配件管理系统是十分有必要的。
    2.发展趋势
    汽车部件仓储管理已经渐渐的走向稳定发展的趋势,更加具有企业化的概念,在体制上,汽车部件仓储管理已经开始慢慢的健全它的体制,对公司人员进行培训,将业务进行熟练化,这样大大的提高了汽车部件管理在世界中的发展,并且使它的地位明显的上升,也进一步的满足了大家的需求。为了更好的发展,企业渐渐的从整体中分离开来建立自己的发展模块,不断的寻求发展模式,扩大自己的经营模式。
    通过计算机进行货物的进入和销售数量的统计,使管理者不必再为统计数量而感到烦恼,可以利用节省出来的时间全身心的投入到其他事情当中,也对管理制度进行了优化和改良,集中对零部件进行统计和分配,这样不仅减少我们使用的资源,也大大的降低了我们的劳动成本,节省了财力,使管理人员更加专心的从事管理工作,使管理制度更加合理化和规范化。
    1.4 论文的基本结构此次论文详细的介绍了汽车配件信息管理网站设计及实现的过程以及相关功能解说、研究思路、思想总结等部分。着重介绍了这个网站的设计思想、技术路线、开发平台的选择、总体框架、程序流程、本网站应实现的功能以及具体的实现方法和步骤,并且讨论类似网站存在的局限性和解决的思路。其主要基本结构如下:

    绪论,用来详细解说该系统的背景、研究意义及研究前景。
    系统开发平台的介绍,用来详细介绍该系统用到的开发工具,如Microsoft VisualStudio,SQLServer。
    第1章是需求分析,用来分析经济、技术、操作上的可行性,重点介绍系统的功能分析、业务流程图以及ER图等。
    第2章是系统设计,用来详细介绍各个模块的功能,并设计数据库,展示系统界面。
    第3章是实现部分功能的主要代码及系统的整体及相关功能测试,用来展示系统的核心代码以及展示系统测试的效果。

    第2章 系统开发工具及相关技术本章将对本次汽车配件信息管理网站的开发平台进行简要的介绍,同时介绍在开发过程中采用的一些Ajax技术。
    2.1 开发工具简介本次网站设计主要采用的是学校中通用的软件,操作系统是Windows,主要Web端和后端的开发都是在Microsoft Visual Studio中操作实现,数据库采用的是Sql Server数据库。下面将对两个软件简要介绍:
    1.Microsoft Visual Studio
    Microsoft Visual Studio(简称VS)是微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等。所写的目标代码适用于微软支持的所有平台,包括MicrosoftWindows、Windows Phone、WindowsCE、.NET Framework、.NET CompactFramework和Microsoft Silverlight。
    而Visual Studio .NET是用于快速生成企业级ASP.NET Web应用程序和高性能桌面应用程序的工具。Visual Studio包含be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端组件的开发工具(如Visual C#、Visual J#、VisualBasic和Visual C++),以及许多用于简化be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端小组的解决方案的设计、开发和部署的其他技术。
    2.Sql Server
    SQL Server一开始并不是微软自己研发的产品,而是当时为了要和IBM竞争时,与Sybase合作所产生的,其最早的发展者是Sybase[1],同时微软也和Sybase合作过SQL Server 4.2版本的研发,微软亦将SQL Server 4.2移植到Windows NT(当时为3.1版),在与Sybase终止合作关系后,自力开发出SQL Server 6.0版,往后的SQL Server即均由微软自行研发。
    Sql Server是一个关系数据库管理系统。具有易用性、适合分布式组织的可伸缩性、用于决策支持的数据仓库功能、与许多其他服务器软件紧密关联的集成性、良好的性价比等。为数据管理与分析带来了灵活性,允许单位在快速变化的环境中从容响应,从而获得竞争优势。
    维基百科给的解释是这样的,Microsoft SQL Server是由美国微软公司所推出关系数据库解决方案,最新的版本是SQL Server 2016,已经在2016年6月1日发布。 数据库的内置语言原本是采用美国标准局(ANSI)和国际标准组织(ISO)所定义的SQL语言,但是微软公司对它进行了部分扩充而成为作业用SQL(Transact-SQL)。几个初始版本适用于中小企业数据库管理,但是近年来它的应用范围有所扩展,已经触及到大型、跨国企业的数据库管理。
    2.2 .net 平台介绍.NET就是微软用来实现XML,Web Services,SOA(面向服务的体系结构service-oriented architecture)和敏捷性的技术。对技术人员,想真正了解什么是.NET,必须先了解.NET技术出现的原因和它想解决的问题,必须先了解为什么他们需要XML,Web Services 和 SOA。技术人员一般将微软看成一个平台厂商。微软搭建技术平台,而技术人员在这个技术平台之上创建应用系统。从这个角度,.NET也可以如下来定义:.NET是微软的新一代技术平台,为敏捷商务构建互联互通的应用系统,这些系统是be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端标准的,联通的,适应变化的,稳定的和高性能的。从技术的角度,一个.NET应用是一个运行于.NET Framework之上的应用程序。(更精确的说,一个.NET应用是一个使用.NET Framework类库来编写,并运行于公共语言运行时Common Language Runtime之上的应用程序。)如果一个应用程序跟.NETFramework无关,它就不能叫做.NET程序。比如,仅仅使用了XML并不就是.NET应用,仅仅使用SOAPSDK调用一个Web Service也不是.NET应用。.NET是be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端Windows操作系统运行的操作平台,应用于互联网的分布式。
    2.3 相关技术1.B/S结构
    B/S结构是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。目前大多数应用软件系统都是Client/Server形式的两层结构,由于现在的软件应用系统正在向分布式的Web应用发展,Web和Client/Server 应用都可以进行同样的业务处理,应用不同的模块共享逻辑组件;因此,内部的和外部的用户都可以访问新的和现有的应用系统,通过现有应用系统中的逻辑可以扩展出新的应用系统。
    根据实际开发的需要,位置信息管理网站设计的开发中选择了B/S结构开发web应用程序,通过浏览器访问服务器的的方式实现远程操作和数据共享。
    2.Ajax技术
    AJAX即“AsynchronousJavaScript and XML”(异步JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。Ajax的概念由杰西·詹姆士·贾瑞特所提出[1]。
    传统的Web应用允许用户端填写表单(form),当提交表单时就向网页服务器发送一个请求。服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中的大部分HTML码往往是相同的。由于每次应用的沟通都需要向服务器发送请求,应用的回应时间依赖于服务器的回应时间。这导致了用户界面的回应比本机应用慢得多。
    与此不同,AJAX应用可以仅向服务器发送并取回必须的数据,并在客户端采用JavaScript处理来自服务器的回应。因为在服务器和浏览器之间交换的数据大量减少(大约只有原来的5%)来源请求,服务器回应更快了。同时,很多的处理工作可以在发出请求的客户端机器上完成,因此Web服务器的负荷也减少了。
    类似于DHTML或LAMP,AJAX不是指一种单一的技术,而是有机地利用了一系列相关的技术。虽然其名称包含XML,但实际上数据格式可以由JSON代替,进一步减少数据量,形成所谓的AJAJ。而客户端与服务器也并不需要异步。一些be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端AJAX的“派生/合成”式(derivative/composite)的技术也正在出现,如AFLAX。
    第3章 系统需求分析3.1 系统业务描述根据相应的需求及对应功能的完善实现,汽车配件仓储管理网站设计业务流程主要包括以下几个方面:

    一级管理,通过登录界面,判定是一级管理员后,进入一级管理界面。可以查看配件信息,供应商信息,需求商信息,二管理员信息以及二级管理员的操作日志。并且可以通过切换不同的界面,可以对相应的信息进行添加,删除,修改各个部分的信息。在汽车配件信息界面,可以通过链接查看该零件的生产单位等多种操作。
    二级管理员管理,通过登录界面,判定是二级管理员后,进入二级管理界面。二级管理界面可以查询配件信息以及需求商的基本信息。主要进行入库/出库操作而且额外可以添加需求商户。

    至此,本系统业务流程结束。
    3.2 可行性分析可行性分析应从经济可行性,技术可行性和操作可行性三个方面考虑,以下是对本系统具体的可行性分析。
    1.经济可行性
    利用本校现有的校园网、计算机及配套设备就可使用本系统进行配件的信息管理;对系统的使用都是简单的操作;软件系统由本人在指导老师的帮助下完成的,不要任何费用。
    2.技术可行性
    系统采用B/S架构,前台采用html+css+js编码实现页面的可视化与交互性,后端使用C#实现对SQL Server数据库进行数据的存储、修改、删除等操作,该数据库具有方便、灵活的特点,适应该系统的开发。本系统要求的硬件标准不高,一般的硬件设备足够运行系统。
    3.操作可行性
    使用汽车配件仓储管理系统网站,只需要输入网址就能进入登录界面。然后就是管理首页,主要的管理功能是一级管理员对配件信息,供应商信息,需求商信息,二级管理员信息的增、删、改、查以及对操作日志的查看。其次功能是二级管理员的查询,入库、出库操作以及添加新的需求商功能,实用简单。
    综上所述,开发汽车配件仓储管理网站设计在经济上、技术上、操作上都是可行的。
    3.3 功能需求分析汽车配件仓储信息管理网站设计的使用和相关者有:

    一级管理员:一级管理员对配件信息,供应商信息,需求商信息,二级管理员信息的增、删、改、查以及对操作日志的查看。
    二级管理员:二级管理员能够对配件信息进行查询所搜,主要进行入库、出库操作。同时,可以对需求商的信息进行查询,得到是否有需求商正等待发货而进行出库,也可以添加新的需求商用户。

    汽车配件仓储信息管理网站设计应该满足如下功能需求:
    管理员登陆:能让管理员方便的使用密码登陆系统,从而进行一系列的操作。

    一级管理员可以对配件信息进行增、删、改、查,并且由该配件信息获取其生产单位的相关信息。
    一级管理员对供应商的信息管理。
    一级管理员对二级管理员的信息管理。
    一级管理员对需求商的信息管理。
    一级管理员对日志的查看。
    二级管理员进行出库、入库操作。
    二级管理员添加新的需求商。

    3.4 分析模型3.4.1 业务流程图业务流程图(Transaction Flow Diagram, TFD)就是用一些规定的符号及连线来表示某个具体业务处理过程。是一种物理模型。业务流程图主要是描述业务走向,比如说去ATM机取款,首先得打开自助银行的门走进去,然后找到 一台ATM机,再插入卡输入相应的密码,最后钱才能出来被你取走(当然需要余额充足)。利用它可以帮助分析人员找出业务流程中的不合理流向,业务流程图描述的是完整的业务流程,以业务处理过程为中心,一般没有数据的概念。
    1.数据管理
    数据管理业务流程图如图3-1所示:

    2.设备管理
    设备管理业务流程图如图3-2所示:

    3.汽车配件信息查看
    汽车配件信息查看业务流程图如图3-3所示:

    3.4.2 实体模型图(ER图)E-R图也称实体-联系图(EntityRelationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型。
    系统总ER图如图3-4所示:

    管理员实体用来存储管理员的基本信息,其ER图如图3-5所示:

    供应单位实体用来存储供应单位的相关信息,其ER图如图3-6所示:

    需求单位实体用来存储需求单位的相关信息,其ER图如图3-7所示:

    汽车配件实体存储汽车配件的相关信息,其ER图如图3-8所示:

    操作日志实体存储相关操作的信息,其ER图如图3-9所示:

    3.4.3 系统用例图1.总用例图
    总用例图如图3-10所示:

    2.子用例图
    一级管理员配件信息管理如图3-11所示:

    二级管理员配件信息管理如图3-12所示:

    第4章 系统设计4.1概要设计系统的各部分功能模块独立开发、调试,然后利用系统集成的方法将各个模块信息传入数据库。各个功能模块采用事件驱动的方式 与应用程序进行交互,系统部分程序的应用执行是在后台进行的。汽车配件仓储管理网站设计的系统总体结构设计如图4-1所示。

    各模块的结构:
    1.二级管理员管理模块:
    该模块有如下功能:二级管理员可添加需求商信息,并且可以对汽车配件进行出库入库操作。其模块功能图如图4-2所示:

    2.一级管理员管理模块:
    该模块有如下功能:一级管理员可对该模块进行管理,可以查看所有汽车配件,供应商,需求商,管理员的信息,并且可以对信息进行添加,修改,删除,而且可以查看日志信息。其模块功能图如图4-3所示:

    4.2 数据库设计通过以上的对网站的综合分析,本网站选择SQL Server作为网站的数据库,数据库中包括管理员信息、供应商基本信息、需求商基本信息、二级管理员信息、操作日志信息。
    管理员信息表



    表名:Users
    备注:管理员信息表







    字段名称
    数据类型
    自增主键
    允许为空
    默认值


    UserId
    int





    UserName
    nvarchar(50)





    Password
    nvarchar(50)





    Type
    nvarchar(50)





    LoginTime
    Datetime





    Department
    nvarchar(50)





    汽车配件信息表



    表名:CarParts
    备注:汽车配件信息表







    字段名称
    数据类型
    自增主键
    允许为空
    默认值


    PartId
    int





    PartName
    nvarchar(50)





    FromDepartId
    nvarchar(50)





    Num
    nvarchar(50)





    InTime
    Datetime





    UnitPrice
    decimal(18, 2)





    Quantity
    int





    供应单位信息表



    表名: Supplies
    备注:供应商信息表







    字段名称
    数据类型
    自增主键
    允许为空
    默认值


    Id
    int





    Name
    nvarchar(50)





    Principal
    nvarchar(50)





    Address
    nvarchar(50)





    Phone
    nvarchar(50)





    Ways
    nvarchar(50)





    Num
    nvarchar(50)





    供应单位信息表



    表名: NeedMerchant
    备注:需求商信息表







    字段名称
    数据类型
    自增主键
    允许为空
    默认值


    Id
    int





    Num
    nvarchar(50)





    Name
    nvarchar(50)





    Principal
    nvarchar(50)





    Phone
    nvarchar(50)





    IsDeliver
    bit





    Address
    nvarchar(50)





    NeedPartName
    nvarchar(50)





    NeedNum
    int





    操作日志信息表



    表名: Log
    备注:操作日志信息表







    字段名称
    数据类型
    自增主键
    允许为空
    默认值


    Id
    int





    Operator
    nvarchar(50)





    Time
    Datetime





    Details
    Nverchar(1000)





    Type
    nvarchar(50)





    IP
    nvarchar(50)





    4.3 功能模块设计流程图位置信息管理网站设计其功能已详细介绍,本节将详细介绍各个功能模块的设计流程图。其中登录界面程序流程图,如图4-9所示:

    网站中很多功能都涉及到修改数据,修改数据信息主要是实现前端数据与后台数据库的交互,以ID为判断条件将修改后的信息用SQL语句调用数据库修改相应的数据,刷新数据库及相应页面,显示数据库的信息。修改数据流程图如图4-11所示,

    删除数据信息,实现主要是根据删除按钮或是全选删除按钮的点击事件获取相应的要删除信息的ID,然后根据ID利用SQL语句删除数据库中的数据,更新数据库。删除程序主要流程图,如图4-12所示:

    增加数据信息的功能主要是将表单中的数据提交到后台数据库中,在由后台对数据做相应的判断,若不符合要求,则显示增加不成功,不保存到数据库,否则将数据保存到相应数据库。增加数据信息的程序流程图,如图4-14所示:

    4.4 软件界面设计本节将系统展示位置信息管理网站设计完成后页面的完成情况,及大致的布局。其中登录界面如图4-16所示:

    第5章 系统编码与测试5.1 系统编码1.数据库连接代码
    <add name="MainConn"connectionString="server=.;database=CarParts;user=sa;pwd=0301;Max Pool Size=512;" provider Name="System.Data.SqlClient"/>
    2.登录界面核心代码
    <form> <label for="username">用户名</label> <input name="username" type="text" placeholder="请输入用户名" id="name"/> <label for="pass">密码</label> <input name="pass" type="password" placeholder="请输入密码" id="password"/> <input value="登录" id="submit" /></form>
    3.登录后台核心代码
    using System.Data;using System.Data.SqlClient;using System.Linq;using System.Text;using System.Web;using System.Web.SessionState;namespace WebApp{ /// <summary> /// LoginHandler 的摘要说明 /// </summary> public class LoginHandler : IHttpHandler, IRequiresSessionState { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; //获取用户名和密码 string name = context.Request["name"]; string password = context.Request["password"]; //获取数据库数据,放置在ds中 StringBuilder sb = new StringBuilder(); sb.AppendLine("SELECT TOP 1 UserId,UserName,Password,Type,LoginTime,Department "); sb.AppendLine("FROM Users"); sb.AppendLine("WHERE UserName = @UserName AND Password = @Password; "); SqlParameter[] pms = { new SqlParameter("@UserName",SqlDbType.NVarChar,50), new SqlParameter("@Password",SqlDbType.NVarChar,50) }; pms[0].Value = name; pms[1].Value = password; DataSet ds = DbHelperSQL.Query(sb.ToString(),pms); //判断表中是否存在数据,如果有数据则登录成功,如果没有数据,则登录失败 if (ds.Tables[0].Rows.Count > 0) { //根据判断选择进入哪个主页,无论进来的管理员或者是普通用户都记录下操作者的ID,方便记录日志 if (ds.Tables[0].Rows[0]["Type"].ToString() == "1") { context.Session["Id"] = ds.Tables[0].Rows[0]["UserId"].ToString(); context.Session["LoginTime"] = DateTime.Now.ToString(); context.Response.Write("ok1:登录成功"); } else { context.Session["Id"] = ds.Tables[0].Rows[0]["UserId"].ToString(); context.Session["LoginTime"] = DateTime.Now.ToString(); context.Response.Write("ok2:登录成功"); } } //验证失败弹出提示框 else { context.Response.Write("用户名或密码错误,请重新登录"); } } public bool IsReusable { get { return false; } } }}
    4.一级管理员首页界面前端核心代码
    <div class="easyui-layout" style="width:960px; height:800px;margin:50px auto;"> <%--采用easy-ui布局--%> <%--头部导航--%> <div data-options="region:'north',border:false" class="top_bar"> <h1>汽车仓储管理系统</h1> </div> <%--头部导航结束--%> <%--左侧的切换选择--%> <div data-options="region:'west',split:true,title:'信息总览'" class="left_nav"> <ul class="main_nv"> <li class="nv_item"><a href="javascript:void(0)" class="linkToPage" url="InfoPage/PartsInfo.aspx">配件信息</a></li> <li class="nv_item"><a href="javascript:void(0)" class="linkToPage" url="InfoPage/Supplies.aspx">供应商信息</a></li> <li class="nv_item"><a href="javascript:void(0)" class="linkToPage" url="InfoPage/NeedMerchant.aspx">需求商信息</a></li> <li class="nv_item"><a href="javascript:void(0)" class="linkToPage" url="InfoPage/Manager.aspx">管理员信息</a></li> <li class="nv_item"><a href="javascript:void(0)" class="linkToPage" url="InfoPage/Log.aspx">操作日志</a></li> </ul> </div> <%--左侧的切换选择结束--%> <%--底部标注信息--%> <div data-options="region:'south',border:false" class="bottom_bar"> <h3>此系统仅供本公司人员使用</h3> </div> <%--底部标注信息结束--%> <%--核心内容展示区域--%> <div data-options="region:'center',title:'信息管理'" class="right"> <div class="easyui-tabs" style="width:700px;height:250px;" class="right" fit="true" id="tt"> <div title="配件信息" style="padding:10px;overflow:hidden;"class="right"> <iframe src="InfoPage/PartsInfo.aspx" scrolling="no" width="100%" height="100%" frameborder="0"></iframe> </div> </div> </div> <%--核心内容展示区域结束--%></div>
    5.二级管理员首页界面核心代码
    365bet英文 <h1 class="top_title" style="margin-bottom:100px;text-align:center;">汽车配件的出库/入库</h1> <form id="form1" runat="server"> <div> <%--<asp:Button ID="btnAdd" runat="server" Text="添加" />--%><%---------------------------------需求商信息--------------------------------------------------%> <asp:GridView ID="gvNeedMer" runat="server" AutoGenerateColumns="False" DataKeyNames="Id" AllowPaging="True" OnPageIndexChanging="gvParts_PageIndexChanging"> <Columns> <asp:CheckBoxField DataField="IsDeliver" HeaderText="已发货" /> <asp:BoundField DataField="Num" HeaderText="编号" /> <asp:TemplateField HeaderText="单位名称"> <ItemTemplate> <a id="linkToPartInfoEdit" target="_blank" href="javascript:linkToPart(<%# Eval("Id") %>)"> <%#Eval("Name") %> </a> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="Principal" HeaderText="负责人" /> <asp:BoundField DataField="Address" HeaderText="地址" /> <asp:BoundField DataField="Phone" HeaderText="联系电话" /> <asp:TemplateField HeaderText="添加"> <ItemTemplate> <input type="button" id="btnAdd" value="添加"/> </ItemTemplate> </asp:TemplateField> </Columns> <%--添加分页--%> <PagerTemplate> 当前第: <%--//((GridView)Container.NamingContainer)就是为了得到当前的控件--%> <asp:Label ID="LabelCurrentPage" runat="server" Text="<%# ((GridView)Container.NamingContainer).PageIndex + 1 %>"></asp:Label> 页/共: <%-- //得到分页页面的总数--%> <asp:Label ID="LabelPageCount" runat="server" Text="<%# ((GridView)Container.NamingContainer).PageCount %>"></asp:Label> 页 <%--//如果该分页是首分页,那么该连接就不会显示了.同时对应了自带识别的命令参数CommandArgument--%> <asp:LinkButton ID="LinkButtonFirstPage" runat="server" CommandArgument="First" CommandName="Page" Visible='<%#((GridView)Container.NamingContainer).PageIndex != 0 %>'>首页</asp:LinkButton> <asp:LinkButton ID="LinkButtonPreviousPage" runat="server" CommandArgument="Prev" CommandName="Page" Visible='<%# ((GridView)Container.NamingContainer).PageIndex != 0 %>'>上一页</asp:LinkButton> <%--//如果该分页是尾页,那么该连接就不会显示了--%> <asp:LinkButton ID="LinkButtonNextPage" runat="server" CommandArgument="Next" CommandName="Page" Visible='<%# ((GridView)Container.NamingContainer).PageIndex != ((GridView)Container.NamingContainer).PageCount - 1 %>'>下一页</asp:LinkButton> <asp:LinkButton ID="LinkButtonLastPage" runat="server" CommandArgument="Last" CommandName="Page" Visible='<%# ((GridView)Container.NamingContainer).PageIndex != ((GridView)Container.NamingContainer).PageCount - 1 %>'>尾页</asp:LinkButton> 转到第 <asp:TextBox ID="txtNewPageIndex" runat="server" Width="20px" Text='<%# ((GridView)Container.Parent.Parent).PageIndex + 1 %>'/>页 <%--//这里将CommandArgument即使点击该按钮e.newIndex 值为3--%> <asp:LinkButton ID="btnGo" runat="server" CausesValidation="False" CommandArgument="-2" CommandName="Page" Text="Go"/> </PagerTemplate> </asp:GridView><%---------------------------------需求商信息结束--------------------------------------------------%><%---------------------------------配件信息表--------------------------------------------------%> <div class="input_info" style="width:620px;margin:15px auto;color:white;"> <span>操作类型:</span> <asp:DropDownList ID="ddlType" runat="server"> <asp:ListItem>入库</asp:ListItem> <asp:ListItem>出库</asp:ListItem> </asp:DropDownList> <span>编号:</span> <asp:TextBox runat="server" ID="txtNum"></asp:TextBox> <span>数量:</span> <asp:TextBox runat="server" ID="txtQuantity"></asp:TextBox> <div class="direction"> <span>需求商编号:</span> <asp:TextBox runat="server" ID="txtNeedMerchant"></asp:TextBox> </div> <asp:Button runat="server" Text="确认" ID="btnConfirm" OnClick="btnConfirm_Click"></asp:Button> </div> <asp:GridView ID="gvParts" runat="server" DataKeyNames="PartId" AutoGenerateColumns="False" AllowPaging="True" OnPageIndexChanging="gvParts_PageIndexChanging"> <Columns> <asp:BoundField DataField="Num" HeaderText="编号" /> <asp:BoundField DataField="PartName" HeaderText="名称" /> <asp:BoundField DataField="Name" HeaderText="生产单位" /> <asp:BoundField DataField="InTime" HeaderText="入库时间" /> <asp:BoundField DataField="Quantity" HeaderText="数量" /> <asp:BoundField DataField="UnitPrice" HeaderText="单价" /> </Columns> <%--添加分页--%> <PagerTemplate> 当前第: <%--//((GridView)Container.NamingContainer)就是为了得到当前的控件--%> <asp:Label ID="LabelCurrentPage" runat="server" Text="<%# ((GridView)Container.NamingContainer).PageIndex + 1 %>"></asp:Label> 页/共: <%-- //得到分页页面的总数--%> <asp:Label ID="LabelPageCount" runat="server" Text="<%# ((GridView)Container.NamingContainer).PageCount %>"></asp:Label> 页 <%--//如果该分页是首分页,那么该连接就不会显示了.同时对应了自带识别的命令参数CommandArgument--%> <asp:LinkButton ID="LinkButtonFirstPage" runat="server" CommandArgument="First" CommandName="Page" Visible='<%#((GridView)Container.NamingContainer).PageIndex != 0 %>'>首页</asp:LinkButton> <asp:LinkButton ID="LinkButtonPreviousPage" runat="server" CommandArgument="Prev" CommandName="Page" Visible='<%# ((GridView)Container.NamingContainer).PageIndex != 0 %>'>上一页</asp:LinkButton> <%--//如果该分页是尾页,那么该连接就不会显示了--%> <asp:LinkButton ID="LinkButtonNextPage" runat="server" CommandArgument="Next" CommandName="Page" Visible='<%# ((GridView)Container.NamingContainer).PageIndex != ((GridView)Container.NamingContainer).PageCount - 1 %>'>下一页</asp:LinkButton> <asp:LinkButton ID="LinkButtonLastPage" runat="server" CommandArgument="Last" CommandName="Page" Visible='<%# ((GridView)Container.NamingContainer).PageIndex != ((GridView)Container.NamingContainer).PageCount - 1 %>'>尾页</asp:LinkButton> 转到第 <asp:TextBox ID="txtNewPageIndex" runat="server" Width="20px" Text='<%# ((GridView)Container.Parent.Parent).PageIndex + 1 %>'/>页 <%--//这里将CommandArgument即使点击该按钮e.newIndex 值为3--%> <asp:LinkButton ID="btnGo" runat="server" CausesValidation="False" CommandArgument="-2" CommandName="Page" Text="Go"/> </PagerTemplate> </asp:GridView> </div></form>
    6.二级管理员首页后台核心代码
    protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { BindData(); } } //绑定gvParts和gvNeed public void BindData() { //查询数据 StringBuilder sb = new StringBuilder(); sb.AppendLine("SELECT C.PartId,C.Num,C.PartName,S.Name,C.InTime,C.Quantity,C.UnitPrice"); sb.AppendLine("FROM CarParts AS C INNER JOIN Supplies AS S"); sb.AppendLine("ON C.FromDepartId = S.Id;"); DataSet ds = DbHelperSQL.Query(sb.ToString()); //将数据绑定到gvParts上展示 gvParts.DataSource = ds.Tables[0]; gvParts.DataBind(); //查询数据并绑定显示,绑定需求商表 string sql = "SELECT Id,IsDeliver,Num,Name,Principal,Address,Phone FROM NeedMerchant;"; DataSet dsNeed = DbHelperSQL.Query(sql); gvNeedMer.DataSource = dsNeed; gvNeedMer.DataBind(); } //分页 protected void gvParts_PageIndexChanging(object sender, GridViewPageEventArgs e) { // 得到该控件 GridView theGrid = sender as GridView; int newPageIndex = 0; if (e.NewPageIndex == -3) { //点击了Go按钮 TextBox txtNewPageIndex = null; //GridView较DataGrid提供了更多的API,获取分页块可以使用BottomPagerRow 或者TopPagerRow,当然还增加了HeaderRow和FooterRow GridViewRow pagerRow = theGrid.BottomPagerRow; if (pagerRow != null) { //得到text控件 txtNewPageIndex = pagerRow.FindControl("txtNewPageIndex") as TextBox; } if (txtNewPageIndex != null) { //得到索引 newPageIndex = int.Parse(txtNewPageIndex.Text) - 1; } } else { //点击了其他的按钮 newPageIndex = e.NewPageIndex; } //防止新索引溢出 newPageIndex = newPageIndex < 0 ? 0 : newPageIndex; newPageIndex = newPageIndex >= theGrid.PageCount ? theGrid.PageCount - 1 : newPageIndex; //得到新的值 theGrid.PageIndex = newPageIndex; //重新绑定 BindData(); } protected void btnConfirm_Click(object sender, EventArgs e) { //为操作日志做好准备 //获取输入编号数量和出库方向 string Num = txtNum.Text; int Quantity = Convert.ToInt32(txtQuantity.Text); string NeederNum = txtNeedMerchant.Text; //根据写入的编号获取配件的名称 string sqlGetPName = "Select PartName from CarParts where Num = @Num;"; SqlParameter[] pmsGetPName = { new SqlParameter("@Num",SqlDbType.NVarChar,50), }; pmsGetPName[0].Value = Num; DataSet dsGetPName = DbHelperSQL.Query(sqlGetPName, pmsGetPName); string pName = dsGetPName.Tables[0].Rows[0]["PartName"].ToString(); //根据写入的编号获取需求商的名称 string nName = ""; if (NeederNum != "") { string sqlGetNName = "Select Name from NeedMerchant where Num = @Num;"; SqlParameter[] pmsGetNName = { new SqlParameter("@Num",SqlDbType.NVarChar,50), }; pmsGetNName[0].Value = NeederNum; DataSet dsGetNName = DbHelperSQL.Query(sqlGetNName, pmsGetNName); nName = dsGetNName.Tables[0].Rows[0]["Name"].ToString(); } //获取用户登录的Id,并获取登录用户的相关信息 int id = Convert.ToInt32(Session["Id"]); DateTime date = Convert.ToDateTime(Session["LoginTime"]); if (id == 0) { id = 2; } string sqlUsers = "Select UserName,Department from Users where UserId = @id;"; SqlParameter[] pms = { new SqlParameter("@id",SqlDbType.Int), }; pms[0].Value = id; DataSet ds = DbHelperSQL.Query(sqlUsers,pms); string type = ddlType.SelectedValue; //插入日志列表 string sqlInsertLog = "insert into Log(Operator,Department,Type,Details,Time,IP)" + " Values(@Operator,@Department,@Type,@Details,getDate(),@IP)"; SqlParameter[] pmsInsertLog = { new SqlParameter("@Operator",SqlDbType.NVarChar,50), new SqlParameter("@Department",SqlDbType.NVarChar,50), new SqlParameter("@Type",SqlDbType.NVarChar,50), new SqlParameter("@Details",SqlDbType.NVarChar,50), new SqlParameter("@IP",SqlDbType.NVarChar,50) }; pmsInsertLog[0].Value = ds.Tables[0].Rows[0]["UserName"]; pmsInsertLog[1].Value = ds.Tables[0].Rows[0]["Department"]; pmsInsertLog[2].Value = type; if (type == "入库") { pmsInsertLog[3].Value = Num + pName + type + Quantity + "件"; } else { pmsInsertLog[3].Value = Num + pName + type + "至" + nName + Quantity + "件"; } pmsInsertLog[4].Value = GetIP(); DbHelperSQL.ExecuteSql(sqlInsertLog,pmsInsertLog); //根据下拉选择不同,有出库和入库两个选择,然后进行不同的操作 //入库操作 if (ddlType.SelectedValue == "入库") { //更改数据库数据 string sql = "update CarParts set Quantity = Quantity + @Quantity where Num = @Num"; SqlParameter[] pms2 = { new SqlParameter("@Quantity",SqlDbType.Int), new SqlParameter("@Num",SqlDbType.NVarChar,50) }; pms2[0].Value = Quantity; pms2[1].Value = Num; DbHelperSQL.ExecuteSql(sql,pms2); //插入操作日志 Response.Redirect("Index2.aspx"); } //出库操作 else { string sql = "update CarParts set Quantity = Quantity - @Quantity where Num = @Num"; SqlParameter[] pms1 = { new SqlParameter("@Quantity",SqlDbType.Int), new SqlParameter("@Num",SqlDbType.NVarChar,50) }; pms1[0].Value = Quantity; pms1[1].Value = Num; DbHelperSQL.ExecuteSql(sql, pms1); //更改需求商的是否发货状态 string sqlUpdate = "update NeedMerchant set IsDeliver = 'True' where Num = @NeedNum;"; SqlParameter[] pars = { new SqlParameter("@NeedNum",SqlDbType.NVarChar,50) }; pars[0].Value = NeederNum; DbHelperSQL.ExecuteSql(sqlUpdate,pars); Response.Redirect("Index2.aspx"); } } //获取Ip public string GetIP() { string result = String.Empty; result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.UserHostAddress; } if (string.IsNullOrEmpty(result)) { return "127.0.0.1"; } return result; }
    5.2 系统测试为了保证设计完成后的软件是有效的,健壮的,在软件开发的生命周期中要对软件进行测试,测试工作可以验证软件的需求是否都得以实现,软件是否正确地提供了需要的功能,以及软件是否能健壮稳定地运行。所以,本网站的测试主要以如下几方面为切入点:

    一、功能验收测试:对应软件的需求分析和详细设计文档,检查系统所应该实现的功能是否已经实现。对于一个软件,完成并能够使用的最基本条件是所有的功能都能覆盖,并且功能能够成功执行。 二、集成验收测试:在保证了每个功能都实现并可用之后,需要验证系统的每个功能的正确性,于是进一步的测试则要保证每一个功能的每种可能执行方式 都能得到正确的结果。这样我们才可以说,对外发布的系统是一个正确的系统。 三、健壮性、稳定性及性能测试:为了让系统能够稳定的高效运行,需要对系统进行以下的测试。如,选择一些非正常的输入,这时系统需要能继续稳定运 行,或者很容易从错误中自动恢复;当长时间的进行持续的操作时,系统对资源 的消耗应该处于稳定的,可接受的范围内,尤其要避免内存泄露等问题带来的风险;系统还要达到需求分析文档中所规定的性能指标,所以还要针对实际情况进 行性能测试;最后系统还要根据需要对不同平台、不同环境的兼容性进行测试。 整个系统需要测试的模块主要有登录模块,一级管理员的管理模块,二级管理员的管理模块。
    系统测试:功能测试、性能测试、验收测试。目的是为了保证所实现的系统确实是用户所需要的。
    登录验证,当用户名或密码不输入时提示用户重新输入,以及当用户输入的用户名和密码不匹配时,提示重新输入。当输入的是一级管理员则进入一级管理员首页,当输入的是二级管理员进入二级管理员首页。

    添加配件

    点击配件名称,弹出编辑界面

    勾选点击删除按钮便可以对信息进行删除

    填写入库信息后点击确定,该汽车配件数量增加
    参考文献[1] Karli Watson着,齐立波译,C#入门经典(第6版),2014-8
    [2] (美)内格尔(Nagel.C)等所着,C#高级编程,2008-10-1
    [3] 明日科技 着,ASP.NET从入门到精通,2012-09
    [4] 王珊,萨师煊.数据库系统概论(第四版).高等教育出版社,2006.5
    [5] ASP.NET 入门经典(第9版),2016-11
    [6] Baron Scbwartz.高性能MySQL(第3版)[M].电子工业出版社,2013
    [7] (美)加洛韦 等着,ASP.NET MVC5高级编程(第5版),2015-02
    [8] 构建之法 现代软件工程(第二版),2015-07
    [9] 王国辉,王毅.数据库系统开发案例精选[M].人民邮电出版社,2006
    [10] 软件工程:实践者的研究方法(原书第8版),2016-11
    1 评论 12 下载 2018-09-26 18:38:29 下载需要21点积分
  • linux下实现的ping程序

    一、设计目的PING程序是我们使用的比较多的用于测试网络连通性的程序。PING程序be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端ICMP,使用ICMP的回送请求和回送应答来工作。由计算机网络课程知道,ICMP是be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端IP的一个协议,ICMP包通过IP的封装之后传递。
    课程设计中选取PING程序的设计,其目的是通过PING程序的设计,能初步掌握TCP/IP网络协议的基本实现方法,对网络的实现机制有进一步的认识。
    熟悉SOCKET的编程,包括基本的系统调用如SOCKET、BIND等。
    二、设计内容2.1 RAW模式的SOCKET编程PING程序是面向用户的应用程序,该程序使用ICMP的封装机制,通过IP协议来工作。为了实现直接对IP和ICMP包进行操作,实验中使用RAW模式的SOCKET编程。
    2.2 具体内容2.2.1 定义数据结构定义IP数据报、ICMP包等相关的数据结构。
    ICMP数据头结构
    typedef struct Icmp{ unsigned char type; //类型 unsigned char code; //代码 unsigned short check_sum; //检验和 unsigned short id; //标识符 unsigned short seq; //序列号}IcmpHeader;
    IP数据包头结构
    typedef struct iphdr { unsigned int headLen:4; //首部长度 unsigned int version:4; //版本 unsigned char tos; //区分服务 unsigned short totalLen; //总长度 unsigned short ident; //标识 unsigned short fragAndFlags; //标志与片偏移 unsigned char ttl; //生存时间 unsigned char proto; //协议 unsigned short checkSum; //检验和 unsigned int sourceIP; //源地址 unsigned int destIP; //目的地址}IpHeader;
    2.2.2 程序实现在LINUX环境下实现PING程序
    2.2.3 程序功能
    ping ip 地址如ping 192.168.1.1
    ping 域名(进行DNS解析)如ping www.baidu.com
    参数“ -n 数字”进行设置ping 的次数如ping www.baidu.com –n 10
    参数 -t 无限循环如ping 192.168.1.140 -t
    分析ping到的数据报如最短时间,最长时间,平均时间和丢包率
    ping ? 提供帮助提示

    三、实验平台与语言
    平台:linux
    语言:C语言

    四、功能模块实现4.1 总体设计方案流程图

    主要代码
    // ICMP数据头结构 typedef struct Icmp{ unsigned char type; //类型 unsigned char code; //代码 unsigned short check_sum; //检验和 unsigned short id; //标识符 unsigned short seq; //序列号}IcmpHeader;//执行ping功能int ping(const char *ip, int send_count){ int rawfd; struct sockaddr_in dest_adr; char icmp_data[1024]; int size = sizeof(IcmpHeader)+32; int r, i = 0, send, recv=0, lost=0; char recv_buf[1024]; int all_time[1024] = {0}; //创建原始套接字 rawfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if(rawfd == -1) { perror("create socket failed!"); return -1; } //设置目的地址与端口 dest_adr.sin_family = AF_INET; dest_adr.sin_port = htons(80); inet_aton(ip, &dest_adr.sin_addr); //封装icmp数据包 pack_icmp(icmp_data, size); printf("\n正 Ping %s 具有%d个字节的数据:\n", ip, size-sizeof(IcmpHeader)); if(send_count == LOOP) { //无限循环 while(1) { if(ping_one(rawfd,dest_adr, ip, icmp_data , all_time) != -1) { recv++; } send++; } } else { for(i = 0; i<send_count; i++) { if(ping_one(rawfd,dest_adr, ip, icmp_data , all_time) != -1) { recv++; } send++; } } printf("\n%s 的 Ping 统计信息:\n 数据包:已发送 = %d,已接收 = %d, 丢失 = %d<%.1f%% 丢失>, \n",ip, send, recv, lost, ((float)lost/(float)send)*100); printf("往返行程的估计时间:\n 最短=%dms 最长=%dms 平均 = %dms \n\n" ,min(all_time, send), max(all_time, send), average(all_time, send)); close(rawfd); return 0;}
    4.2 DNS域名解析功能实现4.2.1 DNS 服务器
    地址:202.96.134.133
    端口:53

    #define DNS_PORT 53#define DNS_IP "202.96.134.133"#define DNS_IP2 "8.8.8.8"
    4.2.2 DNS 的实现基础:通过UDP发送查询报文给DNS 服务器,然后从服务通过UDP 返回的回应报文中解析得到对应域名的IP。
    4.2.3 DNS 报文格式
    4.2.4 首部格式
    其中标志字段:16位

    定义首部结构体
    typedef struct DNSheader{ unsigned short id; unsigned char qr_opcode_aa_tc_rd; unsigned char ra_zero_rcode; unsigned short qdcount; unsigned short ancount; unsigned short nscount; unsigned short arcount;}DnsHeader;
    4.2.5 问题记录格式

    查询名字:域名的可变长字段;其中计数字段指明每一节中的字符数
    查询类型:16位;值的意义如下表,查询ip 时为1
    查询类别:16位;定义使用DNS的特定协议, 一般为1

    查询名字打包代码:
    //把域名打包成dns数据报的数据部分 如(3www5baidu3com)//计算每段的数量for(i = 0; i < name_len; i++){ if(netname[i] == '.') { len[flg++] = i - s; s += len[flg-1]+1; }}len[flg] = i - s;i = 0;flg = 0;data[i++] = len[flg++];//加入每段字节的数量for(; i < name_len+1; i++){ if(netname[i-1] == '.') { data[i] = len[flg++]; } else { data[i] = netname[i-1]; }}
    4.2.6 资源记录格式
    资源数据:可变长;值内容取决于类型字段的值,可以是数值、域名、偏移指针、字符串。
    4.2.7 在资源数据中提取ip和原域名失败的解决方法
    由于没有查到详细的解析资料,因此通过对整个报文每个字节进行分析,发现其格式的规律:ip地址放在报文的末尾,可以通过指针快速定位。
    采样分析的域名有(www.baidu.com 和 www.sina.com),下图是对 www.baidu.com 的分析。

    代码如下:
    //直接定位ip地址Ipadr *ip =(Ipadr *) (sen_buf+(r-8-4-8-2));//如果ip地址长度不为4, 则返回if(ip->len != 0x0400){ return -1;}//次ip地址转为字符串sprintf(get_ip, "%u.%u.%u.%u", ip->a, ip->b, ip->c, ip->d);
    失败原因:过于投机取巧,取得两个分析对象不够特殊,对DNS回答格式完全不解
    新的解决方法
    通过用wireshark抓取DNS包进行分析,由于分析次数过多,此处以 www.baidu.com 为例。

    由抓取的dns包分析可得到回答部分的格式如下:
    answer1:name : 不定长,c0 0c指段偏移地址type: 16 位 0005 是别名answerclass: 16位, 0001ttl:32位data length: 16位cname: 别名,长度data lengthanswer 2name:c0 2b 指向别名type: 16位 0001 是ip answerclass : 16位 0001ttl: 32位data length:16位address: 4个字节answer 3与回应2相似 ip 不一样进一步分析
    可以发现回答部分有两个类型(只是本设计的情况,DNS有很多种类型),type 字段为5时为别名回应,为1 时为ip回应,因此通过type和上面得到的格式来进行ip和别名的获取。
    其中还发现,DNS为了减小数据报文的长度,回应部份重复的字段会省略,并通过偏移指针指向重复部分,由上面的分析可知是用c0(代替字段长度)来转义下一字节为偏移指针。
    获取代码设计
    int parse_dns_respone(unsigned char *recv_buf,unsigned char **answer_o, int data_len ,char *get_ip, const char *netname){ int asw_type; int i,j, k; static int fn = 0, fi = 0; int r; unsigned char cname[40]; unsigned char *answer = *answer_o; answer +=2;//查询域名 asw_type = ntohs(*((unsigned short*)answer)); answer +=2;//type answer +=2;//class answer +=4;//ttl if(asw_type == 5) //域名包 { bzero(cname, sizeof(cname)); //解析域名 parse_dns_name(recv_buf, &answer, cname); fn = 1; //标记已取得别名 } else if(asw_type == 1) //ip 回应包 { //解析IP parse_dns_ip(&answer ,get_ip); if(fn == 1) printf("\n---- %s(%s)",cname , get_ip); else printf("\n---- %s(%s)",netname , get_ip); fi = 1; //标记已取得IP } *answer_o = answer; if(fn != 0 && fi != 0) return 2; //已取得别名和域名。则结果 else if(fi != 0) return 1; return 0;}//解析IPvoid parse_dns_ip(unsigned char **answer_o ,char *get_ip){ unsigned char *answer = *answer_o; Ipadr *ip =(Ipadr *)answer; //取提ip sprintf(get_ip, "%u.%u.%u.%u", ip->a, ip->b, ip->c, ip->d); *answer_o = answer;}//解析域名void parse_dns_name(unsigned char *recv_buf, unsigned char **answer_o, unsigned char *cname){ int tmp_len; int d_length; int i, k; unsigned char *answer = *answer_o; d_length = ntohs(*((unsigned short*)answer));//总长度 answer +=2; //data length i=0; for(k=0; k<d_length; k++) { tmp_len = *answer++; //名字段长度 if(i != 0) cname[i++]='.'; if(tmp_len == 0xc0) //CO转义为复字段 { int tmp = *answer++; //获得偏移指针 k ++; i--; while(1) { tmp_len = recv_buf[tmp++];//跳转到偏移位置 if(tmp_len == 0) break; //偏移位置结果 cname[i++]='.'; //填充域名 get_seg_name(&recv_buf[tmp], cname+i, tmp_len); tmp += tmp_len; i += tmp_len; } continue; } if(tmp_len == 0) break; //填充域名 get_seg_name(answer, cname+i, tmp_len); k += tmp_len; i += tmp_len; //移动指针 answer += tmp_len; } cname[i] = '\0'; *answer_o = answer;}
    4.2.8 遇到的问题有多段连续的域名字段重复
    原来只考虑到有一个域名字段是重复的,但是有些是有多段连续的域名字段重复的,解决的方法是(直到len字节为0 才认为没有重复字段了)。
    while(1){ tmp_len = recv_buf[tmp++];//跳转到偏移位置 if(tmp_len == 0) break; //偏移位置结果 cname[i++]='.'; //填充域名 get_seg_name(&recv_buf[tmp], cname+i, tmp_len); tmp += tmp_len; i += tmp_len;}
    有多个域名回答
    原来只考虑到只有一个域名名回答,但有些(如 www.sina.com )是有多个域名的,因此解决方法是域名回答可以多次解析,只有取得IP地址才结束,而不是原来只解析两个回答就认为拿到了IP地址。
    4.2.9 本实现的不足
    没有完全掌握DNS 回应报文的格文
    服务器单一,没有备用服务器
    还存在未知域名不能解析的,未能确保能解析所有正确域名

    五、结果分析Ping ip 地址 如 ping 192.168.1.1

    Ping 域名 如:ping www.sougou.com





    Ping –n 如:ping 14.215.177.37 –n 2

    Ping –t 如: ping www.baidu.com -t

    Ping ?

    六、心得体会做的永远比想象中的难,修改了多次代码,刚开始想只要IP 地址,要愿意深入分析回应数据报,只是进过一些特例来定位ip 地址就好,想不到两个特例效果是一样的(www.baidu.com 和 www.sina.com ), ip 地址都是在末尾前几个字节,但是,由于DNS 的去掉重复的功能,造成只有是只有2个IP 地址的域名才能有效,多于或少于两个的都不行,因此又得花时间重新进行分析,然后才想到利用抓包软件来协助分析,又花了不少心血修正这个BUG,程序员真不好做,坐到腰酸背痛。
    但是,还情事还没那么顺利,拿多几个域名来试之后又发现了问题,具有多个别名的域名没办法正确解析,在原来的基础上又很难修改,因此决定把代码封装起来,封装多几个函数,然后在封装好的基础上解决多个别名的问题,但是在调试中又出现多个连绵的域名字段重复省略导致解析也来的域名完全的问题,又进行了一番修改。真不容易。
    总结

    DNS的格式还需要找相关资料来学习
    以后写代码如果不是用于学习的,则应该找完成的框架进行修改,这样可以省时间,且写出来的程序也会比较稳定
    写程序前最好先做出详细方案,避免一些BUG
    网络知识的学习还有很多要学,网络编程要学的知识更加多
    2 评论 6 下载 2019-06-25 11:26:26 下载需要11点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端B树实现的图书管理系统

    1 需求分析1.1 数据结构分析图书管理系统中图书管理模块包括图书类型定义:书号(int),现存量(int),总存量(int),出版时间(int),价格(float),书名,作者名为字符型,借阅指针为读者类型;
    读者类型定义:ID号(int),姓名为字符型。
    B树(2-3树)类型定义:关键字个数和关键字数组为整型,另外还有指向双亲的指针,指向子树的指针;
    B树查找结果类型定义:结点指针,关键字序号和查找标志变量为整型。
    1.2 输出的形式输出界面以用户于计算机的交互方式进行,在输出窗口上显示“特定的提示信息”之后,由用户按提示在键盘上输入演示程序中规定的运算命令,相应的输入数据和运算结果显示在下面。由于时间和能力有限,该管理系统没有用文件存放数据,所有数据放在内存中存放(后来做了改进版就有了),但是选做的功能就还没有实现。其基本业务都是以书号为关键字进行,采用了(2-3树)对书号建立索引,以提高效率。
    1.3 程序所能达到的功能1.3.1 采编入库
    新书购入,将书号,书名,作者,册数,出版时间以及价格添加入图书管理系统中,如果这种书在系统中已存在,则只将总库存量增加,每增加一个书号则以凹入表的形式显示B树形状。
    1.3.2 清除库存
    实现某本书的全部信息删除操作,每清除一个书号则以凹入表的形式显示B树形状。
    1.3.3 图书借阅
    如果树的库存量大于零时则执行出借,登记借阅者的图书证号和姓名。
    1.3.4 图书归还
    注销借阅者信息,并改变该书的现存量。
    1.3.5 查看图书馆全部图书
    用表格输出所有图书的信息。
    1.3.6 查看某图书信息
    查看指定某一本书的全部信息。
    1.3.7 查看某本书的借阅者信息
    表格输出某本书的全部借阅者信息。
    1.3.8 读取图书信息
    从文件中读取所有图书的信息以及所有借阅者的信息
    1.4 测试数据
    入库书号:35, 16, 18, 70, 5, 50, 22, 60, 13, 17, 12 , 45, 25, 42, 15, 90, 30, 7
    然后清除:45, 90, 50, 22, 42
    其余数据自行设计。由空树开始,每插入删除一个关键字后就显示B树的状态。

    2 概要设计2.1 所有数据类型的定义采用KeyType类型(本次实验默认为int)为元素类型实现抽象数据类型BTree。
    ADT BTree{
    数据对象
    T是具有相同特征的数据元素集合。
    数据关系
    若D为空集,则称为空树;

    树中每个结点最多含有m棵子树
    若根结点不是叶子结点,则至少有2个子树
    除根结点之外的所有非终端结点至少有┌m/2┐棵子树
    每个非终端结点中包含信息:(n,A0,K1,A1,K2,A2,…,Kn,An)。其中:

    Ki(1<=i<=n)为关键字,且关键字按升序排序指针Ai(0<=i<=n)指向子树的根结点,Ai-1指向子树中所有结点的关键字均小于Ki,且大于Ki-1
    关键字的个数n必须满足:┌m/2┐-1<=n<=m-1。 (5)所有的叶子节点都在同一层,子叶结点不包含任何信息


    基本操作
    result SearchBTree(BTree T, int k);

    初始条件:树T存在
    操作结果:在m阶B数T上查找关键字k,返回p{pt,i,tag}

    Status InsertBTree(BTree &T, int k, BTree q, int i, Record *recptr);

    初始条件:树T存在
    操作结果:在B树T上结点p->pt的key[i]和key[i+1]之间插入关键字k

    Status DeleteBTree(BTree &T, int k);

    初始条件:B树上p结点存在
    操作结果:删除B树T上结点p->pt的关键字k

    void BTreeTraverse(BTree T, void(*visit)(BTree));

    初始条件:树T存在
    操作结果:用visit()函数遍历B树

    void DestroyBTree(BTree T);

    初始条件:树T存在操作结果:销毁B树
    } ADT BTree
    ADT Library{
    数据对象
    T是具有相同特征的数据元素集合。
    数据关系
    数据元素同属于一个集合。
    基本操作
    void InitLibrary(BTree &L);

    操作结果:初始化书库L为空书库
    void InsertBook(BTree &L, BookType B, result res);

    初始条件:书库L和B存在,result包含B书在书库中的位置或应该插入的位置
    操作结果:如果书库中已存在B树,则只将B树库存量增加,否则插入B书到书库L中

    int DeleteBook(BTree &L, BookType B);

    初始条件:书库L和B存在
    操作结果:如果书库中存在B书,则从书库中删除B书的信息,并返回OK,否则返回ERROR

    void BorrowBook(BTree L, BookType B, ReaderType R);

    初始条件:书库L存在,B书时书库中的书并且可被读者R借阅
    操作结果:借出一本B书,并登记借阅者信息

    int ReturnBook(BTree L, int booknum, int IDnum, BookType &B, ReaderType &R);

    初始条件:书库L存在
    操作结果:若书库L中有读者R借阅B书的记录,则注销该记录,改变B书现存量,并返回OK,书不存在或物该读者记录则返回ERROR

    void PrintAllbooks(BTree L);

    初始条件:书库L存在
    操作结果:显示所有图书的信息

    int ShowBookinfo(BTree L, int booknum);

    初始条件:书库L存在
    操作结果:若书库L中存在书B,则显示B书基本信息并返回OK,否则返回ERROR

    void PrintBorrower(ReaderType R);

    操作结果:输出某本书所有借阅者的信息
    } ADT Library
    2.2 主程序的流程
    2.3 各程序模块之间的调用关系
    3 详细设计函数和过程的调用关系图

    4 调试分析4.1 调试过程中遇到的问题是如何解决的以及对设计与实现的回顾讨论和分析此次的课程设计的重难点应该在于B树的定义以及删除操作,由于我设计性实验选的也是B树,有几个操作函数大同小异,不过要在原来的基础上增加一些东西,例如在原有的关键字的基础上加上与关键字对应的图书结点,因此算法需要一些小改动。
    一开始程序跑不起来,一看居然68个错误,可是大致看下来都是不太正常的提示,所以在这个地方卡了蛮久的时间,好在经过不断的调试,发现是头文件里各个数据结构的顺序放倒了,更改顺序后只剩下寥寥几个小错误,大大增长了把程序做好的希望。
    此次实验的不足在于这个图书管理系统的存储是建立在内存上的,故程序退出数据得不到保存,每次都得重新输入(经过改进已经解决这个问题)。每个功能比较独立,相互联系不算多,仅仅是完成各部分需求的算法,采编入库,清除库存和显示信息相对逻辑关系强一点。由于个人能力的局限以及时间上的紧迫,此次的选做要求没有实现,系统功能的不够完整和联系不够紧密是我以后要提高的地方。
    4.2 算法的时空分析(包括基本操作和其他算法的时间复杂度和空间复杂度的分析)和改进设想设B树的阶为m,(书号)关键字个数为N

    SearchBTree最好情况为O(1),最坏时比较的结点数不超过log[m/2]((N+1)/2)+1
    因为B树总是在最后一层插入,因此InsertBTree操作比较的结点数也不超过log[m/2]((N+1)/2)+1
    DeleteBTree最好情况为被删关键字在最下层结点而且删除后该结点关键字个数不小于m/2,时间复杂度O(1);最坏情况为删除后需要合并父节点直到到根节点,需比较2 *(log[m/2]((N+1)/2)+1)次
    InsertBook、DeleteBook时间复杂度与B树的插入和删除基本相同
    BorrowBook、ReturnBook除了需要SearchBTree,还与该书借阅人数成正比

    4.3 经验和体会
    按照指导书给出的实习报告规范的步骤,先进行需求分析、概要设计,再进行详细设计,能使实际问题从抽象到具体,能从整体上把握程序的功能方向
    通过划分成几个模块,单独编写每个模块的基本操作,再组合在一起,细分了程序的功能,降低设计的难度,方便了程序的调试、修改和组合
    本次设计实在被B树的指针折磨透了,我深深的体会到:编码时必须对程序的算法了如指掌,对可能出现的每一种情况都处理周到,不然对于复杂的(像B树的删除)函数将会无所适从
    编码时就应该尽量把程序写正确,避免产生错误,这样可能远比调试时才来发现问题、解决问题用的时间少得多,效率高得多
    测试时要注意测试的完备性
    编码时要形成一种自己的风格,同时要注意这种风格应该是大众所接受的,要保持程序的可读性

    5 用户使用说明
    本程序的运行环境为Windows 10操作系统,编译环境是VS 2015
    执行文件为BTree_Library.exe,打开BTree_Library.exe,显示欢迎界面



    输入管理员密码:5372


    进入图书管理系统


    选择1新书入库后提示输入入库书号,读入书号后程序会查找是否已存在,如已存在则提示输入新增加数量,如不存在则提示输入图书其他书名、着者、等信息,插入后显示B树状态
    选择2清除库存后,提示输入删除书号,如果存在该书则提示是否确认删除,如无该书则提示不存在。删除后显示B树状态
    选择3图书出借后,提示输入书号,如该书存在则显示该书,提示输入借阅证号和借阅者姓名,判断如果能借阅则输出借阅成功,否则输出不能借阅;如无该书则提示不存在该书
    选择4图书归还后,提示输入归还书号和借阅证号,如存在该借阅记录则提示还书成功,否则提示不存在该书或无该读者借书记录
    选择5查看图书馆所有图书后,以表格形式输出图书管理系统的总库存
    选择6查看某图书信息后,以表格形式输出该图书的库存情况以及作者等相关信息
    选择7查看某树借阅者信息后,以表格形式输出该图书的所有借阅者的信息
    选择8将文件中的图书内容和借阅者资料导入
    选择0则退出系统

    6 测试结果列出你的测试结果,包括输入和输出。这里的测试数据应该完整和严格,最好多于需求分析中所列。
    将全部数据输入后用凹入表形式显示B树:

    使用功能5:用表格输出图书馆总库存:

    选择功能2:清空某一本书的库存

    清除45后的凹入表:

    用功能2依次清除:45, 90, 50, 22, 42后的凹入表表示如下:

    选择功能3:借阅图书,输入要借的图书号,借阅者的姓名和ID号

    选择功能6:查看某一本图书的信息,并以表格形式输出。

    选择功能4:归还图书

    当图书号不存在时,输出书库中不存在此书

    当借书时该图书的库存已空,则提示库存不足,借阅失败!

    选择功能7:查看某本书的借阅者信息

    输入功能8:从文件中导入图书信息和借阅者信息
    2 评论 155 下载 2018-11-05 22:49:53 下载需要10点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端MFC实现的图形绘图编辑系统

    一、课程设计目的
    学完《C语言程序设计》和《面向对象可视化编程》两门课程之后,进入到实践环节,通过一个简单的MFC的绘图程序来运用自己所学的知识,学会解决编程中遇到的问题。
    本课程设计可以提供一个稍微具有规模的程序开发的例子,让同学们可以体会到程序的构思、编码以及调试的完整过程,最后并总结课程设计的过程。
    通过本次课程设计,增强了自己对程序设计的认识,在不足的方面加强学习。

    二、课程设计的内容与设计思路2.1课程设计内容
    编写一个简单的图形编辑MFC程序,可以添加,修改与删除图形元素,以形成图形画面,如图2-1所示


    图上的黑点给图元的原点,w为宽度width,h为高度height,r为半径radius,a为字符角度angle。这些为这些图元需要保存的参数,另外,每个图元是否填充,用什么模式填充
    采用单文档方式,文档中存储图形画面的各个图元数据,视图负责图形的绘制
    文档支持图形的序列化(连载),提供新建、打开、保存等操作
    视图除了绘制图形,还提供图形交互,能够按住Ctrl键再鼠标左键单击来创建图元,鼠标左键双击编辑修改图元属性,鼠标右键双击删除图元
    图元创建与修改时的参数由参数对话框来编辑,参见对话框示例图2-2,创建时以鼠标左击时光标的所在位置作为基点来创建图元


    2.2 设计思路使用图元基础类shape作为所有六个图元类的基类,设计派生各个具体的图形类,要求支持上述功能,各个类之间的关系如图2-3 所示。

    三、程序实现过程与细节3.1 程序涉及到的函数列表及程序流程图函数定义与功能一览表



    函数 序号
    函数名
    函数定义
    函数定义所在文件
    函数功能




    1
    OnInitDialog()
    BOOL WAttribute::OnInitDialog()
    WAttribute.Cpp
    初始化对话框


    2
    OnCbnSelchangeCombo()
    Void WAttribute::OnCbnSelchangeCombo()
    WAttribute.Cpp
    选择图形类型


    3
    OnBnClickedLinecolor()
    void WAttribute::OnBnClickedLinecolor()
    WAttribute.Cpp
    选择颜色


    4
    OnBnClickedOk()
    void WAttribute::OnBnClickedOk()
    WAttribute.Cpp
    ok控件消息


    5
    ~CWDemoDoc()
    CWDemoDoc::~CWDemoDoc()
    WDemoDoc.cpp
    析构动态数组


    6
    Serialize()
    void CWDemoDoc::Serialize(CArchive& ar)
    WDemoDoc.cpp
    序列化函数


    7
    OnLButtonDown()
    void CWDemoView::OnLButtonDown(UINT nFlags, CPoint point)
    WDemoView.cpp
    左键功能函数


    8
    OnDraw()
    void CWDemoView::OnDraw(CDC* pDC)
    WDemoView.cpp
    绘图函数


    9
    OnRButtonDblClk()
    Void CWDemoView::OnRButtonDblClk(UINT nFlags, CPoint point)
    WDemoView.cpp
    右键功能函数


    10
    WShape()
    WShape::WShape()
    WShape.cpp
    图元基类默认构造函数


    11
    WSquare()
    WSquare::WSquare(int x, int y, int w)
    WSquare.cpp
    正方形类有参构造函数


    12
    WRectangle()
    WRectangle::WRectangle(int x, int y, int w, int h)
    WRectangle.cpp
    矩形类有参构造函数


    13
    Wcircle()
    WCircle::WCircle(int x, int y, int r)
    WCircle.cpp
    圆形类有参构造函数


    14
    WEllipse()
    WEllipse::WEllipse(int x, int y, int hr, int vr)
    WEllipse.cpp
    椭圆形类有参构造函数


    15
    WTriangle
    WTriangle::WTriangle(int x, int y, int length)
    WTriangle.cpp
    三角形类有参构造函数


    16
    WText()
    WText::WText(int x, int y, CString content)
    WText.cpp
    文本类有参构造函数


    17
    Draw()
    Void WSquare:: Draw(CDC pDC) Void WRectangle:: Draw(CDC pDC) Void WCircle:: Draw(CDC pDC) Void WEllipse:: Draw(CDC pDC) void WTriangle::Draw(CDC pDC) void WText::Draw(CDC pDC)
    WSquare.cpp WRectangle.cpp WCircle.cpp WEllipse.cpp WTriangle.cpp WText.cpp
    各种图形的绘制函数


    18
    Serialize()
    void WSquare::Serialize(CArchive & ar) void WRectangle::Serialize(CArchive & ar) void WCircle::Serialize(CArchive & ar) void WEllipse::Serialize(CArchive & ar) void WTriangle::Serialize(CArchive & ar) void WText::Serialize(CArchive & ar)
    WSquare.cpp WRectangle.cpp WCircle.cpp WEllipse.cpp WTriangle.cpp WText.cpp
    各种图形的序列化函数


    19
    IsMatched()
    bool WSquare::IsMatched(CPoint pnt) bool WRectangle::IsMatched(CPoint pnt) bool WCircle::IsMatched(CPoint pnt) bool WEllipse::IsMatched(CPoint pnt) bool WTriangle::IsMatched(CPoint pnt) bool WText::IsMatched(CPoint pnt)
    WSquare.cpp WRectangle.cpp WCircle.cpp WEllipse.cpp WTriangle.cpp WText.cpp
    图元匹配函数


    20
    SetAttribute()
    void WSquare::SetAttribute(int nX, int nY, COLORREF nBoderColor, int nBoderType, int nBoderWidth, COLORREF nFillColor, int nFillType) … void WText::SetAttribute(int nX, int nY, COLORREF nBoderColor, int nBoderType, int nBoderWidth, COLORREF nFillColor, int nFillType)
    WSquare.cpp WRectangle.cpp WCircle.cpp WEllipse.cpp WTriangle.cpp WText.cpp
    重置图元属性值函数



    程序流程图

    3.2 课程设计实现过程3.2.1 选择高级视图由于老师平时上课时,使用的都是经典的基础视图,而课程设计文档中的视图是高级视图,对比运行的视图,我尝试着把程序的视图设为和课程设计文档里面一样的(可参见图4-1)
    3.2.2 设计类和对话框3.2.2.1 设计类
    自己创建一个WShape(以W开头便于和MFC的类区分)图元类,派生图元类单独创建.h和.cpp文件,便于管理,虽然切换有些麻烦,但后期修改很方面,我没有像示例程序里面那样把所有的类都放在shape文件里面。
    基类是WShape

    数据成员:

    原点坐标(鼠标点击的点)旋转角度(单独为文本类设计,其他图形不使用)和线以及填充有关的属性字段
    成员函数

    有参数的构造函数绘制图元的函数判断鼠标点击的位置是否在图形内部的函数,是否打开属性设计窗口序列化数据的函数重新设置图元的属性的函数

    注意:要在每个派生类的.h头文件里面声明该类型支持序列化,并在.cpp源文件里面指定序列化的版本。
    例如:
    矩形类
    DECLARE_SERIAL(WRectangle)//声明类WRectangle是支持序列化IMPLEMENT_SERIAL(WRectangle, CObject, 1)//实现类WSquare的序列化,指定版本为1
    派生类

    正方形类Square,矩形类Rectangle,对于正方形类,除了基类WShape之外的数据成员外,有一个独立的width数据,而矩形类只是在此基础上加上一个height数据,两者的绘图原理是一样的,CDC类的pDC对象中有绘制矩形的函数
    圆类Circle,椭圆类Ellipse,椭圆类既有长半轴,也有短半轴,两者的绘图原理是一样的,使用CDC类的pDC对象中绘制椭圆的函数
    三角类Triangle,使用CDC类的pDC对象中绘制多边形的Polygon函数(图片),参看微软官网上的函数用法,要把多边形的顶点放在一个坐标点数组里面,并指定多边形的顶点的个数
    文本Text类,采取自定义的字体来实现,旋转角度是自定义字体的一个参数

    解决方法
    使用CreateFontIndirect(const LOGFONT* lpLogFont)函数创建斜率字体,参数lpLogFont->lfEscapement是字体的角度。
    //创建自己的字体LOGFONT logfont;lstrcpy((LPSTR)logfont.lfFaceName,(LPSTR)"楷体_GB2312");logfont.lfWeight=700;logfont.lfWidth=40;logfont.lfHeight=70;logfont.lfEscapement=angle;//这个参数就是用来控制角度,这里是正常显示logfont.lfUnderline=FALSE;logfont.lfItalic=FALSE;logfont.lfStrikeOut=FALSE;logfont.lfCharSet=GB2312_CHARSET;hFont=CreateFontIndirect(&logfont);……// 下面就是使用该字体了hOldFont=(HFONT*)dc.SelectObject(hFont);
    3.2.2.2 设计对话框
    使用MFC的控件,来搭建对话框的界面,适当修改控件的ID值
    Combobox下拉框控件
    所用的函数GetCurSel()来获取鼠标焦点的值的序号,注意下拉框的sort属性,默认是true,会按照自然排序,这样和你添加内容的顺序就会不一样,可以改为falseAddString()来向下拉框控件里面添加内容,也可以到VS2015的属性框里面的data属性里面添加,Ctrl+Enter换行。
    Listbox列表框控件
    所用的函数GetCurSel()来获取鼠标焦点的值的序号;AddString()来向列表框控件里面添加内容。
    MFC ColorButton颜色选取控件
    所用的函数Getcolor()获取当前选择的颜色,类型是COLORREF,以RGB的形式储存
    Static Text静态文本控件
    用来制作前台界面。
    Edit Control编辑文本控件
    用来让用户输入参数值。
    3.3 View文件和Doc文件中的代码细节3.3.1 和对话框相关的功能使用控件的消息映射以及相关的成员函数来实现。
    初始化对话框(初始化函数)
    向下拉框以及列表框里面添加内容
    BOOL WAttribute::OnInitDialog()
    选择图形类型(控件消息)
    当用户选择的不是文本类型的对话框,就把和文本框有关的控件隐藏,得到下拉框所选序号,来判断是否要隐藏
    void WAttribute::OnCbnSelchangeCombo()
    选择颜色(控件消息)
    获取边框线型的颜色以及填充颜色,因为我这里定义的是颜色控件变量是control的变量类型,所以还要使用该类型的函数才能获取颜色的color值,其实如果仅是为了获取颜色值,可以直接给该控件绑定一个value的变量类型,我在这里还对颜色控件做了一些定制,详细代码见初始化对话框函数。
    void WAttribute::OnBnClickedLinecolor()
    ok控件(控件消息)
    把一些想在对话框点击确定后想保存的值:下拉框的选项,列表框的选项保存下来,供view文件使用,采取在对话框类里面自定义变量来实现
    void WAttribute::OnBnClickedOk()
    3.3.2 Doc数据文件使用一个动态数组来存放视图中绘制的图形的数组,则每个绘制图形就是数组中的一个元素。
    动态数组的实现原理:添加新的元素后,就把当前所有的元素copy以及新增的元素,再开辟一块新的内存空间来存放新的数组,实际上也是通过静态的普通数组来实现的。
    CObArray m_Elements;
    析构函数,释放每个图形的所占用的资源,以及这个动态数组。
    CWDemoDoc::~CWDemoDoc(){ //析构 父类指针指向的图形资源 函数 int i; WShape* p; if (m_Elements.GetCount() > 0) { for (i = 0; i < m_Elements.GetCount(); i++) { p = (WShape*)m_Elements[i]; delete p; } } m_Elements.RemoveAll();//释放数组}
    序列化函数,每个数组元素调用自己的序列化函数,面向对象的封装思想。
    void CWDemoDoc::Serialize(CArchive& ar){ m_Elements.Serialize(ar);}
    3.3.3 View视图文件鼠标左键加上Ctrl键弹出对话框功能

    设备坐标转化为逻辑坐标
    判断Ctrl键是否按下,来决定是否创建一个对话框
    获取鼠标点击的位置,要放在对话框对象之后,对话框弹出之前
    弹出对话框后根据用户选择的图形类型来创建相对应的图形及文本,我这里是通过比较用户选择的序号,用switch语句实现的
    每次在创建图形后要把它加入到动态数组中,最后刷新界面窗口,调用View文件的OnDraw函数绘制对应的图形

    只按下鼠标左键,而没有按下Ctrl键,则需要判断鼠标当前的落点又没在某个图形内

    把当前图形的相关参数传入到对话框中,供用户修改图形的相关的参数
    当用户按下OK键后,再把对话框界面的值传入到当前图形中,重新设置图元的属性的函数,这样刷新窗口后就改变当前图形

    void CWDemoView::OnLButtonDown(UINT nFlags, CPoint point)
    双击鼠标右键删除当前图元
    这个消息映射需要在使用时,需要注意把MFC框架自带的鼠标右键消息禁用,不然会有冲突。

    还是先把设备坐标转化为逻辑坐标
    用父类指针指向子类对象,调用子类对象的IsMatched函数,循环查找用户选中的是动态数组中的哪个图形,找到后使用动态数组对象自带的删除元素函数删除
    刷新窗口,图形消失
    绘图函数

    每次刷新完窗口后,执行这个这个函数,就会重新绘制view窗口。
    void CWDemoView::OnDraw(CDC* pDC){ CWDemoDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: 在此处为本机数据添加绘制代码 int i; WShape* p; if (pDoc->m_Elements.GetCount() > 0) { for (i = 0; i < pDoc->m_Elements.GetCount(); i++) { p = (WShape*)pDoc->m_Elements[i]; p->Draw(pDC); } }}
    四、运行效果4.1 运行初始画面
    4.2 弹出对话框画面
    4.3 创建图形和文本创建正方形,矩形,椭圆形,圆形,三角形,文本的过程。














    4.4 更改图形属性
    4.5 删除图形双击右键删除图形

    4.6 保存文档
    4.7 打开保存的文档打开刚才保存的文档,重新恢复图形画面

    五、设计小结通过这次课程设计,自己能够更好的查找网上资料,MFC的编程手册,自己独立解决问题的能力得到了提高,很感谢指导老师帮我解决我程序中的困惑之处。
    3 评论 65 下载 2019-03-08 17:39:45 下载需要9点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端C#和SQL SERVER数据库实现的餐饮管理系统

    摘 要餐饮管理系统作为一个餐饮的基本管理,是餐饮服务业对职工以及餐饮的日常管理。开发餐饮管理系统,正是完善餐饮业信息化管理的重要环节。人工操作已很难满足餐饮业信息化管理的要求,面对庞大的信息量,该方式现存在很多弊端。因此,建立现代化的智能管理系统势在必行。这样也大大减轻了餐饮业内部人员的工作量,提高了工作效率,使原本复杂和枯燥无味的工作变得简约而轻松。
    在系统设计中包括系统整体设计,逻辑框架与数据流程,各个功能模块划分,系统功能模块的设计与具体实现等部分。该系统侧重于顾客开台,点菜和结帐,通过已编制好的程序,完成对管理员的登录、桌台信息和职工信息的添加、查询,以及管理员的增、删、改、查等,本系统使用的开发工具是.NET开发程序,采用SQL Server2005数据库。实现餐饮数据及职工的数据采集、数据统计和信息查询过程,完善餐饮管理现代化,方便管理人员统计、考查员工工作情况,方便餐饮业管理部门查询宾馆一段时间内盈余情况,准确地掌握餐饮业近期情况和相关数据。
    关键词:餐饮管理;Visual C#.NET;SQL Server2005数据库
    1 项目介绍针对系统来说主要任务是设计一个餐饮管理系统,实现顾客的开台,点菜,结帐,和餐饮业职工的管理等功能。具体的设计任务如下:

    实现用户登录及修改密码及创建用户帐户
    能查看、查询、输入、添加职工基本信息
    能查看、查询、输入、添加桌台和包间基本信息
    能及时开台,为顾客点菜以及结帐
    能及时备份数据和恢复数据
    有一些辅助工具如日历计算机等

    2 需求分析餐饮管理系统是一个饮食产业不可缺少的一部分,它对于餐饮业的决策者和管理者来说都非常重要。本系统主要包括桌台显示、消费查询、人事档案及权限等几大部分,本系统具有良好的用户接口,使用方便。具有完善的查询,对维护系统起到辅助决策的作用,能及时、方便、灵活地进行查询、修改、删除等维护性操作。餐饮管理系统有足够的存储容量,满足酒店每日营业的变动,另外对于操作用户有一定的管理,并对用户的权限有一定的设置。
    餐饮管理系统的功能模块包括基本信息、辅助工具、系统维护、系统设置模块,其中系统设置模块可以实现口令修改和锁定系统。此模块通过修改密码和锁定系统提高系统安全性也方便工作人员操作。
    2.1 功能需求2.1.1 基本功能需求本课题要实现的是餐饮宾馆管理系统,在设计时应该有友好的用户界面,便于用户的操作,系统应有基本功能如下:

    用户登录功能
    职工和桌台相关信息的管理功能
    开台,点菜,结帐的功能
    查询功能
    用户信息管理功能

    2.1.2 用户界面需求对于一个好的软件有一个友好的用户界面是很重要的。用户界面应尽量做的简单、层次清晰明了,以最大限度为用户提供操作方便。如尽量减少用户输入次数,多使用快捷按扭等。
    2.1.3 开发环境介绍本系统使用的开发语言是Visual C# .net,数据库采用的是SQL Server2005,以Windows XP系统为操作平台。
    3 系统设计3.1 登陆模块3.1.1 模块功能本模块主要起登陆作用,判断用户何不合法,可不可以使用本软件,是本系统的第一个界面
    3.1.2 模块功能图
    3.1.3数据表数据库使用Microsoft SQL SERVER 2005,新建数据库命名为db_MrCy,在数据库中创建了6个数据表用于存储不同的信息,本系统设置模块用到的数据表是表tb_user,用于存放用户信息,如下:



    字段名
    数据类型
    长度
    主键
    描述




    id
    int
    4

    系统标号


    username
    varchar
    50

    用户登录名


    userpwd
    varchar
    50

    用户登录密码


    power
    int
    10

    用户权限



    3.1.4 模块技术分析
    该窗体用到的主要控件如下:

    两个TextBox控件:前一个用于输入用户账号,后一个用于输入登录密码
    两个Bottom控件:确定按钮用于确认登陆,取消按钮用于退出系统

    输入账号或密码为空,则跳出提示窗口:

    若输入账号密码错误,则跳出提示窗口:

    输入账号密码一致,进入下一窗口。
    点击退出按钮,跳出提示窗口:

    单击确定,退出系统。
    3.2 主界面模块3.2.1 模块功能用户通过登录界面登录之后,进入主模块界面。主模块界面上显示基础信息、辅助设计、系统维护、系统设置、帮助和退出菜单,方便用户进行相关操作。此外,主模块界面上通过两幅不同的图片形象的显示桌台或者大厅的空闲状态,用户通过双击图片可以进入另一个界面。如果用户双击的是表示空闲状态的图片,会提示“您已经开过台!请选择加点菜或者退出!”,那么进入另一个界面,就可以点击开台单、点/加菜和退出菜单,并进行相关操作。如果用户双击的是表示非空闲状态的图片,会提示“您没用开台!请选择开台!”,那么进入另一个界面上就不能点击开台单菜单,只能点击点/加菜和退出菜单,并进行相关操作。
    3.2.2 模块数据流图
    3.2.3 数据表


    字段名
    数据类型
    长度
    主键
    描述




    ID
    int
    4

    系统编号


    roomname
    char
    10

    桌台名称


    roomjc
    char
    10

    桌台简称


    roombjf
    decimal
    9

    桌台包间费


    roomwz
    char
    10

    桌台位置


    roomzt
    char
    10

    桌台状态


    roomtype
    char
    10

    桌台类型


    roombz
    varchar
    50

    桌台备注


    roomqt
    varchar
    50

    桌台其它信息


    guestname
    varchar
    50

    顾客姓名


    zhangdandate
    varchar
    50

    开台时间


    num
    int
    4

    顾客人数


    watername
    varchar
    50

    操作员姓名



    3.2.4 模块技术分析开发主模块中的桌台显示时,主要通过ListView控件实现的,系统首先从数据库中检索出每个桌台的状态,然后根据不同的状态通过ListView控件的Items属性中的ADD方法向控件中添加项目集合。
    主模块界面

    主模块用到的控件主要有:

    6个MenuScrip控件:分别用于点击基础信息、辅助工具、系统设置、关于、帮助和退出,方便用户进行相关操作
    1个ImageList控件:用于显示代表桌台状态的图片
    1个ListView控件:用于显示所有桌台

    主模块功能

    主模块提供基础信息、辅助工具、系统设置、关于、帮助和退出菜单,方便用户点击,进行相关操作
    若双击任意表示非空闲状态的图片,弹出以下对话框,提示用户已经开台


    点击确定,进入如图2.5界面,可以进行点/加菜或者退出操作。

    若双击表示空闲状态的界面,弹出以下对话框,提示用户,没有开台。

    点击确定,进入如图2.7界面,进行开台、点/加菜或者退出操作。

    3.3 开台模块3.3.1 模块功能在进入主模块界面之后,选择要进行开台的桌台号或者大厅号,双击图片进入另一个界面。在另一个界面上,单击开台单菜单,进入开台单模块界面。用户可以在该界面上选择服务员、输入顾客名称、用餐人数和备注,点击保存按钮,提示“已经保存成功!”。同时,返回到主模块界面上时,用户刚选择进行开台的桌台号或者大厅号的图片会变化为表示非空闲状态的图片,这样可以提示用户该桌台号或者大厅号已经开台。如果用户没有输入顾客名称和用餐人数,点击保存按钮后,会提示“顾客名称和用餐人数不能为空!”;点击退出按钮,返回到主模块界面。
    3.3.2 模块数据流图
    3.3.3 模块技术分析在开台单模块中用户可以对桌台编号、账单日期、顾客名称、用餐人数、服务员和备注进行录入或更改。数据库录入或修改完毕后,单击“保存”按钮完成开台单的操作。在开发此模块时,主要用到了数据库的更新技术。
    开台单模块界面

    开台单模块用到的控件主要有:

    4个TextBox控件:分别用于输入顾客名称、账单日期、用餐人数和备注
    2个ComboBox控件:分别用于显示桌台编号和服务员
    2个Button控件:分别用于保存数据和退出返回到主模块界面

    开台单模块功能

    选择桌台编号,服务员,并输入顾客名称、用餐人数和备注

    点击保存按钮,会弹出以下对话框,提示已经保存成功,即开台成功。

    如果用户没有输入顾客名称和用餐人数,点击保存按钮,会弹出以下对话框,提示顾客名称和用餐人数不能为空。


    点击退出按钮,返回到主模块界面。
    3.4 点菜结帐模块3.4.1 模块功能服务员在已开台的桌台单击进入点加菜窗体,根据顾客需要从菜品类别中选取菜,在信息文本中会显示菜品的信息,服务员只需输入菜的数量和选取负责服务员的名字,保存信息后系统记录顾客所点的菜品的信息,如果顾客不再需要,服务员可以立即删除记录,另外服务员还可以根据具体要求添加备注。在顾客享用过程中,如有需要服务员还可以再次调出桌台信息,记录顾客加菜的信息。在顾客享用完后,服务员只需点击桌台弹出点加菜窗体,确定信息完整正确,点击结账按钮弹出结账窗体,系统自动结算了顾客消费清单,列出了详细具体的消费情况供顾客查询,此外,系统还有为服务员计算找零的功能,提高了操作效率。
    3.4.2 模块数据流图
    3.4.3 数据表


    字段名
    数据类型
    数据长度
    主键
    数据描述




    ID
    Int
    4

    系统编号


    Foodnum
    Char
    10

    菜品编号


    Foodname
    Varchar
    50

    菜品名称


    Foodsum
    Char
    10

    菜品数量


    Foodallprice
    Decimal
    18

    菜单总价


    Waitername
    Varchar
    50

    服务员名


    Beizhu
    Varchar
    50

    备注


    Zhuotai
    Char
    10

    桌台


    Datatime
    Datetime
    50

    日期



    3.4.4 模块技术分析
    在桌台主界面菜单按钮点加菜菜单,激发单击事件,载入点加菜窗体。
    菜品分类列表

    创建treeview控件,读取数据库中数据,根据类别创建节点。
    菜品信息

    读取数据库中顾客菜品信息,将数据显示在datagridview控件中,服务员输入菜品数量,完整信息,否则系统自动提示。
    菜品记录

    点击保存按钮,将文本中的菜品信息写入数据库中,并保存桌台信息。
    删除记录

    选中下表中顾客数据,点击删除按钮删除数据表中数据。
    结账模块

    点击结账按钮,弹出结账窗体,弹出结账窗体,并在label控件中显示消费情况。
    消费情况

    在datagridview控件中调取数据库中顾客点菜数据。
    找零

    根据消费总额及各科支付的金额,系统给出找零金额。
    3.5 桌台信息管理模块3.5.1 模块功能桌台信息模块主要实现的功能是对桌台信息的添加、查询、修改和删除。选择该窗体以后,如果需要添加信息,用户需要填写添加的内容,然后按添加按钮进行添加,修改信息时,用户需要先从显示数据中选择需要修改的数据,将相关修改信息填写完成后点击修改按钮,查询时输入桌台号,点击查询,即可显示详细信息的窗口,选择数据后可直接点击删除,桌台信息即从数据库中删除成功,若要取消操作,直接点击取消即可。
    3.5.2 模块功能图
    3.5.3 数据表数据库使用Microsoft SQL SERVER 2005,新建数据库命名为MrCy,在数据库中创建了2个数据表用于存储桌台和职员的信息。



    字段名
    数据类型
    长度
    主键
    描述




    Id
    int
    4

    系统编号


    Roomname
    char
    10

    桌台名称


    Roomjc
    char
    10

    桌台简称


    Roombjf
    decimal
    9

    桌台包间费


    Roomwz
    char
    10

    桌台位置


    Roomzt
    char
    10

    桌台状态


    Roomtype
    char
    10

    桌台类型


    Roombz
    varchar
    50

    桌台备注


    Roomqt
    varchar
    50

    桌台其他信息


    Guestname
    varchar
    50

    顾客姓名


    Zhagndandate
    varchar
    50

    开台时间


    Num
    int
    4

    顾客人数


    Waitername
    varchar
    50

    操作员姓名



    3.5.4 模块技术分析新建一个Windows窗口,命名为ZTXX.cs,主要用于实现对数据库中桌台信息的操作,界面如下图所示。

    该窗体用到的主要控件如下:

    6个TextBox控件,用途:接收输入或是从数据库中选择的数据,显示选择的数据
    6个Label控件,用途:标记文本框的内容
    1个DataGridView控件,用途:显示数据库内容
    6个Button控件,用途:分别实现添加、修改、取消、查询、删除、退出的功能

    在查询功能中还调用了ZTXXXX.cs窗口,如下图所示。

    该窗体的主要控件如下:

    9个Label控件,用途:标记文本框的内容
    9个TextBox控件,用途:显示所查询的用户的详细信息
    1个Button控件,用途:退出该窗口,回到上一级窗口

    3.6 职工信息管理模块3.6.1 模块功能职员信息模块的功能和桌台信息模块基本相似。
    3.6.2 模块功能图
    3.6.3 数据表


    字段名
    数据类型
    长度
    主键
    描述




    Id
    Int
    4

    系统编号


    Waitername
    Varchar
    50

    职员姓名


    Cardnum
    Varchar
    50

    身份证号码


    Waiternum
    Char
    10

    职员编号


    Sex
    Char
    10

    性别


    Age
    Char
    10

    年龄


    Tel
    Varchar
    50

    电话



    3.6.4 模块技术分析新建一个Windows窗口,命名为ZYXX.cs,主要用于实现对数据库中职员信息的操作,界面如下图所示。

    同样在查询时也调用了ZYXXXX.cs窗口,如下图所示。

    该模块用到的主要控件基本和桌台信息模块的相同。
    3.7 系统设置模块3.7.1 模块功能系统设置模块主要实现的功能是对管理员的添加、查询、修改和删除,以及软件的锁定和数据库的备份和还原。选择该窗体以后,如果需要添加管理员,用户需要填写添加的内容,然后按添加按钮进行添加,修改信息时,用户需要输入管理员名称,将相关修改信息填写完成后点击修改按钮,查询时点击查询,即可显示所有管理员的窗口,数据库的备份和操作只需点击相应按钮就好,点击锁定软件后必须键入管理员密码才可解锁。
    3.7.2 模块功能图
    3.7.3 数据表数据库使用Microsoft SQL SERVER 2005,新建数据库命名为db_MrCy,在数据库中创建了6个数据表用于存储不同的信息,本系统设置模块用到的数据表是表tb_user,用于存放用户信息,如下:



    字段名
    数据类型
    长度
    主键
    描述




    id
    int
    4

    系统标号


    username
    varchar
    50

    用户登录名


    userpwd
    varchar
    50

    用户登录密码


    power
    int
    10

    用户权限



    3.7.4 模块系统分析用户管理模块界面:

    该窗体用到的主要控件如下:

    2个TextBox控件:前一个用于输入新密码,后一个用于重新输入密码以确认
    2个Bottom控件:确定按钮用于确认修改密码,取消按钮用于退出设置

    用户管理模块功能:

    添加用户:该模块可以添加用户,重复输入密码,如不一致出现出错提醒,各项均为必填。


    修改用户:该模块可修改用户的各项信息,重复输入密码,如不一致出现出错提醒,各项均为必填。


    删除用户:该模块可删除用户,通过用户名来匹配要删除的用户,通过密码来核对,如密码错误则提醒出错。


    查看用户信息

    锁定模块界面:

    该窗体用到的主要控件如下:

    1个TextBox控件:用于输入解锁密码
    1个Bottom控件:解锁按钮用于确认解锁

    系统流程图该窗体用到的主要控件如下:

    2个TextBox控件:前一个用于输入新密码,后一个用于重新输入密码以确认
    2个Bottom控件:确定按钮用于确认修改密码,取消按钮用于退出设置

    锁定系统模块功能:

    输入解锁密码,若密码与登录用户密码不符,则弹出提示框:

    系统维护模块界面

    备份系统

    该模块可以及时的备份数据库,以免出现不可抗拒的因素使得数据丢失。
    恢复系统

    数据得到备份后利用该模块可以使得数据库得以及时的恢复。
    3.8 辅助工具和关于以及帮助模块3.8.1 模块功能本模块主要提供一下小软件,方便用户使用,只需单击主界面上相应按钮即可。
    3.8.2 模块界面
    4 总 结本次实习已接近尾声,经过近一周的艰苦奋战,我们的系统终于基本完成,虽然感到比较累,但看到自己亲手做出的系统,心中却充满了喜悦。这周对我来说是比较累,却很充实的一段时光。期间,有苦,有乐。这是我第一次进行团队合作并完成系统,让我学到了很多,明白了很多,进步了很多,成熟了很多。我作为我们小组的组长,刚开始觉得自己身上的胆子比较重,但是组员相信我,给我信心让我勇于挑战。
    记得刚开始,对这个系统还很陌生,有很多领域知识都不知道,经过老师的讲解和在网上搜索,我们知道了餐饮业的基本运行情况,管理软件在宾馆运营的作用及地位,管理软件要实现的基本功能。之后,在老师的指导要求下我们开始进行需求分析及任务分工。接下来就是分配编写代码任务,刚开始以为基本任务也不过如此,决定在三天内完成,由于我的数据库设计有些失误,导致我们六个人在编写时有些矛盾的思想,六个人的实现功能与计划不一致,三个模块的功能不统一,认识到问题之后我进行深刻的反省,此后我深刻明白在团队的合作中,任何人的一点点失误,就有可能对整个团队造成重大损失;个人不能搞独立,必须融入团队中,再强编程能力的人自己也很难完成一个功能良好的软件。
    在最后阶段,随着各项工作逐渐完成,欢乐的心情也像清流一样缓缓淌入心中,看着这个经过自己团队努力终于等到的丰收的成果。我在这期间不仅学到了书本上没有的东西,还掌握了一些学习方法,奋斗的经验,也认识到在平时的课外生活中,取各方面营养,这样,才有更多的勇气勇于面对未来的生活中挑战。
    参考文献[1] 马煜,Visual C#.NET案例开发集锦,北京:电子工业出版社,2005
    [2] 李乃文 傅游,C#程序设计实践教程,北京:清华大学出版社,2007
    [3] 郭东恩,数据库原理与应用,河南:河南科学技术出版社,2008
    3 评论 83 下载 2018-11-16 12:33:21 下载需要7点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端java语言的C/S模式网络聊天室软件

    一 需求分析
    采用C/S模式,be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端TCP协议编程的方式,使得各个用户通过服务器转发实现聊天的功能
    分为三大模块:客户端模块、服务器端模块和公共辅助类模块
    客户端模块的主要功能:

    登陆功能:用户可以注册,然后选择服务器登入聊天室
    显示用户:将在线用户显示在列表中
    接收信息:能接收其他用户发出的信息
    发送信息:能发出用户要发出的信息

    服务器端模块的主要功能:

    检验登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就允许用户登陆
    显示在线状态:将该用户的状态发给各在线用户
    转发聊天信息:将消息转发给所有在线的用户

    公共辅助类模块的主要功能:

    定义完整的消息传递机制
    对消息转发的方式进行有效约束
    规定消息类型


    二 程序设计2.1 程序设计思想实现网络聊天室编程,关键在于Socket通信,程序的功能都是在Socket的基础上一层一层增加的。
    实现Socket通信的基本方法为以下4个步骤:

    客户端与服务器端分别实例化ServerSockot/Socket
    打开连接到Socket的面向对象输入输出流
    利用输入输出流按照TCP协议对Socket进行读写操作
    关闭输入输出流和Socket

    我们要实现的功能都是在第3步对Socket的输入输出流做相应的操作:

    涉及到多客户端并发访问,必须用线程进行控制,不同的处理线程为不同的客户服务,主线程只负责循环等待,处理线程负责网络连接,接受客户输入的信息,根据消息类型对消息转发。
    2.2 系统模块划分客户端

    Client类模块,ClientUI界面模块,ClientMsgType消息处理模块
    服务器

    Server类模块,ServerHandler模块,ServerMsgType消息处理模块
    公共类:

    Message消息结构类,Common公共函数类,Config系统配置类
    系统模块结构图

    2.3 模块功能设计客户端

    Client类模块:与服务端建立连接,完成客户端登录,实现消息的群聊,私聊,用户列表更新,文件转换等功能
    ClientUI界面模块:客户端窗口界面,实现用户友好,方便用户使用,在窗口上有消息显示,用户列表,消息类型,在线人数等视图信息
    ClientMsgType消息处理模块:定义了常用的消息处理方法

    服务端

    Server类模块:启动监听,与客户端建立连接
    ServerHandler模块:提供线程管理,实现多用户的管理。针对每一个用户发过来的消息,进行相应处理,再转发给客户
    ServerMsgType消息处理模块:对客户端发送的消息进行指定操作模式处理,只进行消息转发,涉及一对多和一对一两种模式

    公共类

    Message消息结构类:客户端和服务器传输的消息被定义为类,通过对Message对象的序列化传输
    Common公共函数类:提供文件序列化的处理以及常用的功能性函数
    Config系统配置类:包含连接IP及端口号的配置信息

    三 程序实现3.1 客户端实现Client类模块
    关键模块,通过服务器IP地址与端口建立连接。客户端有套接字和输入输出流。首先输入用户名,然后包装成Message对象发送给服务器,之后进入主循环对来自服务器的消息进行处理。
    public void run() { try { // 获取用户名 while (name == null || name.equals("")) name = JOptionPane.showInputDialog("请输入名字").trim(); // 第一次运行,发送登陆消息 send(new Message("login", name, null, null)); // 显示界面 ui = new ClientUI(this, name + " 的客户端"); // 消息处理主循环 while (true) { Message rcv = (Message) in.readObject(); // 服务器端发来的消息 System.out.println(rcv.toString()); new ClientMsgType(this, rcv).process(); } } catch (Exception e) { System.out.println(e.toString() + " 客户端退出"); } }
    ClientUI类模块
    用户界面,所有的界面元素及相关的操作都在里面定义了方法,不论UI界面如何改变都不会影响到外部类。里面含有各种控件极其功能定义,还包括文件传输。主体代码如下:
    public ClientUI(Client client, String winname) { super(winname); // 继承父类的名字 setSize(600, 400); this.client = client; // 消息文本显示区域 msgArea = new JTextArea(400, 400); msgArea.setEditable(false); textAreaScrollPane = new JScrollPane(msgArea); add(textAreaScrollPane, BorderLayout.CENTER); // 发送消息区域 textFieldPanel.setLayout(new FlowLayout(0, 10, 10)); add(textFieldPanel, BorderLayout.SOUTH); clientList = new JComboBox<String>(); // 在线用户列表 clientList.addItem("All"); textFieldPanel.add(clientList); msgType = new JComboBox<String>(); // 聊天文本或者文件 msgType.addItem("chat"); msgType.addItem("file"); textFieldPanel.add(msgType); msgField = new JTextField(20); // 输入消息文本 textFieldPanel.add(msgField); btn = new JButton("发送"); // 发送消息按钮 btn.setMnemonic(KeyEvent.VK_ENTER); textFieldPanel.add(btn); cntLabel = new JLabel("在线人数:1"); // 显示在线人数 textFieldPanel.add(cntLabel); // 发送消息按钮监听器 btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String type = (String) msgType.getSelectedItem(); String title = ""; String content = getText().trim(); byte[] fbyte = null; if (content.equals("")) { JOptionPane.showMessageDialog(client.ui, "输入不能为空"); return; } if (type.equals("file")) { // 获取客户端发送文件 JFileChooser dlg = new JFileChooser(); dlg.setDialogTitle("选择文件"); int result = dlg.showOpenDialog(client.ui); if (result == JFileChooser.APPROVE_OPTION) { File file = dlg.getSelectedFile(); fbyte = Common.file2Byte(file); title = file.getName(); } else { return; } append("TO " + getName() + ": " + title + "\n"); } append("TO " + getName() + ": " + content + "\n"); client.send(new Message(type, client.name, getName(), title, content, fbyte)); clear(); } }); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { client.close(); System.exit(0); } }); setVisible(true);}
    ClientMsgType类模块
    定义了客户端处理消息的方法,主体架构和服务区类似,这里我们只介绍处理文件的方法:
    /** * 文件处理 利用字节数组可以处理所有文件 */ public void file() { String toAll = "[public]"; if (msg.getTo().equals(client.name)) toAll = "[private]"; client.ui.append(toAll + msg.getFrom() + ": " + msg.getContent() + "\n"); int confirm = JOptionPane.showConfirmDialog(client.ui, "收到了来自" + msg.getFrom() + "的文件:" + msg.getTitle() + ",需要保存吗?"); if (confirm != JOptionPane.YES_OPTION) return; // 获取保存路径 JFileChooser dlg = new JFileChooser(); dlg.setDialogTitle("选择保存路径"); dlg.setSelectedFile(new File(msg.getTitle())); int result = dlg.showSaveDialog(client.ui); if (result != JFileChooser.APPROVE_OPTION) return; File file = dlg.getSelectedFile(); if (file.exists()) { int copy = JOptionPane.showConfirmDialog(null, "是否要覆盖当前文件?", "保存", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (copy == JOptionPane.YES_OPTION) { dlg.approveSelection(); } } else { dlg.approveSelection(); } if (Common.byte2File(msg.getFile(), file)) { JOptionPane.showMessageDialog(client.ui, "文件保存成功"); } else { JOptionPane.showMessageDialog(client.ui, "文件保存失败"); }}
    3.2 服务器实现Server类模块
    创建ServerSocket,在指定端口监听,当有用户登录,接受套接字输入流,显示其登录信息,调用ServerHandler线程进行管理。
    public Server(int port) { try { @SuppressWarnings("resource") ServerSocket server = new ServerSocket(port); while (true) { Socket conn = server.accept(); // 建立客户端套接字 // 新建线程和客户端建立全双工通信 new Thread(new ServerHandler(conn)).start(); } } catch (Exception e) { System.out.println(e.toString()); } }
    ServerHandler模块
    服务端的核心,其中包含客户端线程连接类,套接字及输入输出流的初始化。每个新连接的客户端被初始化为一个ServerHandler对象线程,首先进行的是客户端登陆合法化检验,通过后将客户端添加到服务器线程池并通知所有在线用户。之后采用一个无限循环来和该客户端进行双向通信。
    代码中数据结构定义:
    // 输入流private ObjectInputStream in; // 输出流private ObjectOutputStream out; // 用户名private String name;// 把用户线程放入对象数组private static ArrayList<ServerHandler> clientList = new ArrayList<ServerHandler>(); // 把用户名和连接线程关联便于查找private static HashMap<String, ServerHandler> clientMap = new HashMap<>();
    初始化代码
    public ServerHandler(Socket socket) { try { in = new ObjectInputStream(socket.getInputStream()); out = new ObjectOutputStream(socket.getOutputStream()); } catch (IOException e) { System.out.println(e.toString() + " 服务端初始化失败"); } }
    核心代码
    public void run() { if (!loginVerify()) return; // 登陆校验 try { addClient(); // 客户端经过登陆检验 添加到列表 sendMessage(new Message("online", name, "All", "上线了!")); // 广播用户列表 while (true) { Message rcv = (Message) in.readObject(); // 等待客户端消息 sendMessage(rcv); } } catch (Exception e) { System.out.println(e.toString() + " 客户端已退出"); } finally { removeClient(); sendMessage(new Message("offline", name, "All", "下线了!")); // 广播下线通知 } }
    登陆校验
    private Boolean loginVerify() { try { Message rcv = (Message) in.readObject(); System.out.println(rcv.toString()); this.name = rcv.getFrom(); if (clientMap.containsKey(name)) { // 用户名重复 sendToClient(this, new Message("login", null, name, "用户名已存在")); return false; } } catch (Exception e) { System.out.println(e.toString() + "登陆检验失败"); return false; } return true; }
    消息广播
    把msg消息发送给每一个用户。其中clientList是ServerHandler的客户端容器类型,可以指向每一个用户。clientMap 是用户名到线程的映射。
    public void sendAllClient(Message msg) { String name = msg.getFrom(); ServerHandler sh = clientMap.get(name); synchronized (clientList) { for (ServerHandler client : clientList) { if (client != sh) { sendToClient(client, msg); } } } }
    上线提醒
    sendClientList函数:更新用户列表,当有新用户上线时,对以前的用户的好友列表,加上这个新用户名字,对于这个新用户,加上所有用户的名字。通过将消息包装成Message对象进行数据交互。
    public synchronized void sendClientList(Message msg) { // 新上线的用户 ServerHandler newclient = clientMap.get(msg.getFrom()); for (ServerHandler client : clientList) { if (client == newclient) continue; // 给新上线用户所有列表 sendToClient(newclient, new Message(msg.getType(), client.name, newclient.name, null)); // 更新老用户 sendToClient(client, new Message(msg.getType(), newclient.name, client.name, msg.getContent())); }}
    ServerMsgType模块
    定义了服务端对客户端发送消息的处理方式。消息包装成Message类,经过序列化后在服务器和客户端间传输。服务端根据消息的收发对象和类型进行转发。这里利用到Java的反射机制,根据消息类型获取相应处理函数。
    public class ServerMsgType { ServerHandler server; Message msg; public ServerMsgType(ServerHandler server, Message msg) { this.server = server; this.msg = msg; } public void process() { try { Method method = this.getClass().getDeclaredMethod(msg.getType()); method.invoke(this); } catch (Exception e) { System.out.println(e.toString() + " 使用了未定义的操作"); try { Method method = this.getClass().getDeclaredMethod("chat"); method.invoke(this); } catch (Exception e1) { System.out.println(e1.toString() + " 默认处理失败"); } } } public void chat() { if (msg.getTo().equals("All")) { // 给所有人发送消息 server.sendAllClient(msg); } else { // 发送消息给指定的人 server.sendToClient(msg); } } public void online() { server.sendClientList(msg); } public void offline() { server.sendAllClient(msg); } public void login() { server.sendToClient(msg); }}
    3.3 公共类实现Message模块
    底层数据封装的核心。所有的消息全部通过封装成Message从而在服务器和客户端之间收发。主体内容如下:
    private String type; // 消息类型private String from; // 来源private String to; // 目的private String title; // 附件名private String content; // 消息内容private byte[] file; // 附件内容
    其中系统已经定义的消息类型包括:

    chat:聊天内容、online:客户端上线、offline:客户端下线、login:客户端登陆
    每种类型在服务器和客户端的MsgType类中都有定义对应的处理函数
    From字段标识消息发送的来源,为客户端的用户名
    To字段标识消息发送的对象,为客户端的用户名,如果为All则是广播消息
    Title字段当发送文件时有效,为原文件名
    Content字段为消息的内容
    File字段为附件的字节数组

    把以上字段组装成类之后经过序列化就可以在客户端和服务器之间传输。
    Common模块
    定义了文件处理相关的函数,这里我们把文件作为字节数组处理,这样实现了文件的透明化传输。
    文件转化为字节数组
    public static byte[] file2Byte(File file) { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int len = 0; try { FileInputStream fin = new FileInputStream(file); len = fin.read(buffer); fin.close(); } catch (Exception e) { System.out.println(e.toString() + " 文件无法转化成字节"); } byte[] ret = new byte[len]; for (int i = 0; i < len; i++) ret[i] = buffer[i]; return ret; }
    字节数组转化为文件
    public static boolean byte2File(byte[] in, File out) { try { FileOutputStream fout = new FileOutputStream(out); fout.write(in); fout.close(); } catch (Exception e) { System.out.println(e.toString() + " 字节转换失败"); return false; } return true; }
    Config模块
    主要包括IP和port的配置。
    四 运行测试4.1 客户端进入聊天室在客户端输入名字进入聊天室,如果名字重复会弹框提示。


    4.2 聊天界面聊天界面显示客户端名字,好友列表,在线人数,消息类型等信息。

    4.3 选择聊天类型4.3.1 聊天类型为chat分为群聊和私聊:群聊是选择All,私聊是选择具体的用户名。


    4.3.2 聊天类型为file发送文件,可以输入描述信息,客户端可以选择是否接收文件。




    4.4 人数动态刷新
    2 评论 100 下载 2018-11-04 21:43:30 下载需要4点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端C语言的银行业务模拟系统

    1.需求分析1.1 问题描述客户业务分为两种。第一种是申请从银行得到一笔资金,即取款或借款。第二种是向银行投入一笔资金,即存款或还款。银行有两个服务窗口,相应地有两个队列。客户到达银行后先排第一个队。处理每个客户业务时,如果属于第一种,且申请额超出银行现存资金总额而得不到满足,则立刻排入第二个队等候,直至满足时才离开银行;否则业务处理完后立刻离开银行。每接待完一个第二种业务的客户,则顺序检查和处理(如果可能)第二个队列中的客户,对能满足的申请者予以满足,不能满足者重新排到第二个队列的队尾。注意,在此检查过程中,一旦银行资金总额少于或等于刚才第一个队列中最后一个客户(第二种业务)被接待之前的数额,或者本次已将第二个队列检查或处理了一遍,就停止检查(因为此时已不可能还有能满足者)转而继续接待第一个队列的客户。任何时刻都只开一个窗口。假设检查不需要时间。营业时间结束时所有客户立即离开银行。
    写一个上述银行业务的事件驱动模拟系统,通过模拟方法求出客户在银行内逗留的平均时间。
    1.2 测试数据一天营业开始时银行拥有的款额为10000(元),营业时间为600(分钟)。其他模拟参量自定,注意测定两种极端的情况:一是两个到达事件之间的间隔时间很短,而客户的交易时间很长,另一个恰好相反,设置两个到达事件的间隔时间很长,而客户的交易时间很短。
    1.3 实现提示事件有两类:到达银行和离开银行。初始时银行现存资金总额为total。开始营业后的第一个事件是客户到达,营业时间从0到closetime。到达事件发生时随机地设置此客户的交易时间和距下一到达事件之间的时间间隔。每个客户要办理的款额也是随机确定的,用负值和正值分别表示第一类和第二类业务。变量total、closetime以及上述两个随机量的上下界均交互地从终端读入,作为模拟参数。
    两个队列和一个事件表均要用动态存储结构实现。注意弄清应该在什么条件下设置离开事件,以及第二个队列用怎样的存储结构实现时可以获得较高的效率。注意:事件表是按时间顺序有序的。
    1.4 设计任务本程序是模拟银行存取款的流程。模拟客户在银行办理存取款的排队以及办理过程,并计算出客户总的逗留时间。
    程序的设计是需要实现两个排队队列(Q1、Q2),一个事件队列(Q_en)。队列1(Q1)和队列2(Q2)用于模拟客户的排队情况,客户从队尾开始排队,从队头出队。事件队列(Q_en)用于记录客户的到达/离开事件,客户到达时记录到达事件,客户办理完存取款后离开时记录离开事件。到达事件记录客户的序列号、办理金额、到达时间;离开事件记录客户的序列号、办理金额、离开时间。
    客户的到达时间是随机确定的(以客户最大到达时间arriveMaxTime为上界,客户最小到达时间arriveMinTime为下界)。客户若办理完存取款离开则离开时间由客户的到达时间加上交易时间(交易时间由dealMaxTime和dealMinTime随机确定)。客户的交易额由最大交易额上限(MaxMoney)随机确定,规定负数为取款,正数为存款。
    开始时,客户到达银行进入队列1(Q1)排队同时记录客户的到达事件将事件存到事件队列(Q_en)。如果客户办理存款,则更新银行的存款(total_money),然后将客户结点从队列1(Q1)删除,同时事件表(Q_en)记录客户的离开事件。如果客户办理取款,当银行当前的金额(total_money)能够满足客户的取款需求,则更新银行的存款(total_money),然后将客户结点从队列1(Q1)删除,同时事件表(Q_en)记录客户的离开事件。当银行当前的金额(total_money)不能够满足客户的取款需求,则将客户移到队列2(Q2)进行等待。每当队列1(Q1)办理完一次存款操作的时候就顺序检查队列2(Q2),查找能够完成取款操作的客户,当队列2(Q2)当前客户完成取款则更新银行存款(total_money),然后将客户从队列2(Q2)中删除,同时事件表(Q_en)记录客户的离开事件,接着转到队列1(Q1)接待客户。如果队列2(Q2)中当前客户无法完成取款则将队客户移到队列2(Q2)的队尾继续排队,接着检查下一个客户。
    当银行营业结束,检查队列1(Q1)和队列2(Q2)将还在排队的客户删除同时更新客户总逗留时间和接待客户总数。最后输出客户排队情况、接待客户总人数(counter)、需要存款的人数(n_p)、成功存款的人数(s_p)、需要取款的人数(n_g)、成功取款的人数(s_g)、客户逗留总时间(totalTime)、客户逗留平均时间(totalTime/ counter)以及银行现存金额(total_money)。
    1.5 输入的形式和输入值的范围银行模拟程序需要用户输入以下几个参量:

    银行初始存款(total_money)
    银行营业时间(closeTime)
    客户最大到达时间间隔(arriveMaxTime)
    客户最小到达时间间隔(arriveMinTime)
    业务最大处理时间(dealMaxTime)
    业务最小处理时间(dealMinTime)
    最大交易额上限(MaxMoney)

    参量输入要求用户从终端输入。
    total_money、closeTime、arriveMaxTime、dealMaxTime、MaxMoney、arriveMinTime、dealMinTime要求是一个大于零的整数。
    同时arriveMinTime不能大于 arriveMaxTime,dealMinTime不能大于dealMaxTime。
    以及arriveMinTime、arriveMaxTime、dealMinTime、dealMaxTime均不能大于closeTime
    1.6 输出的形式银行模拟程序通过dos界面输出银行营业过程的整个排队结果以及银行办理业务的结果。
    输出:

    需要存款的客户人数(n_p)
    需要取款的客户人数(n_g)
    成功存款的客户人数(s_p)
    成功取款的客户人数(s_g)
    客户逗留总时间(totalTime)
    接待客户总数(counter)
    客户逗留平均时间(totalTime/counter)
    银行结业余额(total_money)

    1.7 程序所能达到的功能程序可以根据用户自定输入的合法参量(银行初始存款(total_money)、银行营业时间(closeTime)、客户最大到达时间间隔(arriveMaxTime)、客户最小到达时间间隔(arriveMinTime)、业务最大处理时间(dealMaxTime)、业务最小处理时间(dealMinTime)、最大交易额上限(MaxMoney))来模拟银行的存取款业务。通过模拟输出结果包括客户排队情况、接待客户总人数(counter)、需要存款的人数(n_p)、成功存款的人数(s_p)、需要取款的人数(n_g)、成功取款的人数(s_g)、客户逗留总时间(totalTime)、客户逗留平均时(totalTime/ counter)以及银行现存金额(total_money)。
    1.8 测试数据1.8.1 第一次测试
    银行初始存款(total_money):10000
    银行营业时间(closeTime):600
    客户最大到达时间间隔(arriveMaxTime):20
    客户最小到达时间间隔(arriveMinTime):10
    业务最大处理时间(dealMaxTime):20
    业务最小处理时间(dealMinTime):10
    最大交易额上限(MaxMoney):5000


    输出结果

    1.8.2 第二次测试让两个到达事件之间的间隔时间很短,而客户的交易时间很长。

    银行初始存款(total_money):10000
    银行营业时间(closeTime):600
    客户最大到达时间间隔(arriveMaxTime):5
    客户最小到达时间间隔(arriveMinTime):3
    业务最大处理时间(dealMaxTime):50
    业务最小处理时间(dealMinTime):40
    最大交易额上限(MaxMoney):5000


    输出结果

    1.8.3 第三次测试让两个到达事件之间的间隔时间很长,而客户的交易时间很短。

    银行初始存款(total_money):10000
    银行营业时间(closeTime):600
    客户最大到达时间间隔(arriveMaxTime):50
    客户最小到达时间间隔(arriveMinTime):40
    业务最大处理时间(dealMaxTime):5
    业务最小处理时间(dealMinTime):3
    最大交易额上限(MaxMoney):5000


    输出结果

    1.8.4 第四次测试测试输入非法数据的情况。

    2.概要设计2.1 数据类型的定义2.1.1 结构体定义/*客户/事件结构体*/typedef struct event{ int type;//事件类型到达或者离开 0为到达,1为离开 int arriveTime;//到达时间 int leaveTime;//离开时间 int money;//存款数,正数为存款,复数为取款 int num;//客户编号 event* next;}event,*eventLink;/*队列结构体*/typedef struct QNode{ eventLink front;//队头指针 eventLink rear; //队尾指针 }QNode,*Queue;
    2.1.2 队列抽象数据类型的定义ADT Queue{ 数据对象:D={ ai | ai∈event, i=1,2,...,n, n≥0 } 数据关系:R1={ <ai-1, ai>|ai-1, ai∈D, i=2,...,n } 基本操作: eventLink get_front(Queue &q); 初始条件:队列q存在 操作结果:返回队头结点指针 void push(Queue &q,eventLink e); 初始条件:队列q存在,结点指针e存在 操作结果:将e指向的结点插入到队列q的队尾 void destoryQueue(Queue &q); 初始条件:队列q存在 操作结果:销毁队列q,释放空间 void pop(Queue &q); 初始条件:队列q存在 操作结果:删除对头结点并释放结点的空间}ADT Queue
    2.1.3 全局变量的定义int total_money; //银行现存款int closeTime; //银行结束营业的时间int arriveMaxTime; //两个到达事件的时间间隔上限int arriveMinTime; //两个到达事件的时间间隔下限int dealMaxTime; //客户交易之间的时间上限int dealMinTime; //客户交易之间的时间下限int MaxMoney; //交易额上限int currentTime=0; //当前时间int totalTime; //客户逗留总时间int counter=0; //客户总数int number=1; //客户初始号码int flag=1; //判断是否有窗口在处理int TimeOfDeal; //交易时间int MaxTime; //到达时间Queue Q_en; //事件队列 Queue Q1; //队列一 Queue Q2; //队列二
    2.1.4 函数类型定义/** 结束函数 当银行营业结束的时候调用此函数,清理释放申请的空间*/void closeBank();/** 到达函数 当客户到达时调用此函数,随机生成客户信息以及相应的到达事件,分别加入队列1和事件队列。*/void arrive();/** 存款函数 当客户办理存款的时候调用此函数*/void putMoney();/** 取款函数 当客户办理取款的时候调用此函数*/void getMoney();/** 查找函数 查找队列q中第一个可以满足取款的结点并返回,若是查找失败则返回NULL*/eventLink search(Queue &q,int m);/** 处理函数 对通过【查找函数】找到的结点进行取款处理,生成相应的离开事件*/void findAndDeal();/** 初始化函数 初始化三个队列,为三个队列分配空间*/void initQueue();/** 主函数*/int main();
    2.2 主程序的流程主程序首先先接收用户的数据输入,并对用户输入的数据进行验证,如果输入的数据不合法则要求用户重新输入。
    当用户输入的数据合法后开始主要程序的运行。首先先调用initQueue()函数对队列进行初始化,以及根据客户到达时间的上下界随机生成第一个客户的到达时间。当当前时间(currentTime)小于银行结业时间(closeTime)时进行循环。每循环一次当前时间加1。
    在每一次循环当中进行四次判断。

    当交易时间(TimeOfDeal)小于当前时间(currentTime)的时候,让交易时间等于当前时间
    当交易时间等于当前时间时,让flag为1表示当前有窗口在办理业务
    当到达时间(MaxTime)等于当前时间(currentTime)的时候调用arrive()函数让客户到达加入队列1(Q1)排队并在事件表(Q_en)中加入到达事件,同时随机生成下一个客户到达时间(MaxTime)
    当窗口处于交易状态(flag=1)且队列1(Q1)不为空。则进行客户交易处理,当客户是存款类型的时候调用putMoney()进行存款操作,同时调用findAndDeal()函数对队列2(Q2)进行检查是否有满足取款的客户并进行处理。当客户是取款类型的时候调用getMoney()进行取款处理

    每一次循环当前时间(currentTime)加1,直到银行营业结束退出循环,输出模拟结果,最后调用closeBank()函数结束程序。
    2.3 各模块的调用关系程序分成主程序模块、存款模块、取款模块、检查处理模块、事件处理模块。主程序模块负责调用存款模块、取款模块和事件处理模块。存款模块调用事件处理模块、检查处理模块。取款模块和检查处理模块调用事件处理模块。
    3.详细设计3.1 数据类型的实现3.1.1 队列抽象数据结构的实现//入队操作void push(Queue &q,eventLink e){ if(e==NULL){//结点指针为空 return; } if(q->front==NULL){//队列为空 q->front=e; q->rear=e; }else{ q->rear->next=e; q->rear=q->rear->next; }}//销毁队列void destoryQueue(Queue &q){ eventLink e,e1; e=q->front; if(q->front==q->rear==NULL){//队空 return; } while(e!=NULL){ e1=e->next; free(e); e=NULL; e=e1; } }//删除队首元素 void pop(Queue &q){ eventLink e; e = q->front; if(q->front==NULL){//队列为空 return; }else if(q->front->next==NULL){//队列只有一个元素 q->front=q->rear=NULL; }else{ q->front=q->front->next; } free(e);//释放空间 e=NULL;}//返回队首元素 eventLink get_front(Queue &q){ return q->front; }
    3.1.2 函数类型的实现/** 结束函数 当银行营业结束的时候调用此函数,清理释放申请的空间/void closeBank(){ //调用destoryQueue()函数销毁三个队列Q1、Q2、Q_en destoryQueue(Q1); destoryQueue(Q2); destoryQueue(Q_en);}/** 到达函数 当客户到达时调用此函数,随机生成客户信息以及相应的到达事件,分别加入队列1和事件队列。*/void arrive(){ //声明两个eventLink结点指针e、e1 //用malloc函数为两个结点指针分配空间 if(e为空或者e1为空){ //退出函数}//用(rand()%(2*MaxMoney)-MaxMoney)随机生成e和e1的办理金额//将当前时间(currentTime)作为e和e1的到达时间//将(number)作为e和e1的序列号,number++//将e1的类型设置为0(到达)//将e加入队列1(Q1)//将e1加入事件队列(Q_en)}/** 存款函数 当客户办理存款的时候调用此函数*/void putMoney(){ //声明两个eventLink结点指针e、e1 //用malloc函数为结点指针e1分配空间 if(e1为空){ //退出函数 } //用get_front()函数获取队列1的队头元素 //更新银行金额total_money //利用获得到的对头元素信息设置离开事件e1 //e1的离开时间为客户的到达时间+随机的处理时间 //e1加入事件队列 //删除队列1对头元素 //增加客户的总逗留时间(客户的离开时间-客户的到达时间) //接待客户人数加1 //客户的离开时间为交易时间 //将窗口设置为空闲状态}/** 取款函数 当客户办理取款的时候调用此函数*/void getMoney(){ //声明两个eventLink结点指针e、e1 //用malloc函数为结点指针e1分配空间 if(e1为空){ //退出函数 } //用get_front()函数获取队列1的队头元素 if(客户的取款金额大于银行现存金额){ //取款失败 //e1为队列2客户元素 //将客户从队列1删除,让客户进入队列2继续排队 }else{ //取款成功 //更新银行现存金额 //向事件队列添加相应的离开事件e1 //将客户从队列1删除 //接待客户人数加1 //增加客户的总逗留时间(客户的离开时间-客户的到达时间) //客户的离开时间为交易时间 //将窗口设置为空闲状态 }}/** 查找函数 查找队列q中第一个可以满足取款的结点并返回,若是查找失败则返回NULL*/eventLink search(Queue &q,int m){ //声明两个eventLink结点指针e、e1 //取队列的队头元素e while(队头元素不为空){//遍历队列 if(客户办理金额小于等于银行现存金额){ if(队列只有一个元素){ //队列头尾指针置空 //返回客户指针e1 }else{ //队头指针移动一位 //返回客户指针e1 } }else{//资金不足,查找下一个客户 if(队列只有一个元素){ //不做操作 }else{ //将队头结点放到队尾 } } if(队列遍历了一遍){ //返回NULL } } //返回NULL}/** 处理函数 对通过【查找函数】找到的结点进行取款处理,生成相应的离开事件*/void findAndDeal(){ //声明两个eventLink结点指针e、e1 while(调用search函数查找客户结点e){ //用malloc函数为结点指针e1分配空间 //更新银行现存款total_money //离开事件e1的离开时间为当前时间+随机处理时间 //设置离开事件e1加入事件表(Q_en) //接待客户人数增加 //交易时间加上处理时间 //增加客户总逗留时间(客户的离开时间-客户的到达时间) //释放结点e的空间 } //将交易状态设为空闲状态}/** 初始化函数 初始化三个队列,为三个队列分配空间*/void initQueue(){ //为三个队列Q1、Q2、Q_en分配空间 if(Q1、Q2、Q_en其中一个为空){ //退出函数 } //将三个队列的头尾指针置空}
    3.1.3 主函数的实现int main(){ while(用户选择进入模拟程序){ //用户输入模拟数据 //初始化三个队列 //随机产生到达时间(MaxTime)用来确定第一个到达的客户 while(当前时间<银行结业时间){ //当前时间加1 if(当交易时间<当前时间){ //让交易时间等于当前时间 } if(交易时间==当前时间){ //让flag为1 } if(到达时间==当前时间){ //调用到达函数arrive() //随机生成下一个到达时间(MaxTime) } if(flag==1并且队列1不为空){ if(队列1队头客户办理存款){ //调用存款函数putMoney() //调用查找函数findAndDeal() }else{//办理取款 //调用取款函数getMoney() } } } //输出事件队列信息 while(事件队列队头不为空){//遍历事件队列 if(事件为离开类型){ //输出事件信息 if(事件为存款类型){ //成功存款人数加1 }else{ //事件为取款类型 //成功取款人数加1 } }else{ //事件为到达类型 //输出事件信息 if(事件为存款类型){ //需要存款人数加1 }else{ //事件为取款类型 //需要存款人数加1 } } //删除事件队列队头元素 } //事件队列遍历结束 while(队列1队头元素不为空){ //更新总逗留时间 //接待客户人数加一 //删除事件队列1队头元素 } while(队列2队头元素不为空){ //更新总逗留时间 //接待客户人数加一 //删除事件队列2队头元素 } //调用结束函数closeBank() //输出最终模拟营业结果 }//退出循环}//main
    3.2 程序模块调用关系图程序分成主程序模块、存款模块、取款模块、检查处理模块、事件处理模块。

    3.3 银行业务模拟程序的流程图
    4.调试分析4.1 调试过程中遇到的问题以及解决办法程序调试阶段中遇到了几个问题,下面将对遇到的问题进行描述以及给出解决办法
    4.1.1 问题1问题:在运行程序的一开始就无法运行。
    解决过程:首先排除输入数据的错误,我取了几组正常的数据进行验证,排除是输入的数据的错误。接着我在程序中设置调试输出语句进行调试,发现程序在调用存款函数的时候出错。经过检查发现是在使用节点的时候,忘记给结点指针分配空间。
    解决方法:给待使用的结点指针分配空间。
    4.1.2 问题2问题:在输出结果的时候发现需要存款和需要取款的人数之和有时候会小于总的客户接待数量。
    解决过程:首先我是想到可能是在存款和取款函数里添加离开事件的时候忘记更新客户总数。在对存取款函数进行排查后发现并不是这个问题。接着我对更新需要存款和需要取款的人数进行检查,发现这两个变量的增加是符合逻辑的,并没有错误。最后我通过不断的调试和判断发现原来是在营业结束后没有对队列2里面还在排队的客户进行计算。
    解决方法:在结束模拟营业后增加一个循环对队列2还存在的客户进行计算、更新总逗留时间并释放空间。
    4.1.3 问题3问题:在程序运行到搜索函数的时候会出错,程序无法运行。
    解决过程:我对搜索函数进行调试发现函数陷入循环里面无法退出循环,在对程序的逻辑进行研究后我发现我的逻辑存在问题,在对队列2进行遍历的时候忘记在遍历一遍之后强制退出循环。
    解决办法:在处理函数的循环语句中增加一个判断,当队列遍历一遍后退出寻环
    4.2 算法的时空分析以及改进设想下面给出程序中各个操作的时间复杂度和空间复杂度的分析。
    4.2.1 get_front(Queue &q)//返回队首元素由函数的操作可以看出此操作只需要返回队列头指针,所以时间复杂度为O(1),空间复杂度也为O(1)。
    4.2.2 push(Queue &q,eventLink e)//入队操作由函数的操作可以看出来函数里没有循环语句只有简单的判断语句,没有额外的空间,只有指针的赋值操作。所以时间复杂度为O(1),空间复杂度也为O(1)。
    4.2.3 destoryQueue(Queue &q)// 销毁队列在这个函数中存在循环用以遍历队列,所以这个操作的时间复杂度为O(n),函数 没有额外的空间,所以空间复杂度为O(1)。
    4.2.4 pop(Queue &q)// 删除队首元素通过分析可以知道函数的操作可以看出来函数里没有循环语句只有简单的判断语句,没有额外的空间,只有指针的操作。所以时间复杂度为O(1),空间复杂度也为O(1)。
    4.2.5 closeBank()//结束函数函数只是调用了三个函数而调用的函数时间复杂度为O(n),所以函数时间复杂度为O(n),空间复杂度为O(1)。
    4.2.6 arrive();//到达函数通过对函数操作的分析可以知道,这个函数与问题规模无关所以时间复杂度为O(1),空间复杂度也为O(1)。
    4.2.7 putMoney()//存款函数通过对函数操作的分析可以知道,这个函数与问题规模无关所以时间复杂度为O(1),空间复杂度也为O(1)。
    4.2.8 getMoney()//取款函数通过对函数操作的分析可以知道,这个函数与问题规模无关所以时间复杂度为O(1),空间复杂度也为O(1)。
    4.2.9 search(Queue &q,int m)// 搜索函数通过分析可以知道函数里面存在一个循环用来遍历队列,所以这个操作的时间复杂度为O(n),函数 没有额外的空间,所以空间复杂度为O(1)。
    4.2.10 findAndDeal()//处理函数通过分析可以知道函数里面存在一个循环用来调用查找函数,所以这个操作的时间复杂度为O(n),函数 没有额外的空间,所以空间复杂度为O(1)。
    4.2.11 initQueue()//队列初始化通过对函数操作的分析可以知道,这个函数与问题规模无关所以时间复杂度为O(1),空间复杂度也为O(1)。
    5.经验和体会一开始在选这个课题的时候其实心里挺没底的,因为没有完整的用c语言做过一个课题。在看完这个课题的要求之后发现这个题目主要是需要用队列进行实现。所以我先把队列这部分的知识认真的复习了一遍。之后通过反复看设计需求大致了解了题目的设计要求,在对要求存在疑问的地方我也通过和同学讨论逐渐解决了疑惑。
    在对要求有了一个大致的了解后,我通过写伪代码和思维导图逐渐理清设计思路。接着就是通过题目具体的要求设计了数据结构,和一些基本模块。在经过认真编写后程序的架构基本完成。
    1 评论 1 下载 2019-12-23 12:10:48 下载需要11点积分
  • be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端JAVA和SQL SERVER数据库实现的个人财务管理系统

    一、需求分析个人财务管理系统是智能化简单化个人管理的重要的组成部分。并且随着计算机技术的飞速发展,计算机在管理方面应用的旁及,利用计算机来实现个人财务管理势在必行。本文首先介绍了个人财务管理系统的开发目的,其次对个人财务管理系统的需求分析做了详细的描述。接着,又对系统数据库设计和功能结构的划分做了详细论述。然后又对个人财务管理系统的实现做了详尽的说明。在报告的最后给出了项目的测试结果以及结果分析。
    本系统是对个人的收支情况做一个简单的管理,其中宝库哦个人信息管理以及收支信息管理。 其中,个人信息管理包括用户对自己的信息进行增删查改的一些操作,同样,收支信息管理包括用户对收支情况的信息进行增删查改的管理。
    1.1 系统业务需求该系统具体需求应该有用户登录模块,用户修改信息模块,用户修改信息模块,收支查询模块,收支删除模块,收支添加模块,收支修改模块。
    1.2 系统技术目标该系统的目标主要是能对个人信息以及收支信息进行较快的增删查改,同时也能对收支信息进行各种方式的查询。
    1.3 系统的具体需求根据以上对系统的任务和目标的分析,系统的具体需求如下:

    个人信息:用户名(唯一),密码,姓名,性别,出生日期,工作,身份证号,电话号码
    收支信息:收支编号(唯一),收支日期,收支方式,收支项目,收入金额,支出金额,,总金额

    二、软件功能结构分析由需求分析可知,软件的功能应包括:个人信息管理,收支信息管理。其中,个人信息应包括,个人信息的增删查该,登录时候验证功能。收支信息管理应包括对对收支信息的各种方式查询,以及对收支信息的增加,修改以及删除功能。当然,每个用户应对应其各自的收支信息。
    2.1 个人信息功能在登录界面用户输入用户名以及密码,如果用户与密码都输入正确则可以登录进系统,如果其中任何一项与数据库中的数据不匹配则要求重新输入。当用户没有账户时候,可以点击登录界面的注册按钮注册。成功进入系统后,可以进行个人信息的查询以及修改。
    具体流程图如下:

    2.2 收支管理功能用户登录成功后进入主界面后可以选择查询方式,全部查询:查询用户所有收入支出的信息;收入查询:查询用户收入信息;支出查询:查询用户支出信息;按日期查询:查询用户当天的收入支出信息。用户也可以对收入支出信息进行修改和删除以及添加。
    具体流程图如下:

    三、数据库设计经过以上的需求的分析以及系统功能的分析,需要建立出该系统数据库的各种模型,为建立一个好的,完善的数据库做准备。
    3.1 概念模型由于该系统涉及的较少,只涉及到用户以及财务管理,所以设计比较简单。一个用户可以有多条收支记录,所以用户表与收支表是一对多的关系。通过PowerDesigner工具设计出的概念数据模型如下:

    其对应的E-R模型如下图:

    3.2 逻辑模型联系转换
    一个用户可以有多条记录,而一条记录只能对应一个用户,所以用户与记录之间是一对多的关系。
    其逻辑结构设计如下

    个人信息(用户名,密码,姓名,性别,出生日期,工作,身份证号,电话号码)
    收支信息(收支编号,收支日期,收支方式,收支项目,收入金额,支出金额,总金额)

    关系模式

    个人信息(用户名,密码,姓名,性别,出生日期,工作,身份证号,电话号码)
    收支信息(收支编号,收支日期,收支方式,收支项目,收入金额,支出金额,总金额)

    3.3 物理模型通过PowerDesigner中的概念模型生成物理模型如下:

    3.4 表结构设计用户表

    收支信息表

    四、软件代码设计本系统是对个人财政的管理,下面给出具体的功能模块以及代码实现。
    4.1 功能模块登录界面模块

    说明:

    该界面为登录界面,如果没有账户,则可以点击注册按钮注册
    当用户输入的用户名或者密码输入错误时,会提示用户名或者密码输入错误
    当点击登录时,如果用户名以及密码都正确则会提示登录成功,并跳转到主界面

    用户注册模块

    说明:

    该界面为用户注册模块
    用户填入信息,其中用户名唯一,当用户名重复时会提示“用户名已存在,请重新输入”

    主界面模块

    说明:
    该界面为用户主信息界面

    用户可以有多种查询方式:全部查询(查询全部收支信息)、收入查询(只查询收入信息)、支出管理(只查询支出信息)、日期查询(查询当天收支信息)
    显示用户所有的收入总计、支出总计以及收入支出总计

    个人信息显示模块

    说明:

    该界面为用户显示模块
    用户如果不想使用该系统可以注销掉自己的账户

    个人信息修改模块
    说明:

    修改界面与个人信息查询界面在同一模块
    用户名不能修改

    收支信息插入模块
    说明:

    该界面为添加收支信息界面
    当点击主界面的插入按钮时候,会跳转到该界面
    收支编号不能重复


    收支信息修改界面

    说明:

    该界面为收支信息修改界面
    当点击主界面中的修改按钮时(必须选中一行),跳转到该界面
    收支编号不能修改

    收支信息删除界面
    说明:

    该功能与在主界面上
    选中一行,然后点击删除,即可提示删除成功

    4.2 代码实现登录界面主要功能实现(Login.java)
    jb1.addActionListener(new ActionListener() {//登陆按钮 public void actionPerformed(ActionEvent e) { jLabel5.setVisible(false); String ad = jf1.getText(); String pass = jf2.getText(); int i=0; String sc = "select userName,passWord from admin where userName='"+ad+"'"; try { ResultSet rs = st.executeQuery(sc); while (rs.next()) { i++; String userName = rs.getString("userName"); System.out.println(userName+"sdgdfgdf"); String password = rs.getString("passWord"); if (!ad.equals(userName)||userName.equals("")) { jLabel5.setVisible(true); } else if (!pass.equals(password)) { jLabel6.setVisible(true); } else { JOptionPane.showMessageDialog(null, "登陆成功!"); Show show = new Show(); show.s=jf1.getText(); show.setVisible(true); setVisible(false); } } System.out.println(i+"sdfd"); } catch (SQLException ex) { Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex); } if(i==0){ jLabel5.setVisible(true); } } });
    说明:该代码实现了登录界面的登录、判断用户名与密码输入是否正确。当用户名或者密码输入错误的时候会提示用户名或者密码错误。同时还添加了一个注册按钮让没有账户的用户注册账户。
    用户注册功能实现(UserInsert.java)
    jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { String s1 = jf1.getText();//y用户名 String s2 = jf2.getText();//姓名 String s12 = jf7.getText();//密码 String s3 = (String) jcb.getSelectedItem();//性别 String s5 = jf4.getText();//职业 String s6 = jf5.getText();//身份证号码 String s7 = jf6.getText();//电话号码 String s8 = (String) jcb1.getSelectedItem(); String s9 = (String) jcb2.getSelectedItem(); String s10 = (String) jcb3.getSelectedItem(); String s11 = s8 + "-" + s9 + "-" + s10;//出生日期 ResultSet rs; String str ="select userName from admin where userName='"+s1+"'"; rs = st.executeQuery(str); int i=0; while (rs.next()) { i++; } if (i == 0) { if (s6.length() != 18 || s7.length() != 11) { if (s6.length() != 18) { jLabel5.setVisible(true); } if (s7.length() != 11) { jLabel14.setVisible(true); } } else { String sql = "insert into admin Values ('" + s1 + "','" + s12 + "','" + s2 + "','" + s3 + "','" + s11 + "','" + s7 + "','" + s5 + "','" + s6 + "')"; st.executeUpdate(sql); JOptionPane.showMessageDialog(null, "注册成功"); setVisible(false); } } else{ jLabel15.setVisible(true); } } catch (SQLException ex) { Logger.getLogger(UserInsert.class.getName()).log(Level.SEVERE, null, ex); } } });
    说明:该代码实现了个人信息的注册,其中用户名唯一,重复会给出提示“用户名已存在”,并且判断身份证与电话号码填写的格式是否正确。*
    全部查询实现函数(Show.java)
    jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    收入查询实现函数(Show.java)
    jb2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    支出查询实现函数(Show.java)
    jb3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    日期查询实现函数(Show.java)
    jb4.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    个人信息查询功能模块(Show.java)
    jb9.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    个人信息修改功能模块(User.java)
    jb2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    个人信息删除功能模块(User.java)
    Jb3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    收支信息插入功能模块(UserInsert.java)
    jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    收支信息添加功能模块(Insert.java)
    jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    收支信息删除功能模块(show.java)
    Jb7.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    五、总结通过该课程设计,我认识到软件设计是be365体育在线投注_365BET能赢钱吗_手机365体育投注客户端需求分析和可行性分析的基础上的,软件设计阶段需要合理的分析需求分析中的细节部分的实现,既要考虑到关键处代码的可实现性,又要考虑到开发过程中遇到的问题。刚开始觉得该 项目建立的数据库比较简单,没有认真进行需求分析,所有导致后面举步维艰。后来重新进行需求分析,一步一步来,最终完成了该课程设计。软件设计是把需求分析中的问题抽象化,又要把抽象化了的需求形象的从预期的实现中体现出来。 本小组的个人财务管理系统系统的设计实现了预期的功能,对个人消费进行记录,个人的收入进行统计,对个人收支进行汇总并给出相应的理财提示信息。在这次的个人财务管理系统设计中将理论知识应用到实际中使得对理论知识的理解有了更进一步的理解,如果仅仅只是运用理论知识,是远远不够的。必须理论联系实际,才能很好的将各门课程学好,并用于实际案例中。
    这次设计使我的编程水平提高了一大步。由于这次设计涉及到数据库,我的学到了不少编程工具与数据库连接的知识,对数据库的操作有了进一步的了解。这次设计对我的综合能力是一次很好的锻炼,自己的能力和知识还很有限。所以今后我的学习道路还是很漫长的。
    3 评论 163 下载 2018-10-25 21:36:27 下载需要6点积分
显示 0 到 15 ,共 15 条
eject