C语言读取TXT文件异常求助:无法正确提取姓名与时间
解决C语言读取TXT文件提取人名和时间的问题
嘿,我来帮你搞定这个文件读取的问题!你现在遇到的两个核心问题——人名带冒号、时间读错,都是因为代码里的字符读取逻辑没处理好.和:之间的空格与非空白字符,咱们一步步拆解修复:
问题出在哪?
- 人名带冒号:你用
fscanf(f," %s %s",pnome,unome)读取人名,但%s的规则是读到空白字符就停止,而:不属于空白字符,所以当遇到Pedro Mendes:时,第二个%s会把Mendes:整个读进去,导致人名末尾带冒号。 - 时间读错行:在读取完错误的人名后,你用
while(fgetc(f) != ':')找冒号,但此时冒号已经被前面的fscanf读进unome里了,这个循环会一直跳过字符,直到找到下一行的冒号,自然就读到下一行的时间了。
修复方案:两种可靠的实现方式
方法一:用fscanf的格式控制直接匹配
利用%[^:]格式符(表示读取所有不是冒号的字符),可以精准提取.之后、:之前的完整人名(包括空格),代码示例:
#include <stdio.h> #include <stdlib.h> #define MAX_NAME 100 // 定义足够大的人名缓冲区 int main() { const char *filename = "seu_arquivo.txt"; FILE *f = fopen(filename, "rt"); if (f == NULL) { printf("Erro no acesso ao ficheiro.\n"); return EXIT_FAILURE; } char fullname[MAX_NAME]; int tempo; int c; while (!feof(f)) { // 跳过所有字符直到找到'.',同时避免文件结束死循环 while ((c = fgetc(f)) != '.' && c != EOF); if (c == EOF) break; // 读取'.'之后到':'之前的所有字符(包括空格),前面的空格跳过可能的空白 if (fscanf(f, " %99[^:]", fullname) != 1) { // 读取失败时跳过当前行剩余内容,避免卡死 while ((c = fgetc(f)) != '\n' && c != EOF); continue; } // 跳过':'字符 while ((c = fgetc(f)) != ':' && c != EOF); if (c == EOF) break; // 读取冒号后的时间 if (fscanf(f, "%d", &tempo) == 1) { printf("Nome: %s | Tempo: %d\n", fullname, tempo); } // 跳过当前行剩余内容,准备处理下一行 while ((c = fgetc(f)) != '\n' && c != EOF); } fclose(f); return EXIT_SUCCESS; }
方法二:整行读取后解析(更灵活)
如果你的文本每条记录占一行,用fgets读取整行,再用字符串函数找.和:的位置,这种方法更直观,也不容易出错:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE 256 int main() { const char *filename = "seu_arquivo.txt"; FILE *f = fopen(filename, "rt"); if (f == NULL) { printf("Erro no acesso ao ficheiro.\n"); return EXIT_FAILURE; } char line[MAX_LINE]; while (fgets(line, sizeof(line), f) != NULL) { // 找到'.'的位置 char *dot_pos = strchr(line, '.'); if (dot_pos == NULL) continue; // 找到':'的位置(从'.'之后开始找) char *colon_pos = strchr(dot_pos, ':'); if (colon_pos == NULL) continue; // 提取人名:从dot_pos+1到colon_pos-1 *colon_pos = '\0'; // 把':'换成字符串结束符 char *name = dot_pos + 1; // 去掉人名前后的多余空格(可选) while (*name == ' ') name++; char *name_end = colon_pos - 1; while (name_end > name && *name_end == ' ') name_end--; *(name_end + 1) = '\0'; // 提取时间 int tempo = atoi(colon_pos + 1); printf("Nome: %s | Tempo: %d\n", name, tempo); } fclose(f); return EXIT_SUCCESS; }
关键注意事项
- 缓冲区大小:定义数组时要预留足够空间,或者用
%99[^:]这种带长度限制的格式符,避免缓冲区溢出。 - 文件结束判断:所有读取操作都要检查
EOF,防止死循环或读取错误内容。 - 空白处理:如果人名前后可能有空格,记得用额外的逻辑去除(方法二里已经包含了这个处理)。
内容的提问来源于stack exchange,提问作者Sandra Perdigao
相关产品推荐
相关产品推荐

