费欣宇 2022-04-05 09:24 采纳率: 84.6%
浏览 62
已结题

大一程序期中,请帮我看看我写的将文件内容载入链表的函数为啥载入错误

文件内容载入链表的函数是这样的,在文件为空的情况下总是写入乱码


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

  • 写回答

2条回答 默认 最新

  • [PE]经典八炮 2022-04-05 09:46
    关注

    feof函数有些问题,你必须先读取一次,然后判断feof,如果非0就说明结束,而不是先判断再读取,这样会多读取一次

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 4月13日
  • 已采纳回答 4月5日
  • 创建了问题 4月5日

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看