C语言中如何正确将文件单行数字读取到结构体的数组中?
C语言中如何正确将文件单行数字读取到结构体的数组中?
看起来你遇到的问题是把文件里的单行数字读取到结构体的int数组后,得到的全是垃圾值,而且调试时函数内部打印的结果也不对。我帮你排查了几个可能的问题,以及对应的解决办法:
最可能的元凶:UTF-8 BOM字节干扰
如果你是用Windows自带的记事本保存的UTF-8格式文件,文件开头会偷偷加上3个字节的BOM(十六进制是EF BB BF)。这三个字节不是普通空格,strtok会把它们当成第一个"token"的一部分,atoi把这个非数字的字节序列转成了奇怪的大整数(比如你看到的1102871301,正好是0xEFBBBF的十进制值)。而且因为BOM和后面的数字之间没有空格,strtok只会读到这一个错误的token,所以返回的数组长度总是1。
代码里的其他潜在问题
- 循环逻辑漏洞:你的
keepReading只有在找到目标行时才会设为false,但如果文件的行数比你指定的readLine少,fgets会返回NULL(表示到了文件末尾),这时候lineBuffer里的内容是不确定的,后续处理会读取无效数据。而且你没有检查fgets的返回值,可能会处理到无效的行内容。 - 分隔符太局限:你只用
" "作为strtok的分隔符,但如果文件里的数字之间有多个空格、制表符(Tab)或者换行符,就会分割失败,导致读取不完整。
修正后的完整代码
我把你的代码做了针对性修改,加上了BOM处理、错误检查和更灵活的分隔符:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> // 定义结构体 typedef struct mapData { int* walls; // 可以添加其他成员变量 } mapData; static mapData currentMap; void fileToArray(char *fileName, int lineSize, int readLine, int *array, int *returnedArrayLength) { FILE *file = fopen(fileName, "r"); if (file == NULL) { printf("Error opening file\n"); return; } bool keepReading = true; int currentLine = 1; char lineBuffer[2048]; bool foundTargetLine = false; while (keepReading) { // 先检查fgets是否成功读取到内容,避免处理无效数据 if (fgets(lineBuffer, sizeof(lineBuffer), file) == NULL) { keepReading = false; break; } if (currentLine == readLine) { foundTargetLine = true; keepReading = false; // 处理UTF-8 BOM:如果文件开头有BOM,跳过前3个字节 char *start = lineBuffer; if ((unsigned char)start[0] == 0xEF && (unsigned char)start[1] == 0xBB && (unsigned char)start[2] == 0xBF) { start += 3; } // 用空格、Tab、换行作为分隔符,适配更多场景 char *token = strtok(start, " \t\n"); int i = 0; while (token != NULL && i < lineSize) { array[i++] = atoi(token); token = strtok(NULL, " \t\n"); } printf("Returned array length: %d from line: %d\n", i, readLine); for (int j = 0; j < i; j++) { printf("%d ", array[j]); } printf("\n"); if (returnedArrayLength) { *returnedArrayLength = i; } } currentLine++; } // 如果没找到目标行,给出提示 if (!foundTargetLine) { printf("Line %d not found in the file\n", readLine); } fclose(file); } // 主函数示例 int main() { int mapSize = 10; // 根据你的实际需求调整数组大小 int returnedLength; // 分配内存时检查是否成功 currentMap.walls = malloc(mapSize * sizeof(int)); if (currentMap.walls == NULL) { printf("Malloc failed: out of memory\n"); return 1; } // 注意第一个参数是你的文件名,比如"map.txt" fileToArray("map.txt", mapSize, 1, currentMap.walls, &returnedLength); // 打印结构体数组的内容,验证是否正确 printf("\nStruct array content:\n"); for (int j = 0; j < returnedLength; j++) { printf("%d ", currentMap.walls[j]); } printf("\n"); // 记得释放内存,避免内存泄漏 free(currentMap.walls); return 0; }
额外的注意事项
- 文件保存格式:尽量用纯文本编辑器(比如Notepad++)保存文件,选择「UTF-8无BOM」格式,从根源上避免BOM的干扰。
- 内存管理:记得在使用完
malloc分配的数组后用free释放,避免内存泄漏。 - 数组大小:确保
mapSize足够大,能容纳文件里的所有数字,避免数组越界。
内容来源于stack exchange
相关产品推荐
相关产品推荐

