Created
September 6, 2015 15:02
-
-
Save gitzhou/4d3e4d54ae9b7671b13c to your computer and use it in GitHub Desktop.
北方工业大学-计算机系-大一-小学期-冰鞋管理系统-C代码
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// skate-shoes-rent-system | |
// | |
// Created by aaron67 on 15/9/6. | |
// Copyright (c) 2015年 aaron67. All rights reserved. | |
// | |
// Mac OS X Yosemite环境测试可用 | |
// 在可执行文件相同路径下,新建文件 | |
// - rent.dat | |
// - shoes.dat | |
// - count.dat | |
// - number.dat | |
// - password.dat | |
// 初次运行,先查看 short CheckPassword(); | |
// 了解初始化密码的方式。 | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
/***************************** 模 型 设 计 ***********************************/ | |
// 字符串最大长度 | |
#define STRING_MAX_SIZE 1024 | |
// 冰鞋类型 | |
// Speed 速滑冰鞋 | |
// Synchronise 花样冰鞋 | |
typedef enum ShoeType {Speed = 0, Synchronise = 1} ShoeType; | |
// 字符串类型 | |
typedef struct String | |
{ | |
char string[STRING_MAX_SIZE]; // 字符数组 | |
unsigned long length; // 字符串有效长度 | |
} String; | |
// 日期类型 | |
typedef struct Date | |
{ | |
int year; // 年 | |
int month; // 月 | |
int day; // 日 | |
String string; // 字符串形式 | |
} Date; | |
// 时间类型 | |
typedef struct Time | |
{ | |
int hour; // 时 | |
int minute; // 分 | |
int second; // 秒 | |
String string; // 字符串形式 | |
} Time; | |
// 冰鞋详细信息 | |
// 对应 shoes.dat | |
typedef struct SkateShoe | |
{ | |
String key_number; // 编码 | |
ShoeType type; // 类型 | |
double size; // 鞋号 | |
String color; // 颜色 | |
String brand; // 品牌 | |
double unit_price; // 单价 | |
String manufacturer; // 厂家 | |
short rent_status; // 租用状态 1 表示已租用 | |
short remark; // 说明 1 表示需要维修 | |
short status; // 标记该条记录是否有效 1 表示有效 | |
} SkateShoe; | |
// 冰鞋数量信息 | |
// 对应 number.dat | |
typedef struct ShoeNumber | |
{ | |
double shoe_size; // 鞋号 | |
ShoeType shoe_type; // 冰鞋类型 | |
int total_quantity; // 总数量 | |
int left_quantity; // 剩余数量 | |
short status; // 标记该条记录是否有效 1 表示有效 | |
} ShoeNumber; | |
// 冰鞋租用详细信息 | |
// 对应 rent.dat | |
typedef struct RentDetails | |
{ | |
String user_name; // 姓名 | |
String id_number; // 身份证号 | |
String contact_info; // 联系方式 | |
double shoe_size; // 鞋号 | |
String shoe_key_number; // 冰鞋编码 | |
ShoeType shoe_type; // 冰鞋类型 | |
Date date; // 日期 | |
Time rent_time; // 起始日期 | |
double deposit; // 押金 | |
double rent_price_per_hour; // 每小时租金 | |
short status; // 标记该条记录是否有效 1 表示有效 | |
} RentDetails; | |
// 冰鞋归还详细信息 | |
// 对应 count.dat | |
typedef struct BackDetails | |
{ | |
Date back_date; // 归还日期 | |
double shoe_size; // 鞋号 | |
ShoeType shoe_type; // 冰鞋类型 | |
double lend_hours; // 租用时间 | |
double rent_price_per_hour; // 每小时租金 | |
double total_cost; // 总花费 | |
} BackDetails; | |
/***************************** 函 数 声 明 ***********************************/ | |
/************************* 类 Sring 函 数 声 明 ******************************/ | |
// String 对象初始化 | |
void StringInit(String *str); | |
// 从控制台向 String 类对象 *str 中输入数据 | |
void StringInput(String *str); | |
// 比较两个 String 类对象 str 和 target | |
// 程序返回值 | |
// 等于 0 str = target | |
// 大于 0 str > target | |
// 小于 0 str < target | |
short StringCompare(String str, String target); | |
// 返回 String 类对象 str 的有效长度 | |
unsigned long StringLength(String str); | |
// 将 String 类对象 from 拷贝到 *str 中 | |
void StringCopy(String *str, String from); | |
// 将字符串 sz 拷贝到 String 类对象 *str 中 | |
void StringCopyFromCharArray(String *str, char *sz); | |
// 返回 String 类对象 str 中字符数组的指针 | |
char *StringGetString(String *str); | |
/************************ 类 Date 类 Time 函 数 声 明 ************************/ | |
// 输入日期 | |
void DateInput(Date *date); | |
// 输入时间 | |
void TimeInput(Time *time); | |
// 返回 date 表示日期的字符串 | |
char *DateGetString(Date date); | |
// 返回 time 表示时间的字符串 | |
char *TimeGetString(Time time); | |
// 计算两个时间的差 | |
// 程序返回小时数 | |
// 返回 -1 表示错误 | |
double CalculateHours(Time st, Time et); | |
// 比较 date 和 target 的大小 | |
// 1 date > target | |
// 0 date = target | |
// -1 date < target | |
short DateCompare(Date date, Date target); | |
// 比较 time 和 target 的大小 | |
// 1 time > target | |
// 0 time = target | |
// -1 time < target | |
short TimeCompare(Time time, Time target); | |
/*************************** 主 系 统 函 数 声 明 ****************************/ | |
// 显示欢迎画面 | |
void ShowHello(); | |
// 冰鞋租用 | |
void RentShoes(); | |
// 冰鞋归还 | |
void BackShoes(); | |
// 数据维护 | |
void DataModify(); | |
// 密码修改 | |
void PasswordModify(); | |
// 综合查询 | |
void GeneralQuery(); | |
// 退出主系统 | |
void QuitMainSystem(); | |
/******************** 数 据 维 护 子 系 统 函 数 声 明 ***********************/ | |
// 新增冰鞋数据 | |
void AddShoes(); | |
// 更新冰鞋数据 | |
void UpdateShoes(); | |
// 删除冰鞋数据 | |
void DeleteShoes(); | |
// 退出数据维护子系统 | |
void QuitDataModifySystem(); | |
/******************** 综 合 查 询 子 系 统 函 数 声 明 ***********************/ | |
// 打印全部信息 | |
void DisplayAllFiles(); | |
// 查询统计 | |
void Query(); | |
// 退出综合查询子系统 | |
void QuitGeneralQuerySystem(); | |
/********************** 冰 鞋 租 还 处 理 函 数 声 明 ************************/ | |
// 将记录 rd 写入文件 rent.dat | |
// append = 1 则追加写入 否则在下标 pos 指示的相对位置写入 程序返回 | |
// 0 写入成功 | |
// -1 打开文件错误 | |
// -2 未知错误 | |
short RentDetailsWrite2File(RentDetails rd, int pos, short append); | |
// 将记录 bd 写入文件 count.dat | |
// append = 1 则追加写入 否则在下标 pos 指示的相对位置写入 程序返回 | |
// 0 写入成功 | |
// -1 打开文件错误 | |
// -2 未知错误 | |
short BackDetailsWrite2File(BackDetails bd, int pos, short append); | |
// 根据用户姓名 user_name 身份证号 id_number 冰鞋编号 key_number | |
// 在文件 rent.dat 中查找相应记录 程序返回 | |
// >= 0 记录在文件中的下标 | |
// -3 查找不成功 | |
// -1 文件打开错误 | |
// -2 未知错误 | |
int FindRentRecord(String user_name, String id_number, String key_number, RentDetails *rd); | |
/******************** 查 询 统 计 子 系 统 函 数 声 明 ***********************/ | |
// 查询冰鞋信息 | |
void QueryShoes(); | |
// 根据查询条件从文件 shoe.dat 中查询符合条件的记录 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short QueryShoesFromFile(String key_number, String type, String size, | |
String color, String brand, String manufacturer, | |
String rent_status, String remark); | |
// 查询数量信息 | |
void QueryNumber(); | |
// 根据查询条件从文件 number.dat 中查询符合条件的记录 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short QueryNumberFromFile(String shoe_size, String shoe_type, String total_quantity, String left_quantity); | |
// 查询租用信息 | |
void QueryRentDetails(); | |
// 根据查询条件从文件 rent.dat 中查询符合条件的记录 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short QueryRentDetailsFromFile(String user_name, String id_number, String size, String date); | |
// 计算当日收入 | |
void CalculateIncome(); | |
// 退出查询统计子系统 | |
void QuitQuerySystem(); | |
// 显示查询结果列表表头 | |
void DisplayQueryTitle(); | |
// 同时统计结果列表表头 | |
void DisplayStatisticsTitle(); | |
/**************************** 打 印 函 数 声 明 ******************************/ | |
// 打印 shoes.dat 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short DisplayShoes(); | |
// 打印 number.dat 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short DisplayNumber(); | |
// 打印 rent.dat 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short DisplayRent(); | |
// 打印 count.dat 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short DisplayCount(); | |
// 打印计费单据 | |
void DisplayCostDetails(BackDetails bd); | |
/********************** 冰 鞋 数 据 处 理 函 数 声 明 ************************/ | |
// 冰鞋详细信息对象初始化 | |
void SkateShoeInit(SkateShoe *ss); | |
// 冰鞋数量信息对象初始化 | |
void ShoeNumberInit(ShoeNumber *sn); | |
// 租用详细信息对象初始化 | |
void RentDetailsInit(RentDetails *rd); | |
// 设置 SkateShoe 对象 *ss 的值 | |
// UpdateShoes() 为 1 表示是在更新记录 此时不用输入编号 | |
// 成功返回 0 | |
// 失败返回 -1 | |
short GetShoeData(SkateShoe *ss, short update); | |
// 将记录 ss 写入文件 shoes.dat | |
// append = 1 则追加写入 否则在下标 pos 指示的相对位置写入 返回 | |
// 0 写入成功 | |
// -1 打开文件错误 | |
// -2 未知错误 | |
short ShoesWrite2File(SkateShoe ss, long pos, short append); | |
// 通过编号 key 查找冰鞋信息 | |
// >=0 查找成功 返回的是记录在文件中的下标 | |
// -3 查找失败 | |
// -1 文件打开错误 | |
int FindShoesByKey(String key, SkateShoe *ss); | |
// 新增冰鞋数据时显示生成的标签 | |
void DisplayLabel(SkateShoe ss); | |
/*********************** 冰 鞋 数 量 维 护 函 数 声 明 ***********************/ | |
// 在新增冰鞋数据时更新数量文件 number.dat | |
// flag_back = 1 时表明是 UpdateNumberWhenBackShoes() 调用 | |
void UpdateNumberWhenAddShoes(SkateShoe ss, short flag_back); | |
// 在删除冰鞋数据时更新数量文件 number.dat | |
// flag_rent = 1 时表明是 UpdateNumberWhenRentShoes() 调用 | |
void UpdateNumberWhenDeleteShoes(SkateShoe ss, short flag_rent); | |
// 在更新冰鞋数据时更新数量文件 number.dat | |
void UpdateNumberWhenUpdateShoes(SkateShoe old_ss, SkateShoe new_ss); | |
// 在租用冰鞋时更新数量文件 number.dat | |
void UpdateNumberWhenRentShoes(SkateShoe ss); | |
// 在退租冰鞋时更新数量文件 number.dat | |
void UpdateNumberWhenBackShoes(SkateShoe ss); | |
// 向文件 number.dat 中写入一条记录 | |
// append = 1 则追加写入 | |
// 否则在下标 pos 指示的相对位置写入 | |
// 0 写入成功 | |
// -1 文件打开错误 | |
// -2 未知错误 | |
short NumberWrite2File(ShoeNumber sn, int pos, short append); | |
// 根据鞋号和冰鞋类型在 number.dat 文件中找到记录的下标并返回 | |
// >0 查找成功 | |
// -3 查找失败 | |
// -1 文件打开错误 | |
int FindNumberRecord(double shoe_size, ShoeType st, ShoeNumber *sn); | |
/************************** 密 码 处 理 函 数 声 明 **************************/ | |
// 初始化密码为 gitzhou | |
void InitPassword(); | |
// 更新密码为 str 返回 | |
// 0 更新成功 | |
// -1 文件打开错误 | |
// -2 未知错误 | |
short UpdatePassword(String str); | |
// 处理密码输入的同时在控制台上显示星号 | |
void InputPassword(String *str); | |
// 检测用户输入的密码是否正确 返回 | |
// 2 密码初始化成功 | |
// 1 密码正确 | |
// 0 密码错误 | |
// -1 文件打开错误 | |
// -2 未知错误 | |
short CheckPassword(); | |
/**************************** 菜 单 函 数 声 明 ******************************/ | |
// 显示程序主菜单 | |
void ShowMainMenu(); | |
// 显示数据维护菜单 | |
void ShowDataModifyMenu(); | |
// 显示综合查询菜单 | |
void ShowGeneralQueryMenu(); | |
// 显示查询统计菜单 | |
void ShowQueryMenu(); | |
/******************************** 程 序 入 口 ********************************/ | |
int main() | |
{ | |
short pwd_check; // 密码匹配结果 | |
ShowHello(); // 显示欢迎画面 | |
// 检测密码匹配情况 | |
if((pwd_check = CheckPassword()) == 1 || pwd_check == 2) | |
{ | |
// 通过 | |
printf("\n\n"); | |
ShowMainMenu(); | |
} | |
else if(pwd_check == 0) | |
{ | |
// 未通过 | |
printf("\n\n\a密码输入错误,程序结束!\n"); | |
QuitMainSystem(); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\n\a未知错误,程序结束!\n"); | |
QuitMainSystem(); | |
} | |
return 0; | |
} | |
/***************************** 函 数 实 现 ***********************************/ | |
/************************* 类 Sring 函 数 实 现 ******************************/ | |
// String 对象初始化 | |
void StringInit(String *str) | |
{ | |
(str->string)[0] = 0; | |
str->length = 0; | |
} | |
// 从控制台向 String 类对象 *str 中输入数据 | |
void StringInput(String *str) | |
{ | |
gets(str->string); | |
str->length = strlen(str->string); | |
} | |
// 比较两个 String 类对象 str 和 target | |
// 程序返回值 | |
// 等于 0 str = target | |
// 大于 0 str > target | |
// 小于 0 str < target | |
short StringCompare(String str, String target) | |
{ | |
return strcmp(str.string, target.string); | |
} | |
// 返回 String 类对象 str 的有效长度 | |
unsigned long StringLength(String str) | |
{ | |
return str.length; | |
} | |
// 将 String 类对象 from 拷贝到 *str 中 | |
void StringCopy(String *str, String from) | |
{ | |
strcpy(str->string, from.string); | |
str->length = from.length; | |
} | |
// 将字符串 sz 拷贝到 String 类对象 *str 中 | |
void StringCopyFromCharArray(String *str, char *sz) | |
{ | |
strcpy(str->string, sz); | |
str->length = strlen(sz); | |
} | |
// 返回 String 类对象 str 中字符数组的指针 | |
char *StringGetString(String *str) | |
{ | |
return str->string; | |
} | |
/************************ 类 Date 类 Time 函 数 实 现 ************************/ | |
// 输入日期 | |
void DateInput(Date *date) | |
{ | |
char str[STRING_MAX_SIZE]; | |
scanf("%d/%d/%d", &(date->year), &(date->month), &(date->day)); | |
// 拼装字符串 拼完后格式为 年/月/日 | |
sprintf(str, "%d/%d/%d", date->year, date->month, date->day); | |
// 赋值 | |
StringCopyFromCharArray(&(date->string), str); | |
} | |
// 输入时间 | |
void TimeInput(Time *time) | |
{ | |
char str[STRING_MAX_SIZE]; | |
scanf("%d-%d", &(time->hour), &(time->minute)); | |
time->second = 0; | |
// 拼装字符串 拼完后格式为 时:分 | |
sprintf(str, "%d-%d", time->hour, time->minute); | |
// 赋值 | |
StringCopyFromCharArray(&(time->string), str); | |
} | |
// 返回 date 表示日期的字符串 | |
char *DateGetString(Date date) | |
{ | |
return StringGetString(&date.string); | |
} | |
// 返回 time 表示时间的字符串 | |
char *TimeGetString(Time time) | |
{ | |
return StringGetString(&time.string); | |
} | |
// 计算两个时间的差 | |
// 程序返回小时数 | |
// 返回 -1 表示错误 | |
double CalculateHours(Time st, Time et) | |
{ | |
double d_ansr; // 时间差计算结果 | |
int i_ansr; // 中间变量 | |
short fn_retn_value; // 存放调用 TimeCompare() 函数的返回值 | |
if((fn_retn_value = TimeCompare(et, st)) < 0) | |
{ | |
// 终止时间 < 起始时间 | |
printf("\n\a出错!\n"); | |
return -1; | |
} | |
else if(fn_retn_value == 0) | |
{ | |
// 终止时间 = 起始时间 | |
return 0.0; | |
} | |
// 终止时间 > 起始时间 | |
// 计算时间差 取小数点后一位 | |
d_ansr = ((et.hour - st.hour) * 60 + et.minute - st.minute) / 60.0; | |
i_ansr = (int)(d_ansr * 10); | |
d_ansr = i_ansr / 10.0; | |
return d_ansr; | |
} | |
// 比较 date 和 target 的大小 | |
// 1 date > target | |
// 0 date = target | |
// -1 date < target | |
short DateCompare(Date date, Date target) | |
{ | |
// 比较 年 | |
if(date.year > target.year) | |
{ | |
return 1; | |
} | |
else if(date.year < target.year) | |
{ | |
return -1; | |
} | |
else | |
{ | |
// 比较 月 | |
if(date.month > target.month) | |
{ | |
return 1; | |
} | |
else if(date.month < target.month) | |
{ | |
return -1; | |
} | |
else | |
{ | |
// 比较 日 | |
if(date.day > target.day) | |
{ | |
return 1; | |
} | |
else if(date.day < target.day) | |
{ | |
return -1; | |
} | |
else | |
{ | |
return 0; | |
} | |
} | |
} | |
} | |
// 比较 time 和 target 的大小 | |
// 1 time > target | |
// 0 time = target | |
// -1 time < target | |
short TimeCompare(Time time, Time target) | |
{ | |
// 比较 时 | |
if(time.hour > target.hour) | |
{ | |
return 1; | |
} | |
else if(time.hour < target.hour) | |
{ | |
return -1; | |
} | |
else | |
{ | |
// 比较 分 | |
if(time.minute > target.minute) | |
{ | |
return 1; | |
} | |
else if(time.minute < target.minute) | |
{ | |
return -1; | |
} | |
else | |
{ | |
// 比较 秒 | |
if(time.second > target.second) | |
{ | |
return 1; | |
} | |
else if(time.second < target.second) | |
{ | |
return -1; | |
} | |
else | |
{ | |
return 0; | |
} | |
} | |
} | |
} | |
/*************************** 主 系 统 函 数 实 现 ****************************/ | |
// 显示欢迎画面 | |
void ShowHello() | |
{ | |
printf("\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 欢 迎 使 用 冰 鞋 租 用 管 理 系 统 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
} | |
// 冰鞋租用 | |
void RentShoes() | |
{ | |
ShoeNumber sn; // 冰鞋数量对象 | |
SkateShoe ss; // 冰鞋信息对象 | |
RentDetails rd; // 租用信息对象 | |
int pos_sn; // 存放相应数量记录在文件中的下标 | |
int pos_ss; // 存放相应冰鞋记录在文件中的下标 | |
int flag_rent_continue = 1; // 标记 为 1 表示继续租用其它冰鞋 | |
String input_option; // 存放用户选择是否继续的输入 | |
double shoe_size; // 鞋号 | |
ShoeType shoe_type; // 冰鞋类型 | |
String input_type; // 用户输入的鞋号 | |
String input_size; // 用户输入的冰鞋类型 | |
// 常量 String 对象 | |
String null; | |
String rent_status_0; | |
StringCopyFromCharArray(&null, "null"); | |
StringCopyFromCharArray(&rent_status_0, "0"); | |
// 初始化各对象 | |
ShoeNumberInit(&sn); | |
SkateShoeInit(&ss); | |
RentDetailsInit(&rd); | |
StringInit(&input_type); | |
StringInit(&input_size); | |
StringInit(&input_option); | |
while(flag_rent_continue) | |
{ | |
// 输入查询的鞋号 | |
printf("\n请输入要租用的冰鞋鞋号: "); | |
StringInput(&input_size); | |
if(StringLength(input_size) == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
shoe_size = atof(StringGetString(&input_size)); | |
// 输入查询的冰鞋类型 | |
printf("请选择冰鞋的类型,0 -> 速滑冰鞋 1 -> 花样冰鞋: "); | |
StringInput(&input_type); | |
if(strcmp(StringGetString(&input_type), "0") != 0 && | |
strcmp(StringGetString(&input_type), "1") != 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
shoe_type = atoi(StringGetString(&input_type)); | |
// 取到对应的数量记录 | |
if((pos_sn = FindNumberRecord(shoe_size, shoe_type, &sn)) >= 0) | |
{ | |
if(sn.left_quantity == 0) | |
{ | |
// 没有余鞋 | |
printf("\n\a抱歉,没有余鞋!\n"); | |
} | |
else | |
{ | |
// 有余鞋 可以租用 | |
// 显示可租的冰鞋列表 | |
DisplayQueryTitle(); | |
QueryShoesFromFile(null, input_type, input_size, null, null, null, rent_status_0, null); | |
// 生成 RentDetails 对象 | |
if(flag_rent_continue == 1) | |
{ | |
// flag_rent_continue = 1 表明是用户第一次输入个人信息 | |
// 输入姓名 | |
printf("请输入您的姓名: "); | |
StringInput(&(rd.user_name)); | |
if(StringLength(rd.user_name) == 0) | |
{ | |
printf("\n\a输入错误!\n"); | |
return; | |
} | |
// 输入身份证号 | |
printf("身份证号: "); | |
StringInput(&(rd.id_number)); | |
if(StringLength(rd.id_number) == 0) | |
{ | |
printf("\n\a输入错误!\n"); | |
return; | |
} | |
// 输入联系方式 | |
printf("联系方式: "); | |
StringInput(&rd.contact_info); | |
if(StringLength(rd.contact_info) == 0) | |
{ | |
printf("\n\a输入错误!\n"); | |
return; | |
} | |
// 更新标记 | |
++flag_rent_continue; | |
} | |
// 冰鞋编号 | |
printf("待租用冰鞋编号: "); | |
StringInput(&rd.shoe_key_number); | |
if(StringLength(rd.shoe_key_number) == 0) | |
{ | |
printf("\n\a输入错误!\n"); | |
return; | |
} | |
// RentDetails 对象记录生成完毕 | |
// 取出对应的冰鞋记录 | |
if((pos_ss = FindShoesByKey(rd.shoe_key_number, &ss)) >= 0) | |
{ | |
// 存在对应的冰鞋记录 | |
if(ss.rent_status == 0) | |
{ | |
// 冰鞋未被租用 | |
rd.shoe_size = ss.size; // 鞋号 | |
rd.shoe_type = ss.type; // 冰鞋类型 | |
// 输入日期 | |
printf("\n租用日期,格式 年/月/日: "); | |
DateInput(&(rd.date)); | |
// 输入时间 | |
printf("租用时间,格式 时-分: "); | |
TimeInput(&(rd.rent_time)); | |
// 更新 shoes.dat 文件 | |
ss.rent_status = 1; | |
if(ShoesWrite2File(ss, pos_ss, 0) != 0) | |
{ | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
//更新 rent.dat 文件 | |
RentDetailsWrite2File(rd, 0, 1); | |
// 更新 number.dat 文件 | |
UpdateNumberWhenRentShoes(ss); | |
} | |
else | |
{ | |
// 冰鞋已被租用 | |
printf("\n\a此编号的冰鞋已被租用!\n"); | |
} | |
} | |
else if(pos_ss == -3) | |
{ | |
// 不存在这种编号的冰鞋 | |
printf("\n\a没有此编号的冰鞋!\n"); | |
} | |
else | |
{ | |
// 位置错误 | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
} | |
else if(pos_sn == -3) | |
{ | |
// 无符合要求的冰鞋 | |
printf("\n\a没有符合要求的冰鞋!\n"); | |
} | |
else | |
{ | |
// 位置错误 | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
// 询问是否继续 | |
fflush(stdin); | |
printf("\n您还需要继续租用其它冰鞋吗? (Y/N): "); | |
StringInput(&input_option); | |
if(strcmp(StringGetString(&input_option), "Y") != 0 && | |
strcmp(StringGetString(&input_option), "y") != 0 && | |
strcmp(StringGetString(&input_option), "N") != 0 && | |
strcmp(StringGetString(&input_option), "n") != 0) | |
{ | |
printf("\n\n\a输入错误!\n"); | |
flag_rent_continue = 0; | |
} | |
else if(!strcmp(StringGetString(&input_option), "N") || | |
!strcmp(StringGetString(&input_option), "n")) | |
{ | |
flag_rent_continue = 0; | |
} | |
} // end of while | |
} | |
// 冰鞋归还 | |
void BackShoes() | |
{ | |
SkateShoe ss; // 冰鞋信息对象 | |
RentDetails rd; // 租用信息对象 | |
BackDetails bd; // 归还信息对象 | |
int pos_ss; // 相应的冰鞋信息记录在文件中的下标 | |
int pos_rd; // 相应的租用信息记录在文件中的下标 | |
int flag_back_continue = 1; // 标记 为 1 表示仍要归还其他冰鞋 | |
String input_option; // 用户输入的选项 | |
short flag_query_rent = 0; // 标记 为 1 表明有相应的租用记录 | |
String input_user_name; // 用户输入的姓名 | |
String input_id_number; // 用户输入的身份证号 | |
String input_key_number; // 用户输入的冰鞋编号 | |
Time input_back_time; // 用户输入的归还时间 | |
// 常量 String 对象 | |
String null; | |
StringCopyFromCharArray(&null, "null"); | |
// 初始化各对象 | |
SkateShoeInit(&ss); | |
RentDetailsInit(&rd); | |
StringInit(&input_user_name); | |
StringInit(&input_id_number); | |
StringInit(&input_key_number); | |
StringInit(&input_option); | |
while(flag_back_continue) | |
{ | |
// 输入姓名 | |
printf("\n请输入您的姓名: "); | |
StringInput(&input_user_name); | |
if(StringLength(input_user_name) == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
// 输入身份证号 | |
printf("您的身份证号: "); | |
StringInput(&input_id_number); | |
if(StringLength(input_id_number) == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
// 输出用户租用记录 | |
DisplayQueryTitle(); | |
if((flag_query_rent = QueryRentDetailsFromFile(input_user_name, input_id_number, null, null)) == 1) | |
{ | |
// 存在该用户的租用记录 | |
// 输入归还的冰鞋编号 | |
printf("请输入冰鞋编号: "); | |
StringInput(&input_key_number); | |
if(StringLength(input_key_number) == 0) | |
{ | |
printf("\n\a输入错误!\n"); | |
return; | |
} | |
// 取到对应的冰鞋记录 | |
if((pos_ss = FindShoesByKey(input_key_number, &ss)) >= 0) | |
{ | |
// 取到对应的租用记录 | |
if((pos_rd = FindRentRecord(input_user_name, input_id_number, input_key_number, &rd)) >= 0) | |
{ | |
// 输入冰鞋的归还时间 | |
printf("时间,格式 时-分: "); | |
TimeInput(&input_back_time); | |
// 拼装新的 BackDetails 记录 | |
bd.back_date = rd.date; | |
if((bd.lend_hours = CalculateHours(rd.rent_time, input_back_time)) == -1) | |
{ | |
printf("\n\a请核对时间!\n"); | |
return; | |
} | |
bd.rent_price_per_hour = rd.rent_price_per_hour; | |
bd.shoe_size = rd.shoe_size; | |
bd.shoe_type = rd.shoe_type; | |
bd.total_cost = bd.rent_price_per_hour * bd.lend_hours; | |
// 更新取到的 RentDetails 记录 | |
rd.status = 0; | |
// 更新取到的 SkateShoe 记录 | |
ss.rent_status = 0; | |
// 更新对应的 ShoeNumber 记录 | |
UpdateNumberWhenBackShoes(ss); | |
// 将更新后的记录分别写入文件 | |
if(!ShoesWrite2File(ss, pos_ss, 0) && | |
!RentDetailsWrite2File(rd, pos_rd, 0) && | |
!BackDetailsWrite2File(bd, 0, 1)) | |
{ | |
printf("\n冰鞋归还成功!\n"); | |
// 输出计费单据 | |
DisplayCostDetails(bd); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
else if(pos_rd == -3) | |
{ | |
// 没有相应的租用记录 | |
printf("\n\a没有相应的租用记录!\n"); | |
} | |
else | |
{ | |
// 位置错误 | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
else if(pos_ss == -3) | |
{ | |
// 没有此编号的冰鞋 | |
printf("\n\a没有此编号的冰鞋!\n"); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
else if(flag_query_rent == 0) | |
{ | |
// 没有相应的租用记录 | |
printf("\a没有相应的租用记录!\n"); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\a未知错误!\n"); | |
return; | |
} | |
// 询问是否继续 | |
fflush(stdin); | |
printf("\n您还需要归还其它冰鞋吗? (Y/N): "); | |
StringInput(&input_option); | |
if(strcmp(StringGetString(&input_option), "Y") != 0 && | |
strcmp(StringGetString(&input_option), "y") != 0 && | |
strcmp(StringGetString(&input_option), "N") != 0 && | |
strcmp(StringGetString(&input_option), "n") != 0) | |
{ | |
printf("\n\n\a输入错误!\n"); | |
flag_back_continue = 0; | |
} | |
else if(!strcmp(StringGetString(&input_option), "N") || | |
!strcmp(StringGetString(&input_option), "n")) | |
{ | |
flag_back_continue = 0; | |
} | |
} // end of while | |
} | |
// 数据维护 | |
void DataModify() | |
{ | |
// 显示子系统菜单 | |
ShowDataModifyMenu(); | |
} | |
// 密码修改 | |
void PasswordModify() | |
{ | |
String new_pwd, confirm_pwd; // 新密码和第二次输入的新密码 | |
short pwd_check; // 输入的旧密码是否验证通过 | |
// 初始化各对象 | |
StringInit(&new_pwd); | |
StringInit(&confirm_pwd); | |
// 验证密码 | |
if((pwd_check = CheckPassword()) == 1) | |
{ | |
// 验证通过 | |
printf("\n\n请输入新密码,以 Enter 结束输入: "); | |
InputPassword(&new_pwd); | |
printf("\n\n请再输入新密码,以 Enter 结束输入: "); | |
InputPassword(&confirm_pwd); | |
// 验证两次输入的新密码是否一致 | |
if(StringCompare(new_pwd, confirm_pwd) == 0) | |
{ | |
// 一致 | |
// 更新密码 | |
if(UpdatePassword(new_pwd) == 0) | |
{ | |
// 更新成功 | |
printf("\n\n密码修改成功!\n"); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\n\a未知错误!\n"); | |
return; | |
} | |
} | |
else | |
{ | |
// 不一致 | |
printf("\n\n\a两次输入的密码不一致!\n"); | |
return; | |
} | |
} | |
else if(pwd_check == 0) | |
{ | |
// 验证失败 | |
printf("\n\n\a密码错误!\n"); | |
} | |
else if(pwd_check == 2) | |
{ | |
// 初始化密码 | |
printf("\n"); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\n\a未知错误!\n"); | |
} | |
} | |
// 综合查询 | |
void GeneralQuery() | |
{ | |
// 显示子系统菜单 | |
ShowGeneralQueryMenu(); | |
} | |
// 退出主系统 | |
void QuitMainSystem() | |
{ | |
printf("\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 感 谢 使 用 冰 鞋 租 用 管 理 系 统 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
} | |
/******************** 数 据 维 护 子 系 统 函 数 实 现 ***********************/ | |
// 新增冰鞋数据 | |
void AddShoes() | |
{ | |
SkateShoe ss; // 冰鞋信息对象 | |
SkateShoeInit(&ss); // 初始化对象 | |
// 获得用户输入 | |
printf("\n"); | |
if(GetShoeData(&ss, 0) == 0) | |
{ | |
// 用户输入成功 | |
// 将记录写入文件 | |
if(ShoesWrite2File(ss, 0, 1) == 0) | |
{ | |
// 写入成功 | |
printf("\n新增数据成功!\n"); | |
// 打印标签 | |
DisplayLabel(ss); | |
// 更新 number.dat | |
UpdateNumberWhenAddShoes(ss, 0); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a错误!\n"); | |
} | |
} | |
else | |
{ | |
// 用户输入出错 | |
printf("\n\a输入出错,新增数据失败!\n"); | |
} | |
} | |
// 更新冰鞋数据 | |
void UpdateShoes() | |
{ | |
int pos; // 相应的冰鞋信息记录在文件中的下标 | |
SkateShoe old_ss; // 原冰鞋信息记录 | |
SkateShoe new_ss; // 更新后的冰鞋信息记录 | |
String input_key_number; // 输入的冰鞋编号 | |
// 初始化各对象 | |
SkateShoeInit(&old_ss); | |
SkateShoeInit(&new_ss); | |
StringInit(&input_key_number); | |
// 输入冰鞋编号 | |
printf("\n请输入冰鞋编号: "); | |
StringInput(&input_key_number); | |
// 查询 | |
if((pos = FindShoesByKey(input_key_number, &old_ss)) >= 0) | |
{ | |
// 查询成功 | |
if(old_ss.rent_status == 1) | |
{ | |
// 如果冰鞋被借出则不允许更新信息 | |
printf("\n\a冰鞋已被租用,不能更新该条记录!\n"); | |
return; | |
} | |
else | |
{ | |
// 可以更新这条记录 | |
// 获得用户输入 | |
if(GetShoeData(&new_ss, 1) == 0) | |
{ | |
// 输入成功 | |
StringCopy(&(new_ss.key_number), old_ss.key_number); | |
// 将新记录写入文件 | |
if(ShoesWrite2File(new_ss, pos, 0) == 0) | |
{ | |
// 更新成功 | |
printf("\n更新成功!\n"); | |
// 更新 number.dat | |
UpdateNumberWhenUpdateShoes(old_ss, new_ss); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a错误,更新失败!\n"); | |
return; | |
} | |
} | |
else | |
{ | |
// 输入出错 | |
printf("\n\a错误!\n"); | |
return; | |
} | |
} | |
} | |
else if(pos == -3) | |
{ | |
// 查询失败 | |
printf("\n\a无此编号的冰鞋!\n"); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a未知错误!\n"); | |
} | |
} | |
// 删除冰鞋数据 | |
void DeleteShoes() | |
{ | |
int pos; // 相应的冰鞋信息记录在文件中的下标 | |
SkateShoe ss; // 冰鞋信息对象 | |
String input_key_number; // 用户输入的冰鞋编号 | |
// 初始化各对象 | |
SkateShoeInit(&ss); | |
StringInit(&input_key_number); | |
// 输入冰鞋编号 | |
printf("\n请输入冰鞋编号: "); | |
StringInput(&input_key_number); | |
// 查询 | |
if((pos = FindShoesByKey(input_key_number, &ss)) >= 0) | |
{ | |
// 查询成功 | |
if(ss.rent_status == 1) | |
{ | |
// 如果冰鞋借出则不能删除记录 | |
printf("\n\a冰鞋已被租用,不能删除该条记录!\n"); | |
return; | |
} | |
else | |
{ | |
// 可以删除这条记录 | |
ss.status = 0; | |
// 更新文件 | |
if(ShoesWrite2File(ss, pos, 0) == 0) | |
{ | |
// 删除成功 | |
printf("\n删除成功!\n"); | |
// 更新 number.dat | |
UpdateNumberWhenDeleteShoes(ss, 0); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a错误,删除失败!\n"); | |
return; | |
} | |
} | |
} | |
else if(pos == -3) | |
{ | |
// 查询失败 | |
printf("\n\a无此编号的冰鞋!\n"); | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a未知错误!\n"); | |
} | |
} | |
// 退出数据维护子系统 | |
void QuitDataModifySystem() | |
{ | |
printf("\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 感 谢 使 用 数 据 维 护 子 系 统 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
} | |
/******************** 综 合 查 询 子 系 统 函 数 实 现 ***********************/ | |
// 打印全部信息 | |
void DisplayAllFiles() | |
{ | |
printf("\n"); | |
DisplayShoes(); // 打印 shoes.dat | |
DisplayNumber(); // 打印 number.dat | |
DisplayRent(); // 打印 rent.dat | |
DisplayCount(); // 打印 count.dat | |
} | |
// 查询统计 | |
void Query() | |
{ | |
// 显示子系统菜单 | |
ShowQueryMenu(); | |
} | |
// 退出综合查询子系统 | |
void QuitGeneralQuerySystem() | |
{ | |
printf("\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 感 谢 使 用 综 合 查 询 子 系 统 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
} | |
/********************** 冰 鞋 租 还 处 理 函 数 实 现 ************************/ | |
// 将记录 rd 写入文件 rent.dat | |
// append = 1 则追加写入 否则在下标 pos 指示的相对位置写入 程序返回 | |
// 0 写入成功 | |
// -1 打开文件错误 | |
// -2 未知错误 | |
short RentDetailsWrite2File(RentDetails rd, int pos, short append) | |
{ | |
FILE *fp = fopen("rent.dat", "rb+"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 移动文件指针 | |
if(append == 0) | |
{ | |
rewind(fp); | |
fseek(fp, pos * sizeof(RentDetails), SEEK_SET); | |
} | |
else | |
{ | |
fseek(fp, 0, SEEK_END); | |
} | |
// 将记录写入文件 | |
if(fwrite(&rd, sizeof(RentDetails), 1, fp) == 1) | |
{ | |
printf("\n数据写入成功!\n"); | |
fclose(fp); | |
return 0; | |
} | |
else | |
{ | |
printf("\n\a数据写入失败!\n"); | |
fclose(fp); | |
return -2; | |
} | |
} | |
// 将记录 bd 写入文件 count.dat | |
// append = 1 则追加写入 否则在下标 pos 指示的相对位置写入 程序返回 | |
// 0 写入成功 | |
// -1 打开文件错误 | |
// -2 未知错误 | |
short BackDetailsWrite2File(BackDetails bd, int pos, short append) | |
{ | |
FILE *fp = fopen("count.dat", "rb+"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 移动文件指针 | |
if(append == 0) | |
{ | |
rewind(fp); | |
fseek(fp, pos * sizeof(BackDetails), SEEK_SET); | |
} | |
else | |
{ | |
fseek(fp, 0, SEEK_END); | |
} | |
// 将记录写入文件 | |
if(fwrite(&bd, sizeof(BackDetails), 1, fp) == 1) | |
{ | |
printf("\n数据写入成功!\n"); | |
fclose(fp); | |
return 0; | |
} | |
else | |
{ | |
printf("\n\a数据写入失败!\n"); | |
fclose(fp); | |
return -2; | |
} | |
} | |
// 根据用户姓名 user_name 身份证号 id_number 冰鞋编号 key_number | |
// 在文件 rent.dat 中查找相应记录 程序返回 | |
// >= 0 记录在文件中的下标 | |
// -3 查找不成功 | |
// -1 文件打开错误 | |
// -2 未知错误 | |
int FindRentRecord(String user_name, String id_number, String key_number, RentDetails *rd) | |
{ | |
int pos = 0; // 对应记录在文件中的下标 | |
FILE *fp = fopen("rent.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 初始化对象 | |
RentDetailsInit(rd); | |
// 遍历文件查询 | |
while(!feof(fp)) | |
{ | |
if(fread(rd, sizeof(RentDetails), 1, fp) == 1) | |
{ | |
if(rd->status == 1 && | |
!StringCompare(rd->user_name, user_name) && | |
!StringCompare(rd->id_number, id_number) && | |
!StringCompare(rd->shoe_key_number, key_number)) | |
{ | |
// 查找成功 | |
fclose(fp); | |
return pos; | |
} | |
++pos; | |
} | |
} | |
// 查找失败 | |
fclose(fp); | |
RentDetailsInit(rd); | |
return -3; | |
} | |
/******************** 查 询 统 计 子 系 统 函 数 实 现 ***********************/ | |
// 查询冰鞋信息 | |
void QueryShoes() | |
{ | |
// 存放用户输入 | |
String input_key_number; | |
String input_type; | |
String input_size; | |
String input_color; | |
String input_brand; | |
String input_manufacturer; | |
String input_rent_status; | |
String input_remark; | |
// 初始化各对象 | |
StringInit(&input_key_number); | |
StringInit(&input_type); | |
StringInit(&input_size); | |
StringInit(&input_color); | |
StringInit(&input_brand); | |
StringInit(&input_manufacturer); | |
StringInit(&input_rent_status); | |
StringInit(&input_remark); | |
// 输入查询条件 | |
printf("\n请输入查询条件,不需要限制的字段请输入 null\n\n"); | |
printf("冰鞋编码: "); | |
StringInput(&input_key_number); | |
printf("冰鞋类型,0 -> 速滑冰鞋 1 -> 花样冰鞋: "); | |
StringInput(&input_type); | |
if(strcmp(StringGetString(&input_type), "null") != 0 && | |
strcmp(StringGetString(&input_type), "0") != 0 && | |
strcmp(StringGetString(&input_type), "1") != 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
printf("鞋号: "); | |
StringInput(&input_size); | |
printf("冰鞋颜色: "); | |
StringInput(&input_color); | |
printf("冰鞋品牌: "); | |
StringInput(&input_brand); | |
printf("冰鞋厂家: "); | |
StringInput(&input_manufacturer); | |
printf("是否已租用,0 -> 未租用 1 -> 已租用: "); | |
StringInput(&input_rent_status); | |
if(strcmp(StringGetString(&input_rent_status), "null") != 0 && | |
strcmp(StringGetString(&input_rent_status), "0") != 0 && | |
strcmp(StringGetString(&input_rent_status), "1") != 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
printf("是否需要修理,0 -> 不需要 1-> 需要: "); | |
StringInput(&input_remark); | |
if(strcmp(StringGetString(&input_remark), "null") != 0 && | |
strcmp(StringGetString(&input_remark), "0") != 0 && | |
strcmp(StringGetString(&input_remark), "1") != 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
// 输入结束 | |
// 查询并打印结果 | |
DisplayQueryTitle(); | |
QueryShoesFromFile(input_key_number, input_type, input_size, | |
input_color, input_brand, input_manufacturer, | |
input_rent_status, input_remark); | |
} | |
// 根据查询条件从文件 shoe.dat 中查询符合条件的记录 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short QueryShoesFromFile(String key_number, String type, String size, | |
String color, String brand, String manufacturer, | |
String rent_status, String remark) | |
{ | |
SkateShoe ss; // 冰鞋信息对象 | |
short flag_print = 0; // 标记是否打印了记录 1 表示打印过 | |
FILE *fp = fopen("shoes.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 初始化对象 | |
SkateShoeInit(&ss); | |
// 遍历文件 | |
printf("| %-7s%-10s%-7s%-7s%-9s%-10s%-9s%-8s%-8s|\n", | |
"编码", "类型", "鞋号", "颜色", "品牌", "单价", "厂家", "被租用", "需维修"); | |
printf("-------------------------------------------------------------------------------\n"); | |
while(!feof(fp)) | |
{ | |
if(fread(&ss, sizeof(SkateShoe), 1, fp) == 1 && ss.status == 1) | |
{ | |
// 检查是否符合查询条件 | |
if( | |
(!strcmp(StringGetString(&key_number), "null") || !StringCompare(key_number, ss.key_number)) | |
&& (!strcmp(StringGetString(&type), "null") || atoi(StringGetString(&type)) == ss.type) | |
&& (!strcmp(StringGetString(&size), "null") || atof(StringGetString(&size)) == ss.size) | |
&& (!strcmp(StringGetString(&color), "null") || !StringCompare(color, ss.color)) | |
&& (!strcmp(StringGetString(&brand), "null") || !StringCompare(brand, ss.brand)) | |
&& (!strcmp(StringGetString(&manufacturer), "null") || !StringCompare(manufacturer, ss.manufacturer)) | |
&& (!strcmp(StringGetString(&rent_status), "null") || atoi(StringGetString(&rent_status)) == ss.rent_status) | |
&& (!strcmp(StringGetString(&remark), "null") || atoi(StringGetString(&remark)) == ss.remark) | |
) | |
{ | |
// 符合查询条件 | |
printf("| %-7s%-10s%-7.1lf", | |
StringGetString(&ss.key_number), | |
(ss.type == 0? "速滑冰鞋": "花样冰鞋"), | |
ss.size); | |
printf("%-7s", StringGetString(&ss.color)); | |
printf("%-9s", StringGetString(&ss.brand)); | |
printf("%-10.2lf", ss.unit_price); | |
printf("%-9s%-8s%-8s|\n", | |
StringGetString(&ss.manufacturer), | |
(ss.rent_status == 0? "否": "是"), | |
(ss.remark == 0? "否": "是")); | |
flag_print = 1; | |
} | |
} | |
} | |
if(flag_print == 0) | |
{ | |
printf("| 没 有 符 合 条 件 的 记 录 |\n"); | |
} | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("\n\n"); | |
fclose(fp); | |
return flag_print; | |
} | |
// 查询数量信息 | |
void QueryNumber() | |
{ | |
// 存放用户输入 | |
String input_shoe_size; | |
String input_shoe_type; | |
String input_total_quantity; | |
String input_left_quantity; | |
// 初始化各对象 | |
StringInit(&input_shoe_size); | |
StringInit(&input_shoe_type); | |
StringInit(&input_total_quantity); | |
StringInit(&input_left_quantity); | |
// 输入查询条件 | |
printf("\n请输入查询条件,不需要限制的字段请输入 null\n\n"); | |
printf("鞋号: "); | |
StringInput(&input_shoe_size); | |
if(StringLength(input_shoe_size) == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
printf("冰鞋类型,0 -> 速滑冰鞋 1 -> 花样冰鞋: "); | |
StringInput(&input_shoe_type); | |
if(strcmp(StringGetString(&input_shoe_type), "null") != 0 && | |
strcmp(StringGetString(&input_shoe_type), "0") != 0 && | |
strcmp(StringGetString(&input_shoe_type), "1") != 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
printf("冰鞋总数量: "); | |
StringInput(&input_total_quantity); | |
printf("剩余量: "); | |
StringInput(&input_left_quantity); | |
// 输入结束 | |
// 查询并打印结果 | |
DisplayQueryTitle(); | |
QueryNumberFromFile(input_shoe_size, input_shoe_type, input_total_quantity, input_left_quantity); | |
} | |
// 根据查询条件从文件 number.dat 中查询符合条件的记录 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short QueryNumberFromFile(String shoe_size, String shoe_type, String total_quantity, String left_quantity) | |
{ | |
ShoeNumber sn; // 冰鞋数量对象 | |
short flag_print = 0; // 标记是否打印过记录 1 表示打印过 | |
FILE *fp = fopen("number.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 初始化对象 | |
ShoeNumberInit(&sn); | |
// 遍历文件 | |
printf("| %-20s%-20s%-20s%-12s|\n", "鞋号", "类型", "总数量", "剩余量"); | |
printf("-------------------------------------------------------------------------------\n"); | |
while(!feof(fp)) | |
{ | |
if(fread(&sn, sizeof(ShoeNumber), 1, fp) == 1 && sn.status == 1) | |
{ | |
// 检查是否符合查询条件 | |
if( | |
(!strcmp(StringGetString(&shoe_size), "null") || atof(StringGetString(&shoe_size)) == sn.shoe_size) | |
&& (!strcmp(StringGetString(&shoe_type), "null") || atoi(StringGetString(&shoe_type)) == sn.shoe_type) | |
&& (!strcmp(StringGetString(&total_quantity), "null") || atoi(StringGetString(&total_quantity)) == sn.total_quantity) | |
&& (!strcmp(StringGetString(&left_quantity), "null") || atoi(StringGetString(&left_quantity)) == sn.left_quantity) | |
) | |
{ | |
// 符合查询条件 | |
printf("| %-20.1lf%-20s%-20d%-12d|\n", | |
sn.shoe_size, | |
(sn.shoe_type == 0? "速滑冰鞋": "花样冰鞋"), | |
sn.total_quantity, sn.left_quantity); | |
flag_print = 1; | |
} | |
} | |
} | |
if(flag_print == 0) | |
{ | |
printf("| 没 有 符 合 条 件 的 记 录 |\n"); | |
} | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("\n\n"); | |
fclose(fp); | |
return flag_print; | |
} | |
// 查询租用信息 | |
void QueryRentDetails() | |
{ | |
// 存放用户输入 | |
String input_user_name; | |
String input_id_number; | |
String input_shoe_size; | |
String input_date; | |
// 初始化各对象 | |
StringInit(&input_user_name); | |
StringInit(&input_id_number); | |
StringInit(&input_shoe_size); | |
StringInit(&input_date); | |
// 输入查询条件 | |
printf("\n请输入查询条件,不需要限制的字段请输入 null\n\n"); | |
printf("用户姓名: "); | |
StringInput(&input_user_name); | |
if(StringLength(input_user_name) == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
printf("身份证号: "); | |
StringInput(&input_id_number); | |
if(StringLength(input_id_number) == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return; | |
} | |
printf("鞋号: "); | |
StringInput(&input_shoe_size); | |
printf("租用日期: "); | |
StringInput(&input_date); | |
// 输入结束 | |
// 查询并打印结果 | |
DisplayQueryTitle(); | |
QueryRentDetailsFromFile(input_user_name, input_id_number, input_shoe_size, input_date); | |
} | |
// 根据查询条件从文件 rent.dat 中查询符合条件的记录 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short QueryRentDetailsFromFile(String user_name, String id_number, String size, String date) | |
{ | |
RentDetails rd; // 租用记录对象 | |
short flag_print = 0; // 标记是否打印过记录 1 为打印过 | |
FILE *fp = fopen("rent.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 初始化对象 | |
RentDetailsInit(&rd); | |
// 遍历文件 | |
printf("| %-7s%-10s%-10s%-7s%-7s%-10s%-9s%-7s%-8s|\n", | |
"姓名", "身份证号", "联系方式", "鞋号", "编码", "类型", "日期", "时间", "租金/时"); | |
printf("-------------------------------------------------------------------------------\n"); | |
while(!feof(fp)) | |
{ | |
if(fread(&rd, sizeof(RentDetails), 1, fp) == 1 && rd.status == 1) | |
{ | |
// 检查是否符合查询条件 | |
if( | |
(!strcmp(StringGetString(&user_name), "null") || !StringCompare(user_name, rd.user_name)) | |
&& (!strcmp(StringGetString(&id_number), "null") || !StringCompare(id_number, rd.id_number)) | |
&& (!strcmp(StringGetString(&size), "null") || atof(StringGetString(&size)) == rd.shoe_size) | |
&& (!strcmp(StringGetString(&date), "null") || !strcmp(StringGetString(&date), DateGetString(rd.date))) | |
) | |
{ | |
// 符合查询条件 | |
printf("| %-7s", StringGetString(&rd.user_name)); | |
printf("%-10s", StringGetString(&rd.id_number)); | |
printf("%-10s", StringGetString(&rd.contact_info)); | |
printf("%-7.1lf", rd.shoe_size); | |
printf("%-7s%-10s", StringGetString(&rd.shoe_key_number), | |
(rd.shoe_type == 0? "速滑冰鞋": "花样冰鞋")); | |
printf("%-9s", DateGetString(rd.date)); | |
printf("%-7s", TimeGetString(rd.rent_time)); | |
printf("%-8.2lf|\n", rd.rent_price_per_hour); | |
flag_print = 1; | |
} | |
} | |
} | |
if(flag_print == 0) | |
{ | |
printf("| 没 有 符 合 条 件 的 记 录 |\n"); | |
} | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("\n\n"); | |
fclose(fp); | |
return flag_print; | |
} | |
// 计算当日收入 | |
void CalculateIncome() | |
{ | |
String input_date; // 用户输入的日期 | |
BackDetails bd; // 归还记录对象 | |
short flag_print = 0; // 标记是否打印过记录 1 为打印过 | |
double shoe_size[100]; // 存放统计的鞋号 | |
double income[100]; // 存放对应鞋号的收入 | |
int record_cnt = 0; // 统计后记录的条数 | |
int i; // 循环变量 | |
FILE *fp = fopen("count.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return; | |
} | |
// 初始化对象 | |
StringInit(&input_date); | |
// 输入要统计的日期 | |
printf("\n请输入日期,格式 年/月/日: "); | |
StringInput(&input_date); | |
if(StringLength(input_date) == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
fclose(fp); | |
return; | |
} | |
// 遍历文件 | |
while(!feof(fp)) | |
{ | |
// 检测记录的日期是否跟输入的日期一致 | |
if(fread(&bd, sizeof(BackDetails), 1, fp) == 1 && | |
!strcmp(StringGetString(&input_date), DateGetString(bd.back_date))) | |
{ | |
// 查找 bd 记录中的鞋号是否已经出现 | |
for(i = 0; i < record_cnt; ++i) | |
{ | |
if(bd.shoe_size == shoe_size[i]) | |
{ | |
break; | |
} | |
} | |
if(i < record_cnt) | |
{ | |
// 已存在的鞋号 | |
income[i] += bd.total_cost; | |
} | |
else | |
{ | |
// 未出现的鞋号 | |
shoe_size[record_cnt] = bd.shoe_size; | |
income[record_cnt] = bd.total_cost; | |
++record_cnt; | |
} | |
} | |
} | |
fclose(fp); | |
// 展示结果 | |
DisplayStatisticsTitle(); | |
printf("| %-20s%-22s |\n", "鞋号", "对应总收入"); | |
printf("|-----------------------------------------------------------------------------|\n"); | |
for(i = 0; i < record_cnt; ++i) | |
{ | |
printf("| %-20.1lf%-22.2lf |\n", shoe_size[i], income[i]); | |
flag_print = 1; | |
} | |
if(flag_print == 0) | |
{ | |
printf("| 没 有 符 合 条 件 的 记 录 |\n"); | |
} | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("\n\n"); | |
} | |
// 退出查询统计子系统 | |
void QuitQuerySystem() | |
{ | |
printf("\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 感 谢 使 用 查 询 统 计 子 系 统 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
} | |
// 显示查询结果列表表头 | |
void DisplayQueryTitle() | |
{ | |
printf("\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 查 询 结 果 列 表 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
} | |
// 同时统计结果列表表头 | |
void DisplayStatisticsTitle() | |
{ | |
printf("\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 统 计 结 果 列 表 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
} | |
/**************************** 打 印 函 数 实 现 ******************************/ | |
// 打印 shoes.dat 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short DisplayShoes() | |
{ | |
short flag_print = 0; // 打印标记 为 1 表示打印过 | |
SkateShoe ss; // 冰鞋信息对象 | |
FILE *fp = fopen("shoes.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\a打开文件错误!\n"); | |
return -1; | |
} | |
// 初始化对象 | |
SkateShoeInit(&ss); | |
// 遍历文件 打印记录 | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| s h o e s . d a t |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| %-7s%-10s%-7s%-7s%-9s%-10s%-9s%-8s%-8s|\n", | |
"编码", "类型", "鞋号", "颜色", "品牌", "单价", "厂家", "被租用", "需维修"); | |
printf("-------------------------------------------------------------------------------\n"); | |
while(!feof(fp)) | |
{ | |
if(fread(&ss, sizeof(SkateShoe), 1, fp) == 1 && ss.status == 1) | |
{ | |
printf("| %-7s%-10s%-7.1lf", | |
StringGetString(&ss.key_number), | |
(ss.type == 0? "速滑冰鞋": "花样冰鞋"), | |
ss.size); | |
printf("%-7s", StringGetString(&ss.color)); | |
printf("%-9s", StringGetString(&ss.brand)); | |
printf("%-10.2lf", ss.unit_price); | |
printf("%-9s%-8s%-8s|\n", | |
StringGetString(&ss.manufacturer), | |
(ss.rent_status == 0? "否": "是"), | |
(ss.remark == 0? "否": "是")); | |
flag_print = 1; | |
} | |
} | |
if(flag_print == 0) | |
{ | |
printf("| 没 有 数 据 |\n"); | |
} | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("\n\n"); | |
fclose(fp); | |
return flag_print; | |
} | |
// 打印 number.dat 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short DisplayNumber() | |
{ | |
short flag_print = 0; // 打印标记 为 1 表明打印过 | |
ShoeNumber sn; // 冰鞋数量信息对象 | |
FILE *fp = fopen("number.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\a打开文件错误!\n"); | |
return -1; | |
} | |
// 初始化对象 | |
ShoeNumberInit(&sn); | |
// 遍历文件 打印记录 | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| n u m b e r . d a t |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| %-20s%-20s%-20s%-12s|\n", "鞋号", "类型", "总数量", "剩余量"); | |
printf("-------------------------------------------------------------------------------\n"); | |
while(!feof(fp)) | |
{ | |
if(fread(&sn, sizeof(ShoeNumber), 1, fp) == 1 && sn.status == 1) | |
{ | |
printf("| %-20.1lf%-20s%-20d%-12d|\n", | |
sn.shoe_size, | |
(sn.shoe_type == 0? "速滑冰鞋": "花样冰鞋"), | |
sn.total_quantity, sn.left_quantity); | |
flag_print = 1; | |
} | |
} | |
if(flag_print == 0) | |
{ | |
printf("| 没 有 数 据 |\n"); | |
} | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("\n\n"); | |
fclose(fp); | |
return flag_print; | |
} | |
// 打印 rent.dat 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short DisplayRent() | |
{ | |
short flag_print = 0; // 打印标记 为 1 表示打印过 | |
RentDetails rd; // 租用信息对象 | |
FILE *fp = fopen("rent.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\a打开文件错误!\n"); | |
return -1; | |
} | |
// 初始化对象 | |
RentDetailsInit(&rd); | |
// 遍历文件 打印记录 | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| r e n t . d a t |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| %-7s%-10s%-10s%-7s%-7s%-10s%-9s%-7s%-8s|\n", | |
"姓名", "身份证号", "联系方式", "鞋号", "编码", "类型", "日期", "时间", "租金/时"); | |
printf("-------------------------------------------------------------------------------\n"); | |
while(!feof(fp)) | |
{ | |
if(fread(&rd, sizeof(RentDetails), 1, fp) == 1 && rd.status == 1) | |
{ | |
printf("| %-7s", StringGetString(&rd.user_name)); | |
printf("%-10s", StringGetString(&rd.id_number)); | |
printf("%-10s", StringGetString(&rd.contact_info)); | |
printf("%-7.1lf", rd.shoe_size); | |
printf("%-7s%-10s", StringGetString(&rd.shoe_key_number), | |
(rd.shoe_type == 0? "速滑冰鞋": "花样冰鞋")); | |
printf("%-9s", DateGetString(rd.date)); | |
printf("%-7s", TimeGetString(rd.rent_time)); | |
printf("%-8.2lf|\n", rd.rent_price_per_hour); | |
flag_print = 1; | |
} | |
} | |
if(flag_print == 0) | |
{ | |
printf("| 没 有 数 据 |\n"); | |
} | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("\n\n"); | |
fclose(fp); | |
return flag_print; | |
} | |
// 打印 count.dat 程序返回 | |
// 0 没有符合条件的记录 | |
// 1 有符合条件的记录 | |
// -1 文件打开错误 | |
short DisplayCount() | |
{ | |
short flag_print = 0; // 打印标记 为 1 表示打印过 | |
BackDetails bd; // 归还信息对象 | |
FILE *fp = fopen("count.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\a打开文件错误!\n"); | |
return -1; | |
} | |
// 遍历文件 打印记录 | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| c o u n t . d a t |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| %-12s%-9s%-13s%-16s%-12s%-12s |\n", | |
"日期", "鞋号", "类型", "使用时间/时", "租金/时", "总费用/元"); | |
printf("-------------------------------------------------------------------------------\n"); | |
while(!feof(fp)) | |
{ | |
if(fread(&bd, sizeof(BackDetails), 1, fp) == 1) | |
{ | |
printf("| %-12s%-9.1lf%-13s%-16.1lf%-12.2lf%-12.2lf |\n", | |
DateGetString(bd.back_date), | |
bd.shoe_size, | |
(bd.shoe_type == 0? "速滑冰鞋": "花样冰鞋"), | |
bd.lend_hours, | |
bd.rent_price_per_hour, | |
bd.total_cost); | |
flag_print = 1; | |
} | |
} | |
if(flag_print == 0) | |
{ | |
printf("| 没 有 数 据 |\n"); | |
} | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("\n"); | |
fclose(fp); | |
return flag_print; | |
} | |
// 打印计费单据 | |
void DisplayCostDetails(BackDetails bd) | |
{ | |
printf("\n-------------------------------------------------------------------------------\n"); | |
printf("| 计 费 单 据 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| %-12s%-9s%-13s%-16s%-12s%-12s |\n", | |
"日期", "鞋号", "类型", "使用时间/时", "租金/时", "总费用/元"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| %-12s%-9.1lf%-13s%-16.1lf%-12.2lf%-12.2lf |\n", | |
DateGetString(bd.back_date), | |
bd.shoe_size, | |
(bd.shoe_type == 0? "速滑冰鞋": "花样冰鞋"), | |
bd.lend_hours, | |
bd.rent_price_per_hour, | |
bd.total_cost); | |
printf("-------------------------------------------------------------------------------\n\n"); | |
} | |
/********************** 冰 鞋 数 据 处 理 函 数 实 现 ************************/ | |
// 冰鞋详细信息对象初始化 | |
void SkateShoeInit(SkateShoe *ss) | |
{ | |
ss->status = 1; | |
} | |
// 冰鞋数量信息对象初始化 | |
void ShoeNumberInit(ShoeNumber *sn) | |
{ | |
sn->status = 1; | |
} | |
// 租用详细信息对象初始化 | |
void RentDetailsInit(RentDetails *rd) | |
{ | |
rd->deposit = 100; // 押金 | |
rd->rent_price_per_hour = 30; // 每小时租费 | |
rd->status = 1; | |
} | |
// 设置 SkateShoe 对象 *ss 的值 | |
// UpdateShoes() 为 1 表示是在更新记录 此时不用输入编号 | |
// 成功返回 0 | |
// 失败返回 -1 | |
short GetShoeData(SkateShoe *ss, short update) | |
{ | |
String input_value; // 用户输入 | |
// 初始化各对象 | |
SkateShoeInit(ss); | |
StringInit(&input_value); | |
// 检测是否是 UpdateShoes() 调用 | |
if(update == 0) | |
{ | |
// 是 update 调用 | |
// 不能更新冰鞋编号 | |
printf("请输入冰鞋的编号: "); | |
StringInput(&input_value); | |
if(input_value.length == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
StringCopy(&(ss->key_number), input_value); | |
} | |
else | |
{ | |
printf("\n"); | |
} | |
// 输入冰鞋类型 | |
printf("请选择冰鞋的类型,0 -> 速滑冰鞋 1 -> 花样冰鞋: "); | |
StringInput(&input_value); | |
if(input_value.length != 1 || | |
(strcmp(StringGetString(&input_value), "0") != 0 && | |
strcmp(StringGetString(&input_value), "1") != 0)) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
ss->type = atoi(StringGetString(&input_value)); | |
// 鞋号 | |
printf("请输入鞋号: "); | |
StringInput(&input_value); | |
if(input_value.length == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
ss->size = atof(StringGetString(&input_value)); | |
// 颜色 | |
printf("请输入鞋的颜色: "); | |
StringInput(&input_value); | |
if(input_value.length == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
StringCopy(&(ss->color), input_value); | |
// 品牌 | |
printf("请输入鞋的品牌: "); | |
StringInput(&input_value); | |
if(input_value.length == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
StringCopy(&(ss->brand), input_value); | |
// 单价 | |
printf("请输入单价: "); | |
StringInput(&input_value); | |
if(input_value.length == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
ss->unit_price = atof(StringGetString(&input_value)); | |
// 厂家 | |
printf("请输入厂家: "); | |
StringInput(&input_value); | |
if(input_value.length == 0) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
StringCopy(&(ss->manufacturer), input_value); | |
// 租用状态 | |
printf("请选择冰鞋租用状态,0 -> 未租用 1 -> 已租用: "); | |
StringInput(&input_value); | |
if(input_value.length != 1 || | |
(strcmp(StringGetString(&input_value), "0") != 0 && | |
strcmp(StringGetString(&input_value), "1") != 0)) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
ss->rent_status = atoi(StringGetString(&input_value)); | |
// 是否需要维修 使用说明 | |
printf("请选择冰鞋是否需要维修,0 -> 不需要 1 -> 需要: "); | |
StringInput(&input_value); | |
if(input_value.length != 1 || | |
(strcmp(StringGetString(&input_value), "0") != 0 && | |
strcmp(StringGetString(&input_value), "1") != 0)) | |
{ | |
printf("\n\a输入有误!\n"); | |
return -1; | |
} | |
ss->remark = atoi(StringGetString(&input_value)); | |
return 0; | |
} | |
// 将记录 ss 写入文件 shoes.dat | |
// append = 1 则追加写入 否则在下标 pos 指示的相对位置写入 返回 | |
// 0 写入成功 | |
// -1 打开文件错误 | |
// -2 未知错误 | |
short ShoesWrite2File(SkateShoe ss, long pos, short append) | |
{ | |
FILE *fp = fopen("shoes.dat", "rb+"); | |
if(fp == NULL) | |
{ | |
printf("\n\a打开文件错误!\n"); | |
return -1; | |
} | |
// 移动文件指针 | |
if(append == 0) | |
{ | |
rewind(fp); // 需要先让文件指针回到文件头 - -# | |
fseek(fp, pos * sizeof(SkateShoe), SEEK_SET); | |
} | |
else | |
{ | |
fseek(fp, 0, SEEK_END); | |
} | |
// 将记录写入文件 | |
if(fwrite(&ss, sizeof(SkateShoe), 1, fp) == 1) | |
{ | |
printf("\n数据写入成功!\n"); | |
fclose(fp); | |
return 0; | |
} | |
else | |
{ | |
printf("\n数据写入失败!\n"); | |
fclose(fp); | |
return -2; | |
} | |
} | |
// 通过编号 key 查找冰鞋信息 | |
// >=0 查找成功 返回的是记录在文件中的下标 | |
// -3 查找失败 | |
// -1 文件打开错误 | |
int FindShoesByKey(String key, SkateShoe *ss) | |
{ | |
int pos = 0; // 相应冰鞋信息记录在文件中的下标 | |
FILE *fp = fopen("shoes.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 遍历文件 | |
while(!feof(fp)) | |
{ | |
if(fread(ss, sizeof(SkateShoe), 1, fp) == 1) | |
{ | |
// 检查是否符合查找条件 | |
if(ss->status == 1 && | |
StringCompare(ss->key_number, key) == 0) | |
{ | |
// 查找成功 | |
fclose(fp); | |
return pos; | |
} | |
++pos; | |
} | |
} | |
// 查找失败 | |
fclose(fp); | |
SkateShoeInit(ss); | |
return -3; | |
} | |
// 新增冰鞋数据时显示生成的标签 | |
void DisplayLabel(SkateShoe ss) | |
{ | |
printf("\n-------------------------------------------------------------------------------\n"); | |
printf("| 冰 鞋 标 签 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| %-20s%-24s%-16s |\n", "编码", "类型", "鞋号"); | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| %-20s%-24s%-16.1lf |\n", | |
StringGetString(&ss.key_number), (ss.type == 0? "速滑冰鞋": "花样冰鞋"), ss.size); | |
printf("-------------------------------------------------------------------------------\n\n"); | |
} | |
/*********************** 冰 鞋 数 量 维 护 函 数 实 现 ***********************/ | |
// 在新增冰鞋数据时更新数量文件 number.dat | |
// flag_back = 1 时表明是 UpdateNumberWhenBackShoes() 调用 | |
void UpdateNumberWhenAddShoes(SkateShoe ss, short flag_back) | |
{ | |
ShoeNumber sn; // 冰鞋数量对象 | |
int pos; // 相应的冰鞋数量记录在文件中的下标 | |
// 初始化对象 | |
ShoeNumberInit(&sn); | |
// 取到数量记录 | |
if((pos = FindNumberRecord(ss.size, ss.type, &sn)) >= 0) | |
{ | |
// 更新已存在的 ShoeNumber 记录 | |
// 处理记录的 total_quantity 和 left_quantity | |
if(flag_back == 0) | |
{ | |
++sn.total_quantity; | |
sn.left_quantity += (ss.rent_status == 0? 1: 0); | |
} | |
else | |
{ | |
++sn.left_quantity; | |
} | |
// 写入文件 | |
if(NumberWrite2File(sn, pos, 0) == 0) | |
{ | |
printf("\n冰鞋数量更新成功!\n"); | |
return; | |
} | |
else | |
{ | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
else if(pos == -3) | |
{ | |
// 新增一条 ShoeNumber 记录 | |
sn.shoe_size = ss.size; | |
sn.shoe_type = ss.type; | |
sn.left_quantity = (ss.rent_status == 0? 1: 0); | |
sn.total_quantity = 1; | |
// 写入文件 | |
if(NumberWrite2File(sn, 0, 1) == 0) | |
{ | |
printf("\n冰鞋数量更新成功!\n"); | |
return; | |
} | |
else | |
{ | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
// 在删除冰鞋数据时更新数量文件 number.dat | |
// flag_rent = 1 时表明是 UpdateNumberWhenRentShoes() 调用 | |
void UpdateNumberWhenDeleteShoes(SkateShoe ss, short flag_rent) | |
{ | |
ShoeNumber sn; // 冰鞋数量对象 | |
int pos; // 数量记录在文件中的下标 | |
// 初始化对象 | |
ShoeNumberInit(&sn); | |
// 取到数量记录 | |
if((pos = FindNumberRecord(ss.size, ss.type, &sn)) >= 0) | |
{ | |
// 更新 ShoeNumber 记录 | |
// 处理记录的 total_quantity 和 left_quantity | |
if(flag_rent == 0) | |
{ | |
--sn.total_quantity; | |
--sn.left_quantity; | |
} | |
else | |
{ | |
--sn.left_quantity; | |
} | |
// 写入文件 | |
if(NumberWrite2File(sn, pos, 0) == 0) | |
{ | |
printf("\n冰鞋数量更新成功!\n"); | |
return; | |
} | |
else | |
{ | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\a未知错误!\n"); | |
return; | |
} | |
} | |
// 在更新冰鞋数据时更新数量文件 number.dat | |
void UpdateNumberWhenUpdateShoes(SkateShoe old_ss, SkateShoe new_ss) | |
{ | |
if(old_ss.size == new_ss.size && | |
old_ss.type == new_ss.type && | |
old_ss.rent_status == new_ss.rent_status) | |
{ | |
// 不需要更新 number.dat | |
return; | |
} | |
else | |
{ | |
// 需要更新 | |
UpdateNumberWhenDeleteShoes(old_ss, 0); | |
UpdateNumberWhenAddShoes(new_ss, 0); | |
} | |
} | |
// 在租用冰鞋时更新数量文件 number.dat | |
void UpdateNumberWhenRentShoes(SkateShoe ss) | |
{ | |
UpdateNumberWhenDeleteShoes(ss, 1); | |
} | |
// 在退租冰鞋时更新数量文件 number.dat | |
void UpdateNumberWhenBackShoes(SkateShoe ss) | |
{ | |
UpdateNumberWhenAddShoes(ss, 1); | |
} | |
// 向文件 number.dat 中写入一条记录 | |
// append = 1 则追加写入 | |
// 否则在下标 pos 指示的相对位置写入 | |
// 0 写入成功 | |
// -1 文件打开错误 | |
// -2 未知错误 | |
short NumberWrite2File(ShoeNumber sn, int pos, short append) | |
{ | |
FILE *fp = fopen("number.dat", "r+"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 移动文件指针 | |
if(append == 0) | |
{ | |
rewind(fp); | |
fseek(fp, pos * sizeof(ShoeNumber), SEEK_SET); | |
} | |
else | |
{ | |
fseek(fp, 0, SEEK_END); | |
} | |
// 写入文件 | |
if(fwrite(&sn, sizeof(ShoeNumber), 1, fp) == 1) | |
{ | |
printf("\n数据写入成功!\n"); | |
fclose(fp); | |
return 0; | |
} | |
else | |
{ | |
printf("\n数据写入失败!\n"); | |
fclose(fp); | |
return -2; | |
} | |
} | |
// 根据鞋号和冰鞋类型在 number.dat 文件中找到记录的下标并返回 | |
// >0 查找成功 | |
// -3 查找失败 | |
// -1 文件打开错误 | |
int FindNumberRecord(double shoe_size, ShoeType st, ShoeNumber *sn) | |
{ | |
int pos = 0; // 数量记录在文件中的下标 | |
FILE *fp = fopen("number.dat", "rb"); | |
if(fp == NULL) | |
{ | |
printf("\n\a文件打开错误!\n"); | |
return -1; | |
} | |
// 初始化对象 | |
ShoeNumberInit(sn); | |
// 遍历文件 | |
while(!feof(fp)) | |
{ | |
if(fread(sn, sizeof(ShoeNumber), 1, fp) == 1) | |
{ | |
// 检查是否符合查找条件 | |
if(sn->status == 1 && | |
sn->shoe_size == shoe_size && sn->shoe_type == st) | |
{ | |
// 查找成功 | |
fclose(fp); | |
return pos; | |
} | |
++pos; | |
} | |
} | |
// 查找失败 | |
fclose(fp); | |
ShoeNumberInit(sn); | |
return -3; | |
} | |
/************************** 密 码 处 理 函 数 实 现 **************************/ | |
// 初始化密码为 gitzhou | |
void InitPassword() | |
{ | |
String pwd; // 存放初始密码的 String 对象 | |
// 初始化并赋值 | |
StringInit(&pwd); | |
StringCopyFromCharArray(&pwd, "gitzhou"); | |
// 更新密码 | |
if(UpdatePassword(pwd) == 0) | |
{ | |
// 更新成功 | |
printf("\n\n密码初始化成功!"); | |
} | |
else | |
{ | |
// 更新失败 | |
printf("\n\n\a未知错误!"); | |
} | |
} | |
// 更新密码为 str 返回 | |
// 0 更新成功 | |
// -1 文件打开错误 | |
// -2 未知错误 | |
short UpdatePassword(String str) | |
{ | |
FILE *fp = fopen("password.dat", "wb"); | |
if(fp == NULL) | |
{ | |
printf("\n\n\a打开文件错误!"); | |
return -1; | |
} | |
// 将新密码写入文件 | |
if(fwrite(&str, sizeof(String), 1, fp) == 1) | |
{ | |
// 更新成功 | |
printf("\n\n密码更新成功!"); | |
fclose(fp); | |
return 0; | |
} | |
else | |
{ | |
// 未知错误 | |
printf("\n\n\a未知错误!"); | |
fclose(fp); | |
return -2; | |
} | |
} | |
// 处理密码输入的同时在控制台上显示星号 | |
void InputPassword(String *str) | |
{ | |
char string[STRING_MAX_SIZE]; // 存放用户输入的字符 | |
int string_len = 0; // 用户输入的字符个数 | |
char ch; // 临时变量 | |
// 读取输入 拼装字符串 | |
while((ch = getchar()) != '\n') | |
{ | |
//putchar('*'); | |
string[string_len++] = ch; | |
} | |
string[string_len] = 0; | |
// 赋值 | |
StringCopyFromCharArray(str, string); | |
} | |
// 检测用户输入的密码是否正确 返回 | |
// 2 密码初始化成功 | |
// 1 密码正确 | |
// 0 密码错误 | |
// -1 文件打开错误 | |
// -2 未知错误 | |
short CheckPassword() | |
{ | |
String pwd; // 存放系统密码 | |
String input_pwd; // 存放用户输入的密码 | |
FILE *fp; | |
// 初始化各对象 | |
StringInit(&pwd); | |
StringInit(&input_pwd); | |
if((fp = fopen("password.dat", "rb"))== NULL) | |
{ | |
printf("\n\a打开文件错误!\n"); | |
return -1; | |
} | |
// 让用户输入密码 | |
printf("\n请输入密码,以 Enter 结束输入: "); | |
InputPassword(&input_pwd); | |
// 检测是否是初始化密码的输入 | |
if(strcmp(StringGetString(&input_pwd), "!@#$%^&*()") == 0) | |
{ | |
// 初始化密码 | |
InitPassword(); | |
fclose(fp); | |
return 2; | |
} | |
if(fread(&pwd, sizeof(String), 1, fp) == 1) | |
{ | |
// 验证密码 | |
if(StringCompare(input_pwd, pwd) == 0) | |
{ | |
// 验证通过 | |
fclose(fp); | |
return 1; | |
} | |
else | |
{ | |
// 验证失败 | |
fclose(fp); | |
return 0; | |
} | |
} | |
else | |
{ | |
// 未知错误 | |
fclose(fp); | |
return -2; | |
} | |
} | |
/**************************** 菜 单 函 数 实 现 ******************************/ | |
// 显示程序主菜单 | |
void ShowMainMenu() | |
{ | |
String input_option; // 用户输入 | |
int option; // 由用户输入转换成的选项值 | |
StringInit(&input_option); | |
while(1) | |
{ | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 欢 迎 使 用 冰 鞋 租 用 管 理 系 统 |\n"); | |
printf("|-----------------------------------------------------------------------------|\n"); | |
printf("| - 1 - 冰 鞋 租 用 |\n"); | |
printf("| - 2 - 冰 鞋 归 还 |\n"); | |
printf("| - 3 - 数 据 维 护 |\n"); | |
printf("| - 4 - 密 码 修 改 |\n"); | |
printf("| - 5 - 综 合 查 询 |\n"); | |
printf("| - 6 - 退 出 系 统 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
fflush(stdin); | |
printf("请选择相应选项: "); | |
StringInput(&input_option); | |
// 转换 | |
option = atoi(StringGetString(&input_option)); | |
// 用户输入选项的错误检测 | |
if(option != 1 && option != 2 && option != 3 && | |
option != 4 && option != 5 && option != 6) | |
{ | |
// 输入错误 | |
printf("\n\a无此选项,请重新输入!\n\n"); | |
continue; | |
} | |
// 输入无误 | |
switch(option) | |
{ | |
// 冰鞋租用 | |
case 1: | |
RentShoes(); | |
break; | |
// 冰鞋归还 | |
case 2: | |
BackShoes(); | |
break; | |
// 数据维护 | |
case 3: | |
printf("\n"); | |
DataModify(); | |
break; | |
// 密码修改 | |
case 4: | |
PasswordModify(); | |
break; | |
// 综合查询 | |
case 5: | |
printf("\n"); | |
GeneralQuery(); | |
break; | |
// 退出系统 | |
case 6: | |
QuitMainSystem(); | |
return; | |
// 未知错误 | |
default: | |
printf("\n\a未知错误,程序结束!\n\n"); | |
return; | |
} | |
printf("\n"); | |
} | |
} | |
// 显示数据维护菜单 | |
void ShowDataModifyMenu() | |
{ | |
String input_option; // 用户输入 | |
int option; // 由用户输入转换成的选项值 | |
StringInit(&input_option); | |
while(1) | |
{ | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 欢 迎 进 入 数 据 维 护 子 系 统 |\n"); | |
printf("|-----------------------------------------------------------------------------|\n"); | |
printf("| - 1 - 新 增 冰 鞋 数 据 |\n"); | |
printf("| - 2 - 更 新 冰 鞋 数 据 |\n"); | |
printf("| - 3 - 删 除 冰 鞋 数 据 |\n"); | |
printf("| - 4 - 退 出 维 护 菜 单 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
fflush(stdin); | |
printf("请选择相应选项: "); | |
StringInput(&input_option); | |
// 转换 | |
option = atoi(StringGetString(&input_option)); | |
// 用户输入选项的错误检测 | |
if(option != 1 && option != 2 && option != 3 && option != 4) | |
{ | |
// 输入错误 | |
printf("\n\a无此选项,请重新输入!\n\n"); | |
continue; | |
} | |
// 输入无误 | |
switch(option) | |
{ | |
// 新增数据 | |
case 1: | |
AddShoes(); | |
break; | |
// 修改数据 | |
case 2: | |
UpdateShoes(); | |
break; | |
// 删除数据 | |
case 3: | |
DeleteShoes(); | |
break; | |
// 退出系统 | |
case 4: | |
QuitDataModifySystem(); | |
return; | |
// 未知错误 | |
default: | |
printf("\n\a未知错误!\n\n"); | |
return; | |
} | |
printf("\n"); | |
} | |
} | |
// 显示综合查询菜单 | |
void ShowGeneralQueryMenu() | |
{ | |
String input_option; // 用户输入 | |
int option; // 由用户输入转换成的选项值 | |
StringInit(&input_option); | |
while(1) | |
{ | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 欢 迎 进 入 综 合 查 询 子 系 统 |\n"); | |
printf("|-----------------------------------------------------------------------------|\n"); | |
printf("| - 1 - 输 出 全 部 信 息 |\n"); | |
printf("| - 2 - 高 级 查 询 统 计 |\n"); | |
printf("| - 3 - 退 出 查 询 菜 单 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
fflush(stdin); | |
printf("请选择相应选项: "); | |
StringInput(&input_option); | |
// 转换 | |
option = atoi(StringGetString(&input_option)); | |
// 用户输入选项的错误检测 | |
if(option != 1 && option != 2 && option != 3) | |
{ | |
// 输入错误 | |
printf("\n\a无此选项,请重新输入!\n\n"); | |
continue; | |
} | |
// 输入无误 | |
switch(option) | |
{ | |
// 输出全部信息 | |
case 1: | |
DisplayAllFiles(); | |
break; | |
// 查询统计 | |
case 2: | |
Query(); | |
break; | |
// 退出系统 | |
case 3: | |
QuitGeneralQuerySystem(); | |
return; | |
// 未知错误 | |
default: | |
printf("\n\a未知错误!\n\n"); | |
return; | |
} | |
printf("\n"); | |
} | |
} | |
// 显示查询统计菜单 | |
void ShowQueryMenu() | |
{ | |
String input_option; // 用户输入 | |
int option; // 由用户输入转换成的选项值 | |
StringInit(&input_option); | |
while(1) | |
{ | |
printf("-------------------------------------------------------------------------------\n"); | |
printf("| 欢 迎 进 入 查 询 统 计 子 系 统 |\n"); | |
printf("|-----------------------------------------------------------------------------|\n"); | |
printf("| - 1 - 查 询 冰 鞋 信 息 |\n"); | |
printf("| - 2 - 查 询 数 量 信 息 |\n"); | |
printf("| - 3 - 查 询 租 用 信 息 |\n"); | |
printf("| - 4 - 统 计 当 日 收 入 |\n"); | |
printf("| - 5 - 退 出 查 询 菜 单 |\n"); | |
printf("-------------------------------------------------------------------------------\n"); | |
fflush(stdin); | |
printf("请选择相应选项: "); | |
StringInput(&input_option); | |
// 转换 | |
option = atoi(StringGetString(&input_option)); | |
// 用户输入选项的错误检测 | |
if(option != 1 && option != 2 && option != 3 && | |
option != 4 && option != 5) | |
{ | |
// 输入错误 | |
printf("\n\a无此选项,请重新输入!\n\n"); | |
continue; | |
} | |
// 输入无误 | |
switch(option) | |
{ | |
// 查询冰鞋信息 | |
case 1: | |
QueryShoes(); | |
break; | |
// 查询数量信息 | |
case 2: | |
QueryNumber(); | |
break; | |
// 查询租用情况 | |
case 3: | |
QueryRentDetails(); | |
break; | |
// 计算当日收入 | |
case 4: | |
CalculateIncome(); | |
break; | |
// 退出系统 | |
case 5: | |
QuitQuerySystem(); | |
return; | |
// 未知错误 | |
default: | |
printf("\n\a未知错误!\n\n"); | |
return; | |
} | |
printf("\n"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment