一、需求分析
软件的功能要求:用户可以根据自己的需求选择订房、退房、浏览所有信息、根据身份证号查询个人信息、根据姓名查询个人信息的功能,并且能够根据用户的需求显示出操作提示,十分便利,已于用户使用。用户根据操作提示进行操作就可以得到相应的结果。
软件的性能要求:系统操作方便,简单。用户可以根据系统的提示进行操作,比较人性化。在经过多次测试之后,系统稳定性大为提高,只要用户按照提示进行操作都会得到正确的回应,不会出现毫无理由的系统错误或者系统崩溃,因此系统的稳定性较高,用户可以放心使用。
二、总体设计
1.设计方案的论证:
A.运用单链表:运用单链表将文件中的内容依次存放进其结点数据域,形成一一对应的关系,在删除以及添加操作时不涉及到其他元素的移动,同时其元素的存储单元是任意的,可连续也可不连续,不需要限定长度。但是,另一方面来说此方案也存在一定的缺点,要访问或者查找问特定元素,只能从链表头开始,遍历到该元素,其查找时间复杂度为 O(n)。
B.运用顺序表:运用顺序表用一组地址连续的存储单元依次存储数据元素,其优点在于其存储结构为随机存取结构,逻辑关系可直接用数组元素下标表示。但是线性表的长度不确定,难以事先确定数组长度。同时线性表要求存储空间必须是连续的,易造成存储空间的“碎片”现象。而其在插入和删除操作需要移动大量元素。
C.运用循环链表:运用循环链表将文件中的内容依次存放进其结点数据域,形成一一对应的关系。其优点在于无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活。同时,在循环链表中,从任一结点出发都可访问到表中所有结点,这样使得在某些运算中更加容易实现(如查询操作)。
对于我们的选题来说,利用单链表更容易去实现,我们最终根据自己操作的熟练程度以及在添加、删除以及修改操作时的简便性选择了方案 A。
2. 数据结构的设计:
为了实现对相应的添加、删除、查询操作,定义了结构体数组以及单链表,并用单链表来存放相应的客人的信息。在后续操作中对相应结点中的相关数据进行直接调用。
typedef struct customer
{
char name[20];
char sex[10];
char age[3];
char id[20];
int room;
}cus;
typedef struct node
{
cus data;
struct node* next;
}Node;
Node* createList()//创建表头
{
Node* listHeadNode=(Node*)malloc(sizeof(Node));
listHeadNode->next=NULL;
return listHeadNode;
}
Node* createNode(cus data)//创建链表
{
Node* newNode=(Node*)malloc(sizeof(Node));
newNode->data=data;
newNode->next=NULL;
return newNode;
}
3.各模块的描述:
Node* createList():创建表头
Node* createNode(cus data):创建结点
void insertNodeByHead(Node* listHeadNode,cus data):头插法建立单链表
void printList(Node* listHeadNode):打印所有节点数据
Node* searchNodeByid(Node* listHeadNode,char *num):通过身份证寻找节点
Node* searchNodeByname(Node* listHeadNode,char *name):通过名字寻找节点
void printNode(Node* curNode): 打印当前节点
void deleteNodeByAppoin(Node* listHeadNode,char *name):删除节点
void readInfoFromFile(const char *fileName,Node* listHeadNode): 读取客户文本创建链表
void saveInfoToFile(const char *fileName,Node* listHeadNode): 将当前链表存进文本覆盖原来的文本
int Reservation():此函数实现订房功能
void Check_out(Node* p): 此函数实现退房功能
int IsFull():通过此函数查看此宾馆房间是否已满
4.软件结构图:
三、项目源代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct customer
{
char name[20];
char sex[10];
char age[3];
char id[20];
int room;
}cus;
typedef struct node
{
cus data;
struct node* next;
}Node;
Node* createList()//创建表头
{
Node* listHeadNode=(Node*)malloc(sizeof(Node));
listHeadNode->next=NULL;
return listHeadNode;
}
Node* createNode(cus data)//创建链表
{
Node* newNode=(Node*)malloc(sizeof(Node));
newNode->data=data;
newNode->next=NULL;
return newNode;
}
void printList(Node* listHeadNode)//打印所有节点数据
{
Node* pMove=listHeadNode->next;
printf("姓名\t性别\t年龄\t身份证号\t房间号\n");
while(pMove)
{
printf("%s\t%s\t%s\t%s\t%9d\n",pMove->data.name,pMove->data.sex,pMove->data.age,pMove->data.id,pMove->data.room);
pMove=pMove->next;
}
printf("\n");
}
void insertNodeByHead(Node* listHeadNode,cus data)//插入链表
{
Node* newNode=createNode(data);
newNode->next=listHeadNode->next;
listHeadNode->next=newNode;
}
Node* searchNodeByid(Node* listHeadNode,char *num)//通过身份证寻找节点
{
Node* pMove=listHeadNode->next;
if(pMove==NULL) return pMove;
else
{
while(strcmp(pMove->data.id,num))
{
pMove=pMove->next;
if(pMove==NULL) break;
}
return pMove;
}
}
Node* searchNodeByname(Node* listHeadNode,char *name)//通过名字寻找节点
{
Node* pMove=listHeadNode->next;
if(pMove==NULL) return pMove;
else
{
while(strcmp(pMove->data.name,name))
{
pMove=pMove->next;
if(pMove==NULL) break;
}
return pMove;
}
}
void printNode(Node* curNode)//打印当前节点
{
printf("姓名\t性别\t年龄\t身份证号\t 房间号\n");
printf("%s\t%s\t%s\t%s\t%9d\n",curNode->data.name,curNode->data.sex,curNode->data.age,curNode->data.id,curNode->data.room);
}
void deleteNodeByAppoin(Node* listHeadNode,char *name)//删除节点
{
Node* posFrontNode=listHeadNode;
Node* posNode=listHeadNode->next;
if(posNode==NULL)
{
printf("无");
return;
}
else
{
while(strcmp(posNode->data.name,name))
{
posFrontNode=posNode;
posNode=posFrontNode->next;
if(posNode==NULL)
{
printf("无");
return;
}
}
posFrontNode->next=posNode->next;
free(posNode);
}
}
void readInfoFromFile(const char *fileName,Node* listHeadNode)//读取客户文本创建链表
{
FILE *fp=fopen(fileName,"r");
if(fp==NULL)
{
fp=fopen(fileName,"w");
}
cus tempData;
while(fscanf(fp,"%s\t%s\t%s\t%s\t%d\n",tempData.name,tempData.sex,tempData.age,tempData.id,&tempData.room)!=EOF)
{
insertNodeByHead(listHeadNode,tempData);
memset(&tempData,0,sizeof(tempData));
}
fclose(fp);
}
void saveInfoToFile(const char *fileName,Node* listHeadNode)//将当前链表存进文本覆盖原来的文本
{
FILE *fp=fopen(fileName,"w");
Node* pMove=listHeadNode->next;
while(pMove)
{
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",pMove->data.name,pMove->data.sex,pMove->data.age,pMove->data.id,pMove->data.room);
pMove=pMove->next;
}
fclose(fp);
}
int Reservation()//订房系统
{
FILE *fp1,*fp2;
int i,m=0;
char ch,c[20];
fp1=fopen("roomInfo.txt","r");
for(i=0;(ch=fgetc(fp1))!=EOF;i++)
{
c[i]=ch;
}
c[i]='\0';
fclose(fp1);
for(i=0;i<10;i++)
{
if(c[i]=='0')
{
m=i+1;
*(c+i)='1';
break;
}
}
fp2=fopen("roomInfo.txt","w");
fprintf(fp2,"%s",c);
fclose(fp2);
return m;
}
void Check_out(Node* p)//退房系统
{
FILE *fp1,*fp2;
char c[15],ch;
int i,m;
fp1=fopen("roomInfo.txt","r");
for(i=0;(ch=fgetc(fp1))!=EOF;i++)
{
c[i]=ch;
}
c[i]='\0';
fclose(fp1);
for(i=0;i<10;i++)
{
if((i==p->data.room-1)||(c[i]=='1'))
{
*(c+i)='0';
break;
}
}
fp2=fopen("roomInfo.txt","w");
fprintf(fp2,"%s",c);
fclose(fp2);
}
int IsFull()//客房是否已满
{
FILE *fp;
int i,m,leap=0;
char c[15],ch;
fp=fopen("roomInfo.txt","r");
for(i=0;(ch=fgetc(fp))!=EOF;i++)
{
c[i]=ch;
}
c[i]='\0';
fclose(fp);
for(m=0;m<i;m++)
{
if(c[m]=='0')
{
leap=1;
break;
}
}
return leap;
}
int main()
{
Node* list=createList();
readInfoFromFile("customer.txt",list);
while(1){
cus tempData;
Node* p=NULL;
int num;
printf(" 欢迎使用酒店管理系统 \n");
printf("-----------------------------\n");
printf(" 【订房服务】输入1 \n");
printf(" 【退房服务】输入2 \n");
printf(" 【浏览信息】输入3 \n");
printf(" 【根据身份证号查找信息】输入4\n");
printf(" 【根据姓名查找信息】输入5 \n");
printf("请输入(1~5):");
scanf("%d",&num);
switch(num)
{
case 1:
printf("\t\t【插入信息】\n");
if(IsFull()) //还有剩余客房
{
printf("请输入姓名,性别,年龄,身份证号:");
scanf("%s%s%s%s",tempData.name,tempData.sex,tempData.age,tempData.id);
tempData.room=Reservation();
printf("房间号为%d\n",tempData.room);
insertNodeByHead(list,tempData);
saveInfoToFile("customer.txt",list);
break;
}
else //没有剩余客房
{
printf("客房已满\n");
break;
}
case 2:
printf("\t\t【删除信息】\n");
printf("请输入要删除的客人姓名:");
scanf("%s",tempData.name);
p=searchNodeByname(list,tempData.name);
Check_out(p);
deleteNodeByAppoin(list,tempData.name);
saveInfoToFile("customer.txt",list);
break;
case 3:
printf("\t\t【浏览信息】\n");
printList(list);
break;
case 4:
printf("\t\t【根据身份号查找信息】\n");
printf("请输入身份证号:");
scanf("%s",tempData.id);
if(searchNodeByid(list,tempData.id)==NULL)
{
printf("未找到\n");
}
else
{
printNode(searchNodeByid(list,tempData.id));
}
break;
case 5:
printf("\t\t【根据姓名查询信息】\n");
printf("请输入姓名:");
scanf("%s",tempData.name);
if(searchNodeByname(list,tempData.name)==NULL)
{
printf("未找到\n");
}
else
{
printNode(searchNodeByname(list,tempData.name));
}
break;
}
}
return 0;
}