You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++98下使用fwrite写入FILE文件失败,如何解决?

解决C++98中fwrite无法写入配置文件的问题

问题背景

使用C++98在NetBeans 8.0开发,已实现从simple.conf加载键值对数据到表单,但Update函数无法将表单中的字符串、IP地址、浮点数、整数写入该文件,配置文件格式为每行值 键。

核心错误分析

  1. 文件打开模式错误:Update函数用"r"只读模式打开文件,无写入权限,根本无法修改文件内容。
  2. fwrite参数误用:fwrite正确参数为fwrite(数据指针, 单个元素大小, 元素个数, 文件流),你写成了fwrite(name, sizeof(name), sizeof(name), fptr),会把整个50字节的char数组(含末尾垃圾数据)重复写入50次,完全不符合需求。
  3. 逻辑匹配错误:
    • 匹配Name时错误写入section数据
    • 匹配Section时错误写入class1数据
    • 匹配Number和Total时写入未初始化的grade数组(垃圾数据)
  4. 直接修改原文件风险:即使改成读写模式,原文件每行长度不同时,新内容会覆盖后续字节,导致文件结构混乱。

修正方案(安全读写版本)

采用「读取原文件内容→内存中修改→写入临时文件→替换原文件」的方式,避免直接修改原文件的风险,同时修正所有逻辑错误:

修正后的Update函数代码

#include "newForm.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>

// 定义键值对结构
typedef struct {
    char value[50];
    char key[50];
} ConfigPair;

void newForm::Update() {
    // 1. 读取原配置文件所有内容到内存
    FILE* fptr = fopen("/root/Desktop/simple.conf", "r");
    if (!fptr) {
        perror("Failed to open config file for reading");
        return;
    }

    ConfigPair pairs[10]; // 假设最多10个配置项
    int pairCount = 0;

    while (pairCount < 10) {
        if (fscanf(fptr, "%s %s", pairs[pairCount].value, pairs[pairCount].key) != 2) {
            break;
        }
        pairCount++;
    }
    fclose(fptr);

    // 2. 用表单数据更新内存中的键值对
    const char* name = widget.lineEdit_1->text().toLocal8Bit().constData();
    const char* classVal = widget.lineEdit_2->text().toLocal8Bit().constData();
    const char* section = widget.lineEdit_3->text().toLocal8Bit().constData();
    const char* number = widget.lineEdit_4->text().toLocal8Bit().constData();
    const char* total = widget.lineEdit_5->text().toLocal8Bit().constData();

    for (int i = 0; i < pairCount; i++) {
        if (strcmp(pairs[i].key, "Name") == 0) {
            strncpy(pairs[i].value, name, sizeof(pairs[i].value)-1);
            pairs[i].value[sizeof(pairs[i].value)-1] = '\0'; // 确保字符串终止
        } else if (strcmp(pairs[i].key, "Class") == 0) {
            strncpy(pairs[i].value, classVal, sizeof(pairs[i].value)-1);
            pairs[i].value[sizeof(pairs[i].value)-1] = '\0';
        } else if (strcmp(pairs[i].key, "Section") == 0) {
            strncpy(pairs[i].value, section, sizeof(pairs[i].value)-1);
            pairs[i].value[sizeof(pairs[i].value)-1] = '\0';
        } else if (strcmp(pairs[i].key, "Number") == 0) {
            strncpy(pairs[i].value, number, sizeof(pairs[i].value)-1);
            pairs[i].value[sizeof(pairs[i].value)-1] = '\0';
        } else if (strcmp(pairs[i].key, "Total") == 0) {
            strncpy(pairs[i].value, total, sizeof(pairs[i].value)-1);
            pairs[i].value[sizeof(pairs[i].value)-1] = '\0';
        }
    }

    // 3. 写入临时文件
    FILE* tempFptr = fopen("/root/Desktop/simple.tmp", "w");
    if (!tempFptr) {
        perror("Failed to open temp file for writing");
        return;
    }

    for (int i = 0; i < pairCount; i++) {
        fprintf(tempFptr, "%s\t%s\n", pairs[i].value, pairs[i].key);
    }
    fclose(tempFptr);

    // 4. 替换原文件
    if (remove("/root/Desktop/simple.conf") != 0) {
        perror("Failed to remove old config file");
        remove("/root/Desktop/simple.tmp"); // 清理临时文件
        return;
    }
    if (rename("/root/Desktop/simple.tmp", "/root/Desktop/simple.conf") != 0) {
        perror("Failed to rename temp file to config file");
        remove("/root/Desktop/simple.tmp");
        return;
    }
}

关键修正点说明

  • 文件操作逻辑:先只读读取原文件,再写入临时文件,最后替换原文件,避免直接修改原文件导致的数据损坏。
  • 字符串安全处理:用strncpy替代strcpy,避免缓冲区溢出,手动添加字符串终止符保证数据有效性。
  • 匹配逻辑修正:每个键对应正确的表单输入数据,解决原代码中的匹配错误。
  • 文本写入优化:用fprintf替代fwrite,更适合文本格式配置文件,自动处理字符串长度,避免写入垃圾数据。

内容的提问来源于stack exchange,提问作者gatcheca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:15:36