#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN sizeof(GUEST)
#define FILENAME_LEN 10
#define NULL 0
#define FORMAT "\n%20d%20s%20d\n"
#define TRUE 1
#define FALSE 0
struct guest
{
int number; /*客号*/
char name[10]; /*姓名*/
int money; /*金额*/
struct guest *pNext;
};
typedef struct guest GUEST;
/*函数的初始化*/
GUEST *Creat(void);
GUEST *Delect(GUEST *pHeadGet, int numSelect);
GUEST *ReadList(void );
char WelcomeAndTip(void);
void Insert(GUEST *pHeadGet, int numInsert);
void Show(GUEST *pHeadGet);
void Max_Print(GUEST *pHeadGet);
void ListSave(GUEST *pHeadGet);
void FoundAndPrint(GUEST *pHeadGet, int number);
void Update(GUEST *pHeadGet, int number, int newMoney);
/*
===========================
功能:main,对各个函数进行选择
返回:void
===========================
*/
void main()
{
GUEST *pHead = NULL;
char select;
int client, number;
SELECT: select = WelcomeAndTip(); /*欢迎界面*/
switch(select)
{
case 'I' :case 'i' :
if (pHead == NULL)
{
pHead = Creat();
system("cls");
Show(pHead);
}
else
{
system("cls");
printf("\n链表已经从文件读入存在\n");
}
break;
case 'D' :case 'd' :
system("cls");
Show(pHead);
printf("\n请输入您要删除的客号:");
scanf("%d", &client);
pHead = Delect(pHead, client);
system("cls");
Show(pHead);
break;
case 'S' :case 's' :
printf("请输入您要插入记录的id(不要超过当前链表的长度):");
scanf("%d", &client);
Insert(pHead, client);
system("cls");
Show(pHead);
break;
case 'Q' :case 'q':
system("cls");
Show(pHead);
break;
case 'M' :case 'm':
Max_Print(pHead);
break;
case 'B' :case 'b':
ListSave(pHead);
break;
case 'R' :case 'r':
pHead = ReadList();
system("cls");
Show(pHead);
break;
case 'F' :case 'f': /*用number作为内部的唯一id,名字会有重名*/
system("cls");
Show(pHead);
printf("\n请输入您要查询的客号:");
scanf("%d", &client);
system("cls");
FoundAndPrint(pHead, client);
break;
case 'C':case 'c':
system("cls");
Show(pHead);
printf("\n请输入要宾客的客号和结算金额(用空格隔开):");
scanf("%d%d", &number, &client);
system("cls");
Update(pHead, number, client);
break;
default :
system("pause");
system("cls");
printf("\n请重新选择\n");
break;
}
goto SELECT;
}
/*
===========================
功能:打印开始的欢迎消息和操作提示
返回:void
传入:void
===========================
*/
char WelcomeAndTip(void) /*欢迎和提示界面*/
{
int client;
char select;
printf("\t\t\t 酒店管理(文件操作)\n");
for( client =0; client < 80; client++)
{
printf("=");
}
printf("\n");
printf("I:创建\tD:删除\tQ:显示\tS:插入\tM:最大\tB:保存\tR:读入\tF:查找\tC:结算\n");
for( client =0; client < 80; client++)
{
printf("=");
}
printf("\n请输入您要进行的操作:");
scanf("%c", &select);
return select;
}
/*
===========================
功能:输出整个节点
返回:void
传入:链表的头指针
===========================
*/
void Show(GUEST *pHeadGet)
{
GUEST *pClient;
pClient = pHeadGet;
if(pClient == NULL)
{
printf("\n数据为空没有数据可以打印\n");
}
else
{
printf("\t\t客号\t\t姓名\t\t\t金额");
do
{
printf(FORMAT, pClient->number, pClient->name, pClient->money);
pClient = pClient->pNext;
}while(pClient != NULL);
}
}
/*
=========================================================
功能:创造整个节点,不对输入的数据进行控制,和错误判断。
返回:链表头指针
传入:void
=========================================================
*/
GUEST *Creat(void)
{
GUEST *pHead = NULL, *pOne = NULL, *pTwo = NULL;
int numberTemp = 1;
pOne = (GUEST *) malloc(LEN);
if(pOne == NULL)
{
printf("\n开辟不成功请重试\n");
}
else
{
pTwo = pOne;
pHead = pOne;
pTwo->pNext = NULL;
printf("\n请输入第%d个的客号,金额,用空格相隔,以0 0结束输入:", numberTemp);
scanf("%d%d", &pOne->number, &pOne->money);
_flushall();
printf("\n请输入第%d个宾客的名字: ", numberTemp);
gets(pOne->name);
}
while (pOne->number != 0)
{
pTwo = pOne;//在开辟之前,前应该给后面的指针赋予前面的指针
pOne = (GUEST *) malloc(LEN);
numberTemp++;
printf("\n请输入第%d个的客号,金额,用空格相隔:", numberTemp);
scanf("%d%d", &pOne->number, &pOne->money);
_flushall();
printf("\n请输入第%d个宾客的名字: ", numberTemp);
gets(pOne->name);
pTwo->pNext = pOne;
}
pTwo->pNext = NULL;
free(pOne);
pOne = NULL;
// free(pTwo); 空间没有开辟,何来释放
// pTwo = NULL;
return(pHead);
}
/*
======================================
功能:删除指定客号的节点
返回:void
传入:链表的头指针和要删除的结点次序
======================================
*/
GUEST *Delect(GUEST *pHeadGet, int numSelect)
{
GUEST *pOne = NULL, *pTwo = NULL;
pOne = pHeadGet;
if (pHeadGet == NULL)
{
printf("\n数据为空没有数据可以删除\n");
}
else
{
while( (pOne->number != numSelect) && (pOne->pNext != NULL) )
{
pTwo = pOne;
pOne = pOne->pNext;
}
if( numSelect == pOne->number )
{
if(pOne == pHeadGet)
{
pHeadGet = pOne->pNext;
free(pOne);
}
else
{
pTwo->pNext = pOne->pNext;
free(pOne);
}
}
else
{
printf("\n没有找到要删除的宾客:\n");
}
}
return pHeadGet; /*若数据位于头节需要返回头一节*/
}
/*
===========================
功能: 查找制定客号的数据
返回:void
传入:pHead(头指针), number(客号)
===========================
*/
void FoundAndPrint(GUEST *pHeadGet, int number)
{
GUEST *pClient = NULL;
int temp = FALSE;
pClient = pHeadGet;
if(pClient == NULL)
{
printf("\n数据为空没有数据可以查找\n");
}
else
{
while(pClient != NULL)
{
if (number == pClient->number)
{
printf("\t\t客号\t\t姓名\t\t\t金额");
printf(FORMAT, pClient->number, pClient->name, pClient->money);
temp = TRUE;
break;
}
pClient = pClient->pNext;
}
if (!temp)
{
printf("\n没有找到您要的数据,请核实!\n");
}
}
}
/*
===========================
功能:指定处(数据的那一条的后面)插入节点
返回:void
传入:链表的头指针和插入的位置
===========================
*/
void Insert(GUEST *pHeadGet, int numInsert)
{
GUEST *pOne = NULL, *pTwo = NULL, *pInsert = NULL;
int temp;
pTwo = pOne = pHeadGet;
/*这里的算法很糟糕,怎样快速定位指定的节点?*/
for( temp = 1; temp < numInsert; temp++ )
{
pTwo = pTwo->pNext;
}
pOne = pTwo->pNext;
pInsert = (GUEST *) malloc(LEN);
printf("\n请输入该客号,金额,用空格相隔:");
scanf("%d%d", &pInsert->number, &pInsert->money);
_flushall();
printf("\n请输入插入宾客名字: ");
gets(pInsert->name);
pTwo->pNext = pInsert;
pInsert->pNext = pOne;
}
/*
===========================
功能:找到最大的消费金额的宾客数据并打印
返回:void
传入:链表的头指针
===========================
*/
void Max_Print(GUEST *pHeadGet)
{
int max;
GUEST *pScan = NULL, *pPut = NULL;
if (pHeadGet == NULL)
{
printf("\n数据为空没有数据可以比较\n");
}
else
{
max = pHeadGet->money;
pScan = pHeadGet->pNext;
pPut = pHeadGet; /*初始化打印节点*/
if(pScan != NULL) /*判断是不是为一个节点的链表*/
{
do
{
if(pScan->money > max)
{
max = pScan->money;
pPut = pScan;
}
else
{
pPut = pHeadGet;
}
pScan = pScan->pNext;
} while(pScan != NULL);
}
system("cls");
printf("金额最好的宾客:\n");
printf("\t\t客号\t\t姓名\t\t\t金额");
printf(FORMAT, pPut->number, pPut->name, pPut->money);
}
}
/*
============================================================
功能:更新客户当前的消费。
当一个客户消费时,若累积消费总金额大于10000万元,
此次就打6折,大于5000万元,打8折;大于1000 元,打9折,
并更新文件中此客户的消费总金额。
返回:void
传入:pHead(链表的头指针),number(客号),newMoney(最新消费)
============================================================
*/
void Update(GUEST *pHeadGet, int number, int newMoney)
{
GUEST *pClient = NULL;
int temp = FALSE;
pClient = pHeadGet;
if(pClient == NULL)
{
printf("\n数据为空没有数据可以更新的\n");
}
else
{
while(pClient != NULL)
{
if (number == pClient->number)
{
if(pClient->money > 10000)
printf("\n这位宾客需要付款:%d\n", (int)(newMoney * 0.6));
else if ((pClient->money < 10000) && (pClient->money > 5000))
printf("\n这位宾客需要付款:%d\n", (int)(newMoney * 0.8));
else
printf("\n这位宾客需要付款:%d\n", newMoney);
pClient->money += newMoney;
temp = TRUE;
break;
}
pClient = pClient->pNext;
}
if (!temp)
{
printf("\n没有找到您要更新的数据项,请核实!\n");
}
}
}
/*
===========================
功能:保存当前链表为文件
返回:void
传入:链表的头指针
===========================
*/
void ListSave(GUEST *pHeadGet)
{
FILE *fposition = NULL;
char fileName[FILENAME_LEN];
GUEST *pOne = pHeadGet;
int listLen = 0;
if (pHeadGet == NULL)
{
printf("\n数据为空没有数据可以保存\n");
}
else
{
while (pOne)
{
pOne = pOne ->pNext;
listLen++;
} /*得到链表的长度*/
printf("\n请输入文件名,以txt方式(*.txt):");
_flushall();
gets(fileName);
if ((fposition = fopen (fileName, "w")) == NULL)
{
printf("\n打开文件失败\n");
exit(0);
}
pOne = pHeadGet;
// fprintf(fposition, "\t\t客号\t\t姓名\t\t\t金额");
while (pOne != NULL)
{
if (! fprintf(fposition, FORMAT, pOne->number,pOne->name, pOne->money))
{
printf("\n读入文件出错\n");
}
pOne = pOne->pNext;
}
fclose(fposition);
}
}
/*
===========================
功能:读入文件并创建为当前链表
返回:pHead
传入:void
===========================
*/
GUEST *ReadList(void)
{
FILE *fposition = NULL;
char fileName[FILENAME_LEN];
GUEST *pOne = NULL, *pTwo = NULL, *pHead = NULL;
printf("\n请输入您要打开的文件名,以txt方式(*.txt):");
_flushall();
gets(fileName);
if ((fposition = fopen (fileName, "r")) == NULL)
{
printf("\n打开文件失败\n");
exit(0);
}
pOne = (GUEST *) malloc(LEN);
pTwo = pOne;
pHead = pOne;
pHead->pNext = NULL;
// fseek(fposition, (long)60L, 0);
while (!feof(fposition))
{
if (!fscanf(fposition, FORMAT, &pOne->number, &pOne->name, &pOne->money))
printf("\n读入文件出错,可能文件为空,或文件不存在!\n");
pTwo = pOne;
pOne = (GUEST *) malloc(LEN);
pTwo->pNext = pOne;
}
pTwo->pNext = NULL;
free(pOne); /*释放多余的创建*/
pOne = NULL;
return pHead;
}