车票根据题意两两站点连线生成,金额和数量分别用随机数。
数据存储:站点,车票,用户分别为3个结构体,用于对应数据库。
购买流程:检查输入数值有效性->检查车票库存->购买成功同步修改用户购买流水及车票库存。(这里题目需求不明确,没有指明用户购买方式),我的代码允许一个用户同时购买多种票,每种票可分批购买多张。购买流水记录自动增加和更新。
退票流程:检查输入和用户购买记录,同步更新用户及车票信息。
删除流程:选择删除没有被用户购买的票(函数检查所有用户,虽然本题只要一个用户,实际传参用户数组首地址)。
PS: 这个题目涉及到增删改,用链表来写更好,但考虑你学习范围,没有使用链表而是动态数组,动态数组删除,考虑内存占用,不仅要需循环移位还要释放多余地址。
另外整体程序,异常的处理我只是单纯返回0或者1或者-1区分基本的成功与失败。你如想对个别异常进行特殊处理,自行修改返回值,接收判断。
下面是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <conio.h>
#define MS 5//最大站点数
typedef struct station
{
char sid[10]
char sName[20]
}STN
typedef struct ticket
{
int tid//票编号
STN *ssP//起始站
STN *tsP//终点站
int value//票价
int number//数量
}TKT
typedef struct userInfo//用户
{
char uid[20]//身份证号
int cnt//购买的票种类数量
int *btids//购买的所有票id数组
int *btNum//购买的所有票数量数组
}UIFO
int init(STN stns[MS],TKT **tkts)//初始化车站、票数据
int disAllTickets(TKT *tkts)
int buyTicket(UIFO *uifo,TKT *tkts)//异常返回0
int reTicket(UIFO *uifo,TKT *tkts)//异常返回0
int showMenu(UIFO *uifo,TKT *tkts)
int delIntByIndex(int *nums,int len,int index)//通过下标index删除动态整型数组nums对应元素,并释放多余地址,返回删除后的数组长度,异常返回-1
int delTkts(UIFO *uifos,int len,TKT *tkts)//删除指定票(检查用户组,只要有一个用户购买,无法删除)
int cnt//票种类数量
int main()
{
STN stns[MS]
TKT *tkts=NULL
UIFO uifo={"321002199902050614",0,NULL,NULL}
srand(time(NULL))
cnt=init(stns,&tkts)
printf("共生成%d组票(每组往返两种票,共%d种票)\n\n",cnt/2,cnt)
printf("按任意键继续。。。。\n"),getch()
system("cls")
showMenu(&uifo,tkts)
return 0
}
int showMenu(UIFO *uifo,TKT *tkts)
{
int n=5
printf("(1) Buy ticket\n")
printf("(2) Refund ticket\n")
printf("(3) Remove ticket\n")
printf("(4) Display all tickets\n")
printf("(0) Exit\n")
while(n<0 || n>4)
scanf("%d",&n)
switch(n)
{
case 0: return 0
case 1: if(!buyTicket(uifo,tkts)) return 0break
case 2: if(!reTicket(uifo,tkts)) return 0break
case 3: if(!delTkts(uifo,1,tkts)) return 0break
//这里删除功能,用户多名,要传数组首地址,由于演示只有一个用户(len=对应用户数),所以只传该用户地址(len=1)
case 4: disAllTickets(tkts)break
}
showMenu(uifo,tkts)
return 1
}
int disAllTickets(TKT *tkts)
{
int i
for(i=0i<cnti++)
printf("编号:%2d 路程:%s-%s 票价:%3d 剩余票数:%d\n",tkts[i].tid,tkts[i].ssP->sName,tkts[i].tsP->sName,tkts[i].value,tkts[i].number)
printf("按任意键继续。。。。\n"),getch()
system("cls")
return 1
}
int delIntByIndex(int *nums,int len,int index)
{
int i,*temp=NULL
if(index>len-1) return -1
for(i=indexi<len-1i++)
nums[i]=nums[i+1]
len--
if(len)
{
temp=(int *)realloc(nums,sizeof(int)*len)
if(!temp) return -1
nums=temp
}
else
free(nums)
return len
}
int reTicket(UIFO *uifo,TKT *tkts)
{
int i,j,tid,n,index,len,flag=0
printf("当前用户购买记录:\n")
for(i=0i<uifo->cnti++)
{
for(j=0j<cntj++)
if(tkts[j].tid==uifo->btids[i]) index=j
printf("--车票编号:%d,起末站:%s-%s,购买票数:%d\n",uifo->btids[i],tkts[index].ssP->sName,tkts[index].tsP->sName,uifo->btNum[i])
}
printf("请输入要退票的车票id及票数:"),scanf("%d%d",&tid,&n)
for(i=0i<uifo->cnti++)
if(uifo->btids[i]==tid &&uifo->btNum[i]>=n)
{
for(j=0j<cntj++)
if(tkts[j].tid==uifo->btids[i]) tkts[j].number+=n//同步修改对应车票剩余票数
uifo->btNum[i]-=n//用户购买记录修改
if(uifo->btNum[i]==0)//某种车票全部退完,删除该条记录
{
len=delIntByIndex(uifo->btNum,uifo->cnt,i)
if(len==-1) return 0
len=delIntByIndex(uifo->btids,uifo->cnt,i)
if(len==-1) return 0
uifo->cnt=len
}
flag=1
break
}
if(flag)
printf("退票成功!\n")
else
printf("无此购买记录或输入数量不符合\n")
printf("按任意键继续。。。。\n"),getch()
system("cls")
return 1
}
int buyTicket(UIFO *uifo,TKT *tkts)
{
char spn[20],tpn[20]
int i,n=-1,index=-1,*temp=NULL
for(i=0i<cnti++)
printf("编号:%2d 路程:%s-%s 票价:%3d 剩余票数:%d\n",tkts[i].tid,tkts[i].ssP->sName,tkts[i].tsP->sName,tkts[i].value,tkts[i].number)
printf("请输入始发站站名和终点站站名:"),scanf("%s%s",spn,tpn)
for(i=0i<cnti++)
if(strcmp(tkts[i].ssP->sName,spn)==0 &&strcmp(tkts[i].tsP->sName,tpn)==0)
{
printf("车票%s-%s 票价:%3d 剩余票数:%d\n",tkts[i].ssP->sName,tkts[i].tsP->sName,tkts[i].value,tkts[i].number)
index=i
break
}
if(index==-1)
printf("购买失败!无此路程的车票\n")
else
{
while(n<=0)
{
printf("请输入要购买的数量(大于0):"),scanf("%d",&n)
if(tkts[index].number<n)
printf("错误:车票数量不足或者输入数值超出范围!请重新输入!\n"),n=-1
}
for(i=0i<uifo->cnti++)//检查用户购买记录,重复票累加购买数量,不同票新增记录
{
if(uifo->btids[i]==tkts[index].tid)
{
printf("该票已购买了%d张,现再次购买%d张,累计购买了%d张\n",uifo->btNum[i],n,uifo->btNum[i]+n)
uifo->btNum[i]+=n
tkts[index].number-=n
break
}
}
if(i==uifo->cnt)//未检查到重复记录,新增
{
if(!uifo->btids)
{
uifo->btids=(int *)malloc(sizeof(int))
if(!uifo->btids) return 0
uifo->btNum=(int *)malloc(sizeof(int))
if(!uifo->btNum) return 0
}
else
{
temp=(int *)realloc(uifo->btids,sizeof(int)*(uifo->cnt+1))
if(!temp) return 0
uifo->btids=temp
temp=(int *)realloc(uifo->btNum,sizeof(int)*(uifo->cnt+1))
if(!temp) return 0
uifo->btNum=temp
}
uifo->btids[uifo->cnt]=tkts[index].tid
printf("该票购买了%d张\n",(uifo->btNum[uifo->cnt]=n))
tkts[index].number-=n
uifo->cnt++
printf("用户购买记录:\n")
for(i=0i<uifo->cnti++)
printf("--车票编号:%d,购买票数:%d\n",uifo->btids[i],uifo->btNum[i])
}
printf("本次成功购买了%s-%s的票%d张!\n",tkts[index].ssP->sName,tkts[index].tsP->sName,n)
}
printf("按任意键继续。。。。\n"),getch()
system("cls")
return 1
}
int delTkts(UIFO *uifos,int len,TKT *tkts)//len:所有购买的用户数量
{
int i,j,k,tid,flag=0,index
for(i=0i<cnti++)
printf("编号:%2d 路程:%s-%s 票价:%3d 剩余票数:%d\n",tkts[i].tid,tkts[i].ssP->sName,tkts[i].tsP->sName,tkts[i].value,tkts[i].number)
printf("请输入要删除的车票编号:"),scanf("%d",&tid)
for(i=0i<cnti++)
if(tid==tkts[i].tid)
{
index=i
flag=1
for(j=0j<lenj++)//检查所有用户购买记录
{
for(k=0k<uifos[j].cntk++)
if(uifos[j].btids[k]==tid)
{
flag=0
printf("该票已被用户购买,无法删除,需先完成退票!\n")
break
}
if(!flag)
break
}
break
}
if(!flag) printf(" 删除失败,输入数值超出范围或不可删除!\n")
else
{
cnt--
if(cnt==0)
{
free(tkts[index].ssP)
free(tkts[index].tsP)
free(&tkts[index])
}
else
{
free(tkts[index].ssP)
free(tkts[index].tsP)
for(i=indexi<cnti++)
tkts[i]=tkts[i+1]
tkts[cnt].ssP=NULL
tkts[cnt].tsP=NULL
free(&tkts[cnt])
}
printf(" 删除成功!\n")
}
printf("按任意键继续。。。。\n"),getch()
system("cls")
return 1
}
int init(STN stns[MS],TKT **tkts)
{
TKT *tTemp=NULL
int i,j,n,v,cnt=2
static int id=1
printf("生成站点:\n")
for(i=0i<MSi++,id++)
{
sprintf(stns[i].sid,"车站%03d",id)
sprintf(stns[i].sName,"SN%03d",id)
printf("----站点名:%s。站点ID:%s\n",stns[i].sid,stns[i].sName)
}
printf("计算所有站点连线,生成车票(票是往返,所以一次生成往返两组票):\n")
for(i=0i<MSi++)
for(j=i+1j<MSj++)
{
if(!(*tkts))
{
*tkts=(TKT *)malloc(sizeof(TKT)*2)
if(!(*tkts)) return -1
}
else
{
tTemp=(TKT *)realloc((*tkts),sizeof(TKT)*cnt)
if(!tTemp) return -1
*tkts=tTemp
}
n=rand()%4+2//每种票随机2~5张(保证总数大于20)
v=rand()%201+50//随机生成票价50~250
(*tkts)[cnt-1].tid=cnt
(*tkts)[cnt-1].ssP=&stns[i]
(*tkts)[cnt-1].tsP=&stns[j]
(*tkts)[cnt-1].value=v
(*tkts)[cnt-1].number=n
(*tkts)[cnt-2].tid=cnt-1
(*tkts)[cnt-2].ssP=&stns[j]
(*tkts)[cnt-2].tsP=&stns[i]
(*tkts)[cnt-2].value=v
(*tkts)[cnt-2].number=n
printf("----%s和%s的之间往返票各生成%d张,票价为%d(随机)\n",stns[i].sName,stns[j].sName,n,v)
cnt+=2
}
return cnt-2
}
//答题不易,如采纳的,请不要无故删除问题。
单项选择题(每小题2分,共50分)
1、一个C程序的执行是从___A__。
A、本程序的main函数开始,到main函数结束
B、本程序的main函数开始,到本程序文件的最后一个函数结束
C、本程序文件的第一个函数开始,到本程序文件的最后一个函数结束
D、本程序文件的第一个函数开始,到本程序main函数结束
2、C语言程序的基本单位是___C___。
A、程序行 B、语句
C、函数 D、字符
3、请选出可用作C语言用户标识符的一组标识符___B___。
A、void B、a3_b3 C、For D、2a
define _123 -abc DO
WORD IF ase sizeof
主要特点
C语言是一种结构化语言,它有着清晰的层次,可按照模块的方式对程序进行编写,十分有利于程序的调试,且c语言的处理和表现能力都非常的强大,依靠非常全面的运算符和多样的数据类型,可以轻易完成各种数据结构的构建,通过指针类型更可对内存直接寻址以及对硬件进行直接操作,因此既能够用于开发系统程序,也可用于开发应用软件。
以上内容参考:百度百科-c语言
一、单项选择题(共10题,每题2分,共20分。在备选答案中选择一个最佳答案。多选、错选、不选不得分)1、不是C语言基本数据类型的是( )。
A、指针类型B、整型
C、字符型D、实型
2、设有:int a=3, b= 4, c= 5,x , y表达式0 &&(x=a)&&(y=b)的值为()。
A、1 B、0C、3D、4
3、设有语句 int a=3 则执行了语句 a+=6后,变量a 的值为( )。
A、18B、-3C、9 D、12
4、执行以下程序段后,输出的y值为( )
void main()
{ int a[]={2,4,6,8,10}
int y, *p
p=&a[0]
y=*p printf(“%d”,y)
}
A、2 B、4C、6D、8
5、有定义语句:float a[4]则分配给数组a的内存空间为( )字节。
A、 20 B、 12 C、 16 C、10
6、以下描述错误的是( )。
A、break语句可用于while语句。
B、break语句和continue语句的作用是一样的。
C、在循环语句中使用break语句是为了跳出循环,提前结束循环。
D、在循环语句中使用continue语句是为了结束本次循环,而不终止整个循环。
7、C语言中规定,if语句的嵌套结构中,else总是( )。
A、与最近的if 配对 B、与第一个if 配对
C、按缩进位置相同的if配对 D、与最近的且尚未配对的if 配对
8、说明语句“int (*p)( )”的含义是( ) 。
A、p是一个指向一维数组的指针变量。
B、p是指针变量,指向一个整型数据。
C、p是一个指向函数的指针,该函数返回一个int型数据。
D、以上都不对。
9、以下对二维数组c的正确声明是 ( ) 。
A、int c[3][ ] B、int c(3,4)
C、int c(2)(2) D、int c[3][2]
10、下述程序段执行后输出结果为( )。
int x=100, y=200
printf ("% d", (x, y))
A、100 B、200 C、100,200 D、编译出错
二、填空题(共7题,共10空,每空1分,共10分。将答案填在题中横线上)
1、C语言提供的三种逻辑运算符是 && 、|| 和!
2、函数的返回值是通过函数中的 return语句获得的。
3、在"int a[ ][3]={{1},{3,2},{4,5,6},{0}}"定义后,a[2][2]的值为_6__ _;
4、对于"int *pa[5];" pa是一个具有5个元素的_数组指针_,每个元素是一个指向int型变量的__指针__;
5、单向链表的尾节点next指针应赋值__ NULL___;
6、在语句for(x=1,y=3;x>y;y++)中循环体执行的次数为0 。
7、int a[5]数组a的首地址为2000,则元素a[1]的地址为 2002 ,元素a[2]的地址为2004。
三、程序填空题(共2题,共5空,每空4分,共20分)
1、以下程序完成计算1-1/2+1/3-1/4+1/5+……前n 项和,请填空。
#include <stdio.h>
int main( )
{ int i, n, flag
float sum
scanf("%d", &n)
flag= 1
sum=0
for(i=1i<=ni++ )
{ sum+=(float)flag/i
flag=-flag
}
printf("%.3f\n", sum)
}
2、以下程序的功能是从键盘输入n个整数,统计其中正数、0、负数的个数,请填空。
#include <stdio.h>
void main( )
{int a, i, count1,count2,count3
count1=count2=count3=0
for(i=1i<=ni++)
{ scanf(“%d”, &a)
if(a>0) count1++
else if(a==0)count2++
else count3++
}
printf(“正数:&d个,零:%d个,负数:%d个\n”, count1,count2,count3 )
}
四、运行程序结果题(共4题,每题6分,共24分)
1、写出程序运行结果。
void main( )
{ int x=1,y=2,t;
int *p1,*p2
p1=&xp2=&y
t=*p1*p1=*p2*p2=t
printf("x=%d,y=%d\n",x,y)
}
运行结果为:
程序有错,不能运行!或写:
x=2,y=1
2、写出程序运行结果。
#include<stdio.h>
int max(int a,int b)
{ int c
c=a>b?a:b
return(c)
}
int min(int a,int b)
{int c
c=a<b?a:b
return(c)
}
void main()
{ int a=2,b=6
printf("max=%d\n",max(a,b))
printf(“min=%d\n”,min(a,b))
}
运行结果为:
程序有错,不能运行!或写:
max=6
min=2
3、写出程序运行结果。
#include <stdio.h>
void main()
{ int a[3][3]={1,2,3,4,5,6,7,8,9}
int i,j,sum=0
for (i=0i<3i++)
for(j=0j<3j++)
if(i==j) sum=sum+a[i][j]
printf(“sum=%d\n”,sum)
}
运行结果为:
程序有错,不能运行!或写:
sum=15
4、写出程序运行结果。
void main( )
{ int n,f
n=1
while(n<=10)
{ f=f*n
n+=2
}
printf(“f=%d\n”,&f)
}
运行结果为:
程序有错,不能运行!或写:
f=不确定
五、程序设计题(共2题,每题13分,共26分)
1、将一个数组按逆序存放,如元素1、2、3、4、5,按逆序存放后为5、4、3、2、1。