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

C语言读取文件中Country结构体仅输出两次hello?如何实现文件重复条目删除

问题分析与解决方案

核心问题:文本文件误用二进制读取

你的文件是纯文本格式,但代码使用fread按二进制结构体的字节数读取,这完全不匹配文本的存储格式。结构体在内存中的二进制布局(比如char数组后的填充、float的二进制编码)和文本里的换行分隔内容完全不同,导致fread读取的字节数错误,循环只执行两次。

解决步骤

1. 改用文本方式读取记录

使用fscanf(或fgets配合sscanf)读取文本文件中的每条记录,确保正确解析3个字段:

struct Country{
    char name[50];
    float square;
    float quantityOfPeople;
};

// 示例读取逻辑(文件以文本模式"r"打开)
struct Country newRecord;
FILE *fout = fopen("countries.txt", "r");
FILE *fp_tmp = fopen("tmp_countries.txt", "w");
if (!fout || !fp_tmp) {
    perror("Failed to open file");
    return 1;
}

// 用%49s限制name长度避免溢出
while (fscanf(fout, "%49s%f%f", newRecord.name, &newRecord.square, &newRecord.quantityOfPeople) == 3) {
    printf("hello\n");
    // 后续去重逻辑...
}

2. 实现重复条目删除完整逻辑

要删除重复条目,需要记录已出现过的国家名称,只保留首次出现的记录:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_RECORDS 100 // 根据实际情况调整最大记录数

struct Country{
    char name[50];
    float square;
    float quantityOfPeople;
};

int main() {
    struct Country records[MAX_RECORDS];
    struct Country current;
    int record_count = 0;
    FILE *fout = fopen("countries.txt", "r");
    FILE *fp_tmp = fopen("tmp_countries.txt", "w");

    if (!fout || !fp_tmp) {
        perror("File open failed");
        return 1;
    }

    // 读取所有记录并去重
    while (fscanf(fout, "%49s%f%f", current.name, &current.square, &current.quantityOfPeople) == 3) {
        int is_duplicate = 0;
        // 检查当前名称是否已存在
        for (int i = 0; i < record_count; i++) {
            if (strcmp(current.name, records[i].name) == 0) {
                is_duplicate = 1;
                break;
            }
        }
        if (!is_duplicate) {
            // 保持文本格式写入临时文件
            fprintf(fp_tmp, "%s\n%f\n%f\n\n", current.name, current.square, current.quantityOfPeople);
            memcpy(&records[record_count], &current, sizeof(struct Country));
            record_count++;
        }
    }

    // 关闭文件
    fclose(fout);
    fclose(fp_tmp);

    // 替换原文件
    if (remove("countries.txt") != 0) {
        perror("Failed to delete original file");
        return 1;
    }
    if (rename("tmp_countries.txt", "countries.txt") != 0) {
        perror("Failed to rename temp file");
        return 1;
    }

    return 0;
}

注意事项

  • 如果要保持输出文件的文本格式,必须用fprintf写入,fwrite会生成二进制文件
  • 必须处理文件操作的错误情况,避免数据丢失或程序崩溃
  • 可根据实际数据量调整MAX_RECORDS,或改用动态数组存储已出现的名称

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:25:18