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
相关产品推荐
相关产品推荐

