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

C语言读取文本文件数据全为0/Null问题排查求助

问题分析与修复方案

我来帮你梳理下代码里的几个关键问题,这就是你输出全是0或空值的核心原因:

1. 打印时访问了未初始化的数组元素

在SortedMergedFile函数的循环里,你先把数据读入elements[i],紧接着就执行i++,然后打印的是elements[i]——这时候i已经指向了下一个完全没被赋值的元素,自然输出的是随机垃圾值(看起来像0或空字符串)。

举个例子:

  • 第一次循环开始时i=0,成功读入elements[0]
  • 立刻执行i++,i变成1
  • 打印elements[1],但这个元素根本没被初始化过,内容是未知的

修复方法:把i++放到打印语句之后,或者直接在打印时使用当前的i,读取完成后再自增。

2. 文件打开的错误处理不严谨

你的main函数里,如果file1打不开但file2能正常打开,程序还是会调用SortedMergedFile函数,这时候file1是NULL指针,用它来执行fscanf会直接导致错误。

修复方法:必须确保两个文件都成功打开才执行合并逻辑,否则及时关闭已打开的文件并退出程序。

3. 当前代码完全没处理第二个文件

你的函数名是SortedMergedFile,但目前的代码只循环读取了file1的4个元素,完全没涉及file2的内容,这和你“合并两个文件”的目标不符。


修正后的完整代码

我把这些问题都修复了,还添加了排序和写入合并文件的逻辑(按原子序数排序):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define str_len 100

// 修正结构体拼写错误(Periodoc → Periodic)
typedef struct {
    int atmNum;
    char name[str_len];
    char symbol[str_len];
    float atmWeight;
} PeriodicElement;

// 排序用的比较函数,用于qsort
int compareElements(const void *a, const void *b) {
    const PeriodicElement *elemA = (const PeriodicElement *)a;
    const PeriodicElement *elemB = (const PeriodicElement *)b;
    return elemA->atmNum - elemB->atmNum;
}

void SortedMergedFile(FILE *file1, FILE *file2);

int main() {
    FILE *file1 = fopen("1.txt", "r");
    FILE *file2 = fopen("2.txt", "r");

    // 严格检查文件是否打开成功
    if (file1 == NULL) {
        printf("FILE 1 DOES NOT EXIST\n");
        if (file2 != NULL) fclose(file2);
        return EXIT_FAILURE;
    }
    if (file2 == NULL) {
        printf("FILE 2 DOES NOT EXIST\n");
        fclose(file1);
        return EXIT_FAILURE;
    }

    SortedMergedFile(file1, file2);

    // 用完文件记得关闭,避免资源泄漏
    fclose(file1);
    fclose(file2);
    return EXIT_SUCCESS;
}

void SortedMergedFile(FILE *file1, FILE *file2) {
    PeriodicElement elements[150];
    int count = 0;

    // 读取第一个文件的内容,用fscanf返回值判断是否成功读取4个字段
    while (fscanf(file1, "%d %s %s %f", &elements[count].atmNum, elements[count].name, elements[count].symbol, &elements[count].atmWeight) == 4) {
        printf("\n读取file1元素:%d %s %s %4.2f", elements[count].atmNum, elements[count].name, elements[count].symbol, elements[count].atmWeight);
        count++;
        if (count >= 150) break; // 防止数组越界
    }

    // 读取第二个文件的内容
    while (fscanf(file2, "%d %s %s %f", &elements[count].atmNum, elements[count].name, elements[count].symbol, &elements[count].atmWeight) == 4) {
        printf("\n读取file2元素:%d %s %s %4.2f", elements[count].atmNum, elements[count].name, elements[count].symbol, elements[count].atmWeight);
        count++;
        if (count >= 150) break;
    }

    // 按原子序数从小到大排序
    qsort(elements, count, sizeof(PeriodicElement), compareElements);
    printf("\n\n排序后的元素:");
    for (int i = 0; i < count; i++) {
        printf("\n%d %s %s %4.2f", elements[i].atmNum, elements[i].name, elements[i].symbol, elements[i].atmWeight);
    }

    // 写入合并后的文件
    FILE *mergedFile = fopen("merged.txt", "w");
    if (mergedFile != NULL) {
        for (int i = 0; i < count; i++) {
            fprintf(mergedFile, "%d %s %s %.2f\n", elements[i].atmNum, elements[i].name, elements[i].symbol, elements[i].atmWeight);
        }
        fclose(mergedFile);
        printf("\n\n合并后的文件已成功生成:merged.txt");
    } else {
        printf("\n\n无法创建合并文件!");
    }
}

额外提示

  • 读取文件时用fscanf的返回值(成功匹配的字段数)来判断读取是否成功,比固定循环次数更灵活,能适应文件内容行数不确定的情况
  • 记得始终关闭已打开的文件,避免系统资源泄漏
  • 我修正了结构体名称的拼写错误(PeriodocElement → PeriodicElement),虽然不影响编译,但更符合英文拼写规范

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:02:32