资源描述
二○一○ ~二○一二 学年第 二 学期
信息科学与工程学院
课程设计报告书
课程名称: C程序课程设计
班 级: 自动化2010级 6班
学 号: 201004134192
姓 名: 杨少卿
指导教师: 尉宇
二○一一年 九 月
C语言课程设计
一、 需求分析
1)题目:汽车售票系统
2)任务与要求:自学C语言中相关知识,设计出汽车售票系统。要求如下所述:
每天“火车站—植物园”有五个班次的汽车,具体的数据格式如下:
班次 发车时间 载客量 已售票数
1 06:40 50 0
2 09:30 40 0
3 12:00 40 0
4 14:30 40 0
5 16:00 50 0
为售票员开发一个小程序,已完成每天的“火车站—植物园”的售票服务。
要求如下:
1. 能够售票和退票。以文件(myfile.txt)的形式保存当天的各个车次的售退票情况。
◆售票功能
当查询出已订票人数小于额定载量且当前系统时间小雨发车时间时才能售票,自动更新已售票人数。
◆退票功能
退票时,输入退票的班次,当本班车未发出时才能退票,自动更新已售票人数。
2. 查询显示功能。可以随时显示当前售票状况(如:班次 发车时间 载客量 已售票数 余票等信息)。
3. 用户接口中的菜单至少应包括“售票”、“退票”、“显示当前售票情况”、“保存当天资料”、“退出”5项。
3)功能分析
程序总共包括五大功能:售票,退票,查询,保存,退出。
二、 概要设计
1) 设计框架、系统功能模块图
汽车售票系统主体部分为主菜单,主菜单下主要包括五个模块:售票模块,退票模块,查询显示模块,保存模块,退出模块。各个模块中又包含有子选项。
售 票 功 能
查 询 功 能
退 票 功 能
汽车售票系统
保 存 功 能
推 出 功 能
三、 详细设计
1)设计框架、系统功能模块图
主菜单为一个主体函数另外包含接口信息,用户接口由结构体输出数据形成。用户通过选择在主菜单中的选项调用各个功能模块。1、在售票模块中包含时间函数,通过函数得到本地时间,通过本地时间与发车时间的比较,来决定是否可以订票。并更改售票人数。2、在退票模块中,同样是调用时间函数,比较时间来决定是否可以退票。3、查询功能中即把系统数据中的信息输出即可。4、保存模块:将包含系统信息的结构体各个数据用fwrite函数写入myfile文本文檔中。5、退出:调用system函数exit退出当前操作面。
2) 工作流程图
四、 主要源程序代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
struct shoupiao
{ int a;
int hour; /*结构体申明*/
int min;
int c;
int d;
int tuipiaoshu ;
};
struct shoupiao str[5]={{1,6,40,50,0},{2,9,30,40,0},{3,12,00,40,0},
{4,14,30,40,0},{5,16,00,50,0}};
void mainmenu();
void shoupiaofuwu();
void tuipiaofuwu(); /*函数申明*/
void chaxunfuwu();
void save();
void esc();
int main() /*主函数*/
{
mainmenu();
getchar();
getchar();
getchar();
}
/* void yonghujiemian()
{
printf(" 欢迎光临火车站-植物园售票系统\n");
struct shoupiao *p;
printf(" 班次 发车时间 载客量 已售票数\n"); /*主要接口*/
// for(p=str;p<str+5;p++)
// printf(" %d %02d:%02d %5d %5d\n",p->a,p->hour,p->min,p->c,p->d);
void mainmenu()
{
printf(" ************************************\n");
printf(" 欢迎光临火车站-植物园售票系统\n");
printf(" ************************************\n");
struct shoupiao *p;int a;
printf(" 班次 发车时间 载客量 已售票数\n"); /*主要用户接口*/
for(p=str;p<str+5;p++)
printf(" %d %02d:%02d %5d %5d\n",p->a,p->hour,p->min,p->c,p->d);
printf("如果您需要购票服务请输入“1”\n如果您需要退票服务请输入“2”\n如果您想查询当前售票情况请输入“3”\n若保存当天数据请输入“4”\n若退出请输入‘5’\n谢谢!\n");
printf("请输入:");
scanf("%d",&a);
switch(a)
{
case 1:system("cls");shoupiaofuwu();
case 2:system("cls");tuipiaofuwu();
case 3:system("cls");chaxunfuwu(); return; /*函数调用*/
case 4:system("cls");save();mainmenu();
case 5:system("cls");esc();
default: system("cls");printf("ERROR请重新输入\n");mainmenu();
}
}
void shoupiaofuwu() /*售票函数*/
{
int i,j,k,l,;
time_t t1;
t1=time(0); /*截取本地时间*/
struct tm*local=localtime(&t1);
printf("请输入您需要预订的班次:");
scanf("%d",&i);
if((local->tm_hour*3600+local->tm_min*60>str[i-1].hour*3600+str[i-1].min*60)||
str[i-1].d>str[i-1].c) /*购票判断*/
{
printf("对不起,您所要预定的班次已发车或者车票已售完,继续预定后续车票请输入‘1’,返回主菜单请输入‘0’\n");
scanf("%d",&j);
if(j)
shoupiaofuwu();
else
mainmenu();
}
else if(i>5)
{
printf("对不起,您所要预定的班次不存在,继续预定后续车票请输入‘1’,返回主菜单请输入‘0’\n");
scanf("%d",&j); /*继续订票或返回*/
if(j)
shoupiaofuwu();
else
mainmenu();
}
else { int j;
printf("请输入您需要该班次的票数:");
scanf("%d",&k);
if(k>(str[i-1].c-str[i-1].d))
{
printf("对不起,当前只有%d张票可以订购,重新订票请输入‘1’返回请输入‘0’\n",str[i-1].c-str[i-1].d);
printf("请输入:");
scanf("%d",&j);
if(j)
shoupiaofuwu();
else
mainmenu();
}
else
str[i-1].d+=k;
printf("订票成功!是否继续买票?继续请输入‘1’否请输入‘0’\n");
printf("请输入:");
scanf("%d",&l);
if(l)
shoupiaofuwu();
else
{
system("cls");
mainmenu(); }
}
}
void tuipiaofuwu() /*退票函数*/
{
int i,j,k,l;
time_t t1;
t1=time(0); /*截取本地时间*/
struct tm*local=localtime(&t1);
printf("请输入您需要退票的班次:");
scanf("%d",&i);
if(i>5)
{
printf("对不起,您所要退票的班次不存在,继续退车票请输入‘1’,返回主菜单请输入‘0’\n");
printf("您输入:");
scanf("%d",&j);
if(j)
tuipiaofuwu();
else
mainmenu(); }
else if((local->tm_hour*3600+local->tm_min*60>str[i-1].hour*3600+str[i-1].min*60)||
str[i-1].d<0)
{
printf("对不起,您所要退票的班次已发车,继续退车票请输入‘1’,返回主菜单请输入‘0’\n");
scanf("%d",&j);
if(j)
tuipiaofuwu();
else
mainmenu();
}
else
{ int j;
printf("请输入您需要退该班次的票数:");
scanf("%d",&k);
if(k>str[i-1].d)
{
printf("您输入的该班次的票数有误,您最多可以退出%d张车票.继续退车票请输入‘1’,返回主菜单请输入‘0’\n",str[i-1].d);
printf("您输入:");
scanf("%d",&j);
if(j)
tuipiaofuwu();
else
{
system("cls");
mainmenu();}
}
else
{
str[i-1].d-=k;
str[i-1].tuipiaoshu+=k;
printf("您已成功退票,是否继续退票?继续请输入‘1’否请输入‘0’");
printf("您输入:");
scanf("%d",&l);
if(l)
tuipiaofuwu();
else
{
system("cls");
mainmenu();} }
}
}
void chaxunfuwu() /*查询函数*/
{
int i;
time_t t1;
t1=time(0); /*截取时间*/
struct tm*local=localtime(&t1);
printf(" 欢迎光临火车站-植物园售票系统\n");
struct shoupiao *p;
printf(" 班次 发车时间 载客量 已售票数 余票数 退票数\n"); /*查询界面*/
for(p=str;p<str+5;p++)
printf(" %d %02d:%02d %5d %5d %5d %d \n",p->a,p->hour,p->min,p->c,p->d,(p->c-p->d),p->tuipiaoshu);
printf("当前时间是%02d:%02d\n",local->tm_hour,local->tm_min);
printf("如果您需要购票服务请输入“1”\n如果您需要退票服务请输入“2”\n返回主菜单请输入‘3’\n退出请输入‘4’\n");
printf("请输入:");
scanf("%d",&i);
if(i==1)
shoupiaofuwu();
if(i==2)
tuipiaofuwu(); /*子菜单*/
if(i==3)
mainmenu();
if(i==4)
esc();
}
void save()
{
FILE *fp;
int i; /*保存函数*/
if((fp=fopen("myfile","wb"))==NULL)
{
printf("cannot open file\n");
return;
}
for(i=0;i<5;i++)
if(fwrite(&str[i],sizeof(struct shoupiao),1,fp)!=1)
printf("file write error\n");
fclose(fp);
printf("保存成功\n");
}
void esc()
{ /*退出函数*/
exit(0);
}
五、 调试分析过程
进入程序用户接口,通过程序菜单输入‘1’调用售票程序,购买车票。但在现实中购买车票数不超过载客量并且不能购买以发车车次,需要修改购买车票的条件。增加函数判断依据。当输入购买第一车次50张。程序判断车次是否存在、有没有超过发车时间、有没有50张票,才能继续进行。当超过余票数时,显示票数不足并提醒顾客。退票程序也如此。保存调用文件函数直接运行。
在调试过程中,实际问题往往是多方面的,比如订购车票,先要查询,那么在查询功能中再有订票功能,那么顾客不需要重新返回主菜单就直接进行订票,这些都需要和实际生活相联系才能不断完善程序,也就是程序能够友好的引领顾客购票。还有要用提示语和温和的语句来改善界面给人的生涩。
六、 课程设计小结
C语言中的库函数中包含好多的函数,这些函数提供了丰富的功能同时也为编写程序者节省了很多的时间,像时间time函数截取当地时间就是很好的例子。函数是算法的核心,函数还是很重要的。
C语言的确以计算机为平台为人们生活提供了便利,用C语言设计这个程序给了我对事物系统的分析能力,虽然不是很多。希望能学好这门语言。
附录资料:不需要的可以自行删除
SHA算法的实现
C语言程序:
#include <iostream>
#include <vector> //定义vector数组
#include <string> //记录消息
using namespace std;
const int NUM = 8; //一个字由32比特(或者8个16进制数)
const int BIT = 512; //消息认证码要以512比特一组
//字常量
string H0 = "67452301";
string H1 = "EFCDAB89";
string H2 = "98BADCFE";
string H3 = "10325476";
string H4 = "C3D2E1F0";
//定义SHA1(安全哈希算法)类
class SHA1
{
public:
//将一个字符串形式的字转化为vector数组
vector<int> hex_into_dec(string word);
//将vector转化为string字符串形式
string num_into_message(vector<int> A);
//两个字X和Y的逻辑"和"
vector<int> word_AND(vector<int> A,vector<int> B);
//两个字X和Y的逻辑"或"
vector<int> word_OR(vector<int> A,vector<int> B);
//两个字X和Y的逻辑"异或"
vector<int> word_XOR(vector<int> A,vector<int> B);
//两个字X和Y的逻辑"补"
vector<int> word_COMPLEMENT(vector<int> A);
//两个字X和Y的摸2^32整数加
vector<int> word_ADD(vector<int> A,vector<int> B);
//将字X循环左移s个位置
vector<int> ROTL(vector<int> A,int s);
//SHA-1的填充方案,我们设定msg由ASCII码组成
vector<vector<int> > SHA_1_PAD(string msg);
//将SHA-1压成以字为单位
vector<vector<vector<int> > > compress(vector<vector<int> > result);
//定义ft函数,每个ft函数都有B,C,D三个字作为输入,并产生一个字作为输出
vector<int> Ft(int t,vector<int> B,vector<int> C,vector<int> D);
//定义字常数K
vector<int> K(int t);
//开始进行SHA-1(安全Hash算法)的加密
vector<vector<int> > SHA_1(string msg);
};
//将vector转化为string字符串形式
string SHA1::num_into_message(vector<int> A)
{
int i;
string msg = "";
for(i = 0;i < A.size();i++)
{
if(A[i] >= 0 && A[i] <= 9)
msg += '0' + A[i];
else if(A[i] >= 10 && A[i] <= 15)
msg += 'A' + (A[i] - 10);
}
return msg;
}
//将一个字符串形式的字转化为vector数组
vector<int> SHA1::hex_into_dec(string word)
{
int i;
vector<int> result(NUM,0);
for(i = 0;i < NUM;i++)
{
if(word[i] >= '0' && word[i] <= '9')
{
result[i] = word[i] - '0';
}
else if(word[i] >= 'A' && word[i] <= 'F')
{
result[i] = 10 + word[i] - 'A';
}
}
return result;
}
//两个字X和Y的逻辑"和"
vector<int> SHA1::word_AND(vector<int> A,vector<int> B)
{
vector<int> result(NUM,0);
int i;
for(i = 0;i < NUM;i++)
{
result[i] = A[i] & B[i];
}
return result;
}
//两个字X和Y的逻辑"或"
vector<int> SHA1::word_OR(vector<int> A,vector<int> B)
{
vector<int> result(NUM,0);
int i;
for(i = 0;i < NUM;i++)
{
result[i] = A[i] | B[i];
}
return result;
}
//两个字X和Y的逻辑"异或"
vector<int> SHA1::word_XOR(vector<int> A,vector<int> B)
{
vector<int> result(NUM,0);
int i;
for(i = 0;i < NUM;i++)
{
result[i] = A[i] ^ B[i];
}
return result;
}
//两个字X和Y的逻辑"补"
vector<int> SHA1::word_COMPLEMENT(vector<int> A)
{
vector<int> result(NUM,0);
int i;
for(i = 0;i < NUM;i++)
{
result[i] = 15 - A[i];
}
return result;
}
//两个字X和Y的摸2^32整数加
vector<int> SHA1::word_ADD(vector<int> A,vector<int> B)
{
vector<int> result(NUM,0);
int i;
for(i = NUM - 1;i >= 0;i--)
{
result[i] = A[i] + B[i];
if(i != 0)
{
int temp = result[i] / 16;
result[i-1] += temp;
}
result[i] %= 16;
}
return result;
}
//将字X循环左移s个位置
vector<int> SHA1::ROTL(vector<int> A,int s)
{
vector<int> result = A;
vector<int> temp(NUM,0);
int i,j;
for(i = 0;i < s;i++)
{
for(j = NUM - 1;j >= 0;j--)
{
if(result[j] / 8 >= 1)
{
temp[j] = 1;
result[j] <<= 1;
result[j] %= 16;
if(j < NUM - 1)
result[j] += temp[j + 1];
}
else if(result[j] / 8 == 0)
{
temp[j] = 0;
result[j] <<= 1;
result[j] %= 16;
}
}
result[NUM - 1] += temp[0];
}
return result;
}
//SHA-1的填充方案,我们设定msg由ASCII码组成
vector<vector<int> > SHA1::SHA_1_PAD(string msg)
{
int len = msg.length();
int bit_num = len * 8;
int i,j;
int num,lest = bit_num % 512;
if(lest != 0) //看消息长度是否超过512字节,我们需要将它补成512的倍数
num = bit_num / 512 + 1;
else
num = bit_num / 512;
//首先我们以8位字节为一组保存到vector里面,512比特为一组,即一组里面有64位元素
vector<vector<int> > result;
result.resize(num);
for(i = 0;i < num;i++)
{
result[i].resize(64);
}
for(i = 0;i < num;i++)
{
for(j = 0;j < 64 && i * 64 + j < len;j++)
{
result[i][j] = msg[i * 64 + j];
}
}
//下面开始为未够512比特的消息分组进行补长度操作
if(lest != 0){
int x = num - 1,last_len = lest / 8;
result[x][last_len] = 128; //先补一个"1"
for(i = last_len + 1;i < 56;i++)
{
result[x][i] = 0;
}
int last_l = lest;
j = 63;
while(j >= 56)
{
result[x][j] = last_l % 128;
last_l /= 128;
j--;
}
}
return result;
}
//将SHA-1压成以字为单位(三维数组有点复杂)
vector<vector<vector<int> > > SHA1::compress(vector<vector<int> > result)
{
vector<vector<int> > rr;
rr.resize(result.size());
int i,j;
for(i = 0;i < rr.size();i++)
{
rr[i].resize(128);
}
for(i = 0;i < result.size();i++)
{
for(j = 0;j < result[i].size();j++)
{
展开阅读全文