空哥sky 2024-03-07 15:51 采纳率: 47.1%
浏览 7
已结题

C语言通讯录写入文件增容显示出错

VS2022,想写一个通讯录,假设最开始容量是3,超过3就增容,往文件里写的时候写第四个写入成功,关闭之后再运行显示的就出错了是为啥


void CheckCapacity(Contact* pc)
{
    if (pc->count == pc->capacity)//如果空间不够,增容
    {
        PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INT_SZ) * sizeof(PeoInfo));
        if (ptr == NULL)
        {
            printf("扩容失败\n");
            return;
        }
        else
        {
            pc->data = ptr;
            pc->capacity += INT_SZ;
            printf("增容成功\n");
        }
    }

}
void LoadContact(Contact* pc)
{
    FILE* pfRead;
    errno_t err = fopen_s(&pfRead, "C:\\C语言\\test_24_3_6\\test.txt", "rb");
    if (pfRead == NULL)
    {
        perror("LoadContact");
        return;
    }
    PeoInfo tmp = { 0 };

    while (fread(&tmp, sizeof(PeoInfo), 1, pfRead) == 1)
    {
        //增容
        CheckCapacity(pc);
        pc->data[pc->count] = tmp;
        pc->count++;
    }
    fclose(pfRead);
    pfRead = NULL;

}

img

  • 写回答

7条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-07 15:51
    关注

    引自免费微信小程序:皆我百晓生

    在您的代码中,CheckCapacity函数用于检查通讯录数组容量,并在需要时进行增容。但是,在LoadContact函数读取文件内容并写入通讯录数组的过程中,您对CheckCapacity的调用位置存在一些问题,这可能导致当超过初始容量时,数据没有正确地存储和重新分配。

    根据您提供的代码片段,当读取到第四个联系人信息时确实会进行一次增容,但是在循环内每次读取新条目之前并没有检查容量。这意味着如果文件中有多个连续的记录需要写入,可能会在未检查容量的情况下先将数据写入旧的、未扩容的空间,然后才进行扩容操作。这样会导致前几次循环写入的数据被后一次扩容后的内存重写而丢失。

    为了修正这个问题,确保每次向通讯录数组添加新的联系人信息前都检查并适当扩容,您可以稍微调整代码逻辑:

    void LoadContact(Contact* pc)
    {
        FILE* pfRead;
        errno_t err = fopen_s(&pfRead, "C:\\C语言\\test_24_3_6\\test.txt", "rb");
        if (pfRead == NULL)
        {
            perror("LoadContact");
            return;
        }
        
        while (1) // 使用条件循环,按需读取和检查容量
        {
            // 先检查容量是否足够,不够则扩容
            if (pc->count == pc->capacity)
            {
                CheckCapacity(pc);
            }
    
            PeoInfo tmp = { 0 };
            
            // 读取单个联系人信息
            if (fread(&tmp, sizeof(PeoInfo), 1, pfRead) != 1)
            {
                break; // 如果无法读取下一个,则跳出循环
            }
    
            // 将读取到的信息写入已扩容的数组
            pc->data[pc->count] = tmp;
            pc->count++;
        }
    
        fclose(pfRead);
        pfRead = NULL;
    }
    

    另外,请注意在CheckCapacity函数中的扩容大小,您使用了INT_SZ这个变量,但在这个上下文中它似乎并未定义或初始化。如果您打算每次增加固定数量的槽位,例如增加3个联系人空间,应该在前面定义好常量(如 #define INT_SZ 3),或者直接在realloc调用中指定合适的增量值。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月9日
  • 创建了问题 3月7日