文件内容载入链表的函数是这样的,在文件为空的情况下总是写入乱码
void load()
{
FILE* fp;
fp = fopen("stockdata.txt", "r");
if (fp == NULL)//如果文件不存在则创建
{
fp = fopen("stockdata.txt", "w");
fclose(fp);
return;
}
FRUIT* fruit;//链表临时指针
while (!feof(fp))//文件指针未达到文件尾则持续读入
{
fruit = (FRUIT*)malloc(sizeof(FRUIT));
fscanf(fp, "%s%s%d%d%lf%lf%lf", fruit->name, fruit->kind, &fruit->packing,&fruit->level,&fruit->cost,&fruit->price,&fruit->stock);
add(fruit);
}
fclose(fp);
return;
}
整个是这样的:
#include<stdio.h>
#include<stdlib.h>
#include"输入限制函数.h"
#include<string.h>
#define NAMELENGTH 21
#define DATELENGTH 9
#pragma warning(disable:4996)
typedef enum level { FIRST, SECOND, THIRD }LEVEL;//定义品质等级为一等品,二等品,三等品
typedef enum packingmethod { BOX, BULK }PACKINGMETHOD;//定义包装方式有盒装、散装
typedef struct fruit
{
char name[NAMELENGTH] = { 0 };//水果名称
char kind[NAMELENGTH] = { 0 };//品种
PACKINGMETHOD packing;//包装方式
LEVEL level;//质量等级
//char number[NAMELENGTH] = { 0 };//进货单号
//char date[DATELENGTH] = {0};//过期时间
double cost = 0;//成本价(元/kg)
double price = 0;//水果单价(元/kg)
double stock = 0;//库存(kg)
struct fruit* next;
}FRUIT;//每一批货物的结构体
FRUIT* head = NULL, * rear = NULL;//链表头指针与尾指针
void showMainMenu();//显示主功能菜单
void mainMenu();//运行主功能菜单
void add(FRUIT* newfruit);//创建与延长链表函数
void load();//从文件加载文件到链表中
void fruitCreate();//建立水果信息
void showFruit(FRUIT* fruit);//打印水果信息
void searchFruit();//查找水果信息
void saveFruit();//存储水果信息
void showAllFruit();//展示所有水果信息
int main()
{
load();
showMainMenu();
mainMenu();
}
//显示主功能菜单
void showMainMenu()
{
printf("欢迎使用超市果蔬管理系统!\n");
printf("**************************\n");
printf("*-----建立水果信息:1-----*\n");
printf("*-----查找水果信息:2-----*\n");
printf("*-----修改水果信息:3-----*\n");
printf("*-----删除水果信息:4-----*\n");
printf("*-----显示水果信息:5-----*\n");
printf("*----- 退出系统 :6-----*\n");
printf("**************************\n");
return;
}
//运行主功能菜单
void mainMenu()
{
int select;
while (true)
{
intInputLimitation1(&select);//选择
switch (select)
{
case 1:fruitCreate();return;//建立水果信息
case 2:showAllFruit();return;//显示水果信息
case 3:
case 4:
case 5:
case 6:saveFruit();exit(0);
default:printf("请输入正确数字!\n");break;
}
}
}
//向链表中添加水果结构体
void add(FRUIT* fruit)
{
if (head == NULL)//如果头指针为空,说明链表不存在,新建链表
{
head = rear = fruit;
rear->next = NULL;
return;
}
rear->next = fruit;//如果头指针不为空,链表存在,在链表尾续
rear = fruit;
rear->next = NULL;
return;
}
//打印水果信息
void showFruit(FRUIT* fruit)
{
printf("水果名称:%s\t水果品种:%s\t\n", fruit->name, fruit->kind);//打印名称、品种,换行
switch (fruit->packing)
{
case BOX:printf("包装方式:盒装\t");break;
case BULK:printf("包装方式:散装\t");break;
}
switch (fruit->level)
{
case FIRST:printf("质量等级:一等品\t");break;
case SECOND:printf("质量等级:二等品\t");break;
case THIRD:printf("质量等级:三等品\t");break;
}
printf("成本价:%.2f元/kg\t单价:%.2f元/kg\t库存:%.2fkg\n", fruit->cost, fruit->price, fruit->stock);
return;
}
//展示所有水果信息
void showAllFruit()
{
FRUIT* fruit=head;
if (fruit == NULL)
printf("信息为空!\n");
else
{
while (fruit!=NULL)
{
showFruit(fruit);
fruit = fruit->next;
}
}
system("pause");
system("cls");
showMainMenu();
mainMenu();
}
//建立水果信息
void fruitCreate()
{
FRUIT* fruit;
fruit = (FRUIT*)malloc(sizeof(FRUIT));
printf("请输入新水果名称:\n");//输入水果名称
stringInputLimitation(NAMELENGTH, fruit->name);
printf("请输入水果品种:\n");//输入水果品种
stringInputLimitation(NAMELENGTH, fruit->kind);
int select;//用于选择的整数
//选择质量等级
while (true)
{
printf("请选择包装方式:1、盒装 2、散装\n");
intInputLimitation1(&select);//用户输入以选择
if (select == 1 || select == 2)
{
if (select == 1)
fruit->packing = BOX;
if (select == 2)
fruit->packing = BULK;
break;//输入正确,跳出
}
printf("请正确选择!\n");//输入错误,重新输入
}
//选择包装方式
while (true)
{
printf("请选择质量等级:1、一等品 2、二等品 3、三等品\n");
intInputLimitation1(&select);//用户输入以选择
if (select == 1 || select == 2 || select == 3)
{
if (select == 1)
fruit->level = FIRST;
if (select == 2)
fruit->level = SECOND;
if (select == 3)
fruit->level = THIRD;
break;//输入正确,跳出
}
printf("请正确选择!\n");//输入错误,重新输入
}
//输入过期时间
printf("请按照如下格式输入过期时间:年 月 日");
system("pause");
printf("请输入成本价:(元/kg)\n");//输入成本价
doubleInputLimitation(&fruit->cost);
printf("请输入水果单价:(元/kg)\n");//输入单价
doubleInputLimitation(&fruit->price);
printf("请输入进货数量:(kg)\n");//输入进货数量
doubleInputLimitation(&fruit->stock);
add(fruit);//添加到链表中
printf("创建成功!按任意键返回\n");
system("pause");
system("cls");
showMainMenu();
mainMenu();
}
void saveFruit()
{
FILE* fp;//文件指针
fp = fopen("stockdata.txt", "w");
FRUIT* fruit=head;//链表临时指针
while (fruit!=NULL)//信息写入文件
{
fprintf(fp, "%s\t%s\t%d\t%d\t%.2lf\t%.2lf\t%.2lf\n", fruit->name, fruit->kind, fruit->packing, fruit->level, fruit->cost, fruit->price, fruit->stock);
fruit = fruit->next;
}
fclose(fp);//关闭文件指针
return;
}
void load()
{
FILE* fp;
fp = fopen("stockdata.txt", "r");
if (fp == NULL)//如果文件不存在则创建
{
fp = fopen("stockdata.txt", "w");
fclose(fp);
return;
}
FRUIT* fruit;//链表临时指针
while (!feof(fp))//文件指针未达到文件尾则持续读入
{
fruit = (FRUIT*)malloc(sizeof(FRUIT));
fscanf(fp, "%s%s%d%d%lf%lf%lf", fruit->name, fruit->kind, &fruit->packing,&fruit->level,&fruit->cost,&fruit->price,&fruit->stock);
add(fruit);
}
fclose(fp);
return;
}
其中输入限制头文件是自己写的限制用户输入的头文件,代码如下
#ifndef Input_Limitation
#define Input_Limitation
#include<stdio.h>
#include<math.h>
//限制输入字符串函数
void stringInputLimitation(int size, char str[])//输入字符串大小和待输入字符串
{
while (true)
{
if (scanf_s("%s", str, size) == 1)//输入正确,退出
{
getchar();//清理缓冲区
return;
}
printf("最多输入%d个汉字或者%d个字符!请重新输入:\n", size / 2, size);
while (getchar() != '\n');//清理缓冲区
}
}
//限制输入整数函数(只能输入9位有效数字)(完杀)
void intInputLimitation9(int* pnumber)
{
char ch;
while (true)
{
if (scanf_s("%9d", pnumber) == 1)//输入正确,退出
{
while ((ch = getchar()) == ' ' || ch == '\t');//数字后的空白字符忽略
if (ch == '\n')//输入正确只能是数字后空白字符加回车
return;
}
printf("请输入整数且最多为9位数!\n");//输入非整数字串或者数字超过1位
while (getchar() != '\n');
}
}
//限制输入整数函数(只能输入1位有效数字)
void intInputLimitation1(int* pnumber)
{
char ch;
while (true)
{
if (scanf_s("%1d", pnumber) == 1)//输入正确,退出
{
while ((ch = getchar()) == ' ' || ch == '\t');//数字后的空白字符忽略
if (ch == '\n')//输入正确只能是数字后空白字符加回车
return;
}
printf("请输入整数且最多为1位数!\n");//输入非整数字串或者数字超过1位
while (getchar() != '\n');
}
}
//限制输入整数函数(最多只能输入X位有效数字)(用字符串存)
void intInputLimitationX(char number[], int x)
{
while (true)
{
while (true)//检查超界
{
if (scanf_s("%s", number, x) == 1)//若未超界,跳出,进行数字判断
break;
printf("请输入正确数字且最多为%d位数!\n", x - 1);//若超界,清理缓冲区继续输入
while (getchar() != '\n');
}
int i = 0;//计数用
for (;number[i] != '\0';i++)
{
if (number[i] >= '0' && number[i] <= '9')
continue;
printf("请输入正确数字且最多为%d位数!\n", x - 1);//若类型不正确,重新输入
break;
}
if (number[i] == '\0')
{
getchar();//清理回车
return;
}
}
}
//限制输入长浮点数函数(double)(整数部分只能输入10位,小数点后只能输入两位)
void doubleInputLimitation(double* pnumber)
{
double sum;
char ch;
while (true)
{
while (scanf_s("%13lf", &sum) == 1)//浮点数输入正确
{
if (sum >= pow(10, 13)) break;//检测整数部分是否超界
if (sum * 100 - (long long)(sum * 100) != 0) break;//检测小数部分是否超界
while ((ch = getchar()) == ' ' || ch == '\t');//数字后的空白字符忽略
if (ch == '\n')//输入正确只能是数字后空白字符加回车
{
*pnumber = sum;
return;
}
break;
}
printf("请输入正确数字且整数部分最多为10位,小数部分最多为2位!\n");//输入非浮点数或整数部分超过10位
while (getchar() != '\n');
}
}
#endif