C语言读取TXT文件时提取含空格姓名的问题求助
解决fscanf读取带空格姓名的问题
问题根源在于fscanf的%s格式符会在遇到空白字符(空格、换行、制表符)时停止读取,再加上你原格式串里多余的逗号(原文件中无逗号),导致字段匹配逻辑混乱,最终出现只拿到smith的异常结果。
下面是几种可行的解决方法:
方法1:整行读取后拆分(最稳妥通用)
先把整行内容读入缓冲区,再从后往前解析固定格式的后续字段,剩下的部分就是带空格的姓名。这种方法不受姓名是否包含特殊字符的限制,容错性强:
#include <stdio.h> #include <string.h> int main() { FILE *file = fopen("data.txt", "r"); if (!file) { perror("Failed to open file"); return 1; } char line[100]; // 读取整行内容 if (!fgets(line, sizeof(line), file)) { perror("Failed to read line"); fclose(file); return 1; } // 去掉行尾的换行符 line[strcspn(line, "\n")] = '\0'; char name[50], priorityGroup[20]; int age, priorityLevel; // 连续找三次倒数的空格,定位到姓名的结束位置 char *p = strrchr(line, ' '); p = strrchr(line, ' ', p - line - 1); p = strrchr(line, ' ', p - line - 1); // 复制前面的内容作为姓名 strncpy(name, line, p - line); name[p - line] = '\0'; // 从空格后解析后续字段 sscanf(p + 1, "%d %s %d", &age, priorityGroup, &priorityLevel); // 输出测试 printf("Name: %s\n", name); printf("Age: %d\n", age); printf("Priority Group: %s\n", priorityGroup); printf("Priority Level: %d\n", priorityLevel); fclose(file); return 0; }
方法2:利用格式符读取非数字内容(适用于姓名无数字的场景)
如果可以确定姓名中不包含数字,直接用%[^0-9]格式符读取所有直到第一个数字的字符,再跳过空格读取后续字段:
#include <stdio.h> #include <string.h> #include <ctype.h> int main() { FILE *file = fopen("data.txt", "r"); if (!file) { perror("Failed to open file"); return 1; } char name[50], priorityGroup[20]; int age, priorityLevel; // %[^0-9] 读取所有非数字字符(含空格),%*[ ] 跳过姓名与年龄间的空格(*表示不存储) fscanf(file, "%[^0-9]%*[ ]%d %s %d", name, &age, priorityGroup, &priorityLevel); // 去掉姓名末尾多余的空格 char *end = name + strlen(name) - 1; while (end > name && isspace(*end)) end--; *(end + 1) = '\0'; printf("Name: %s\n", name); printf("Age: %d\n", age); printf("Priority Group: %s\n", priorityGroup); printf("Priority Level: %d\n", priorityLevel); fclose(file); return 0; }
方法3:先读后续字段再回退指针
先读取后面的固定字段,记录文件指针位置后回退到开头,读取指针前的内容作为姓名:
#include <stdio.h> #include <string.h> int main() { FILE *file = fopen("data.txt", "r"); if (!file) { perror("Failed to open file"); return 1; } int age, priorityLevel; char priorityGroup[20]; // 先读取后续三个字段,记录当前指针位置 fscanf(file, "%d %s %d", &age, priorityGroup, &priorityLevel); long pos = ftell(file); // 回退到文件开头 fseek(file, 0, SEEK_SET); // 读取指针前的内容作为姓名,预留空间存储字符串结束符 char name[pos]; fread(name, 1, pos - 2, file); // 减去末尾的空格和指针偏移量 name[pos - 2] = '\0'; printf("Name: %s\n", name); printf("Age: %d\n", age); printf("Priority Group: %s\n", priorityGroup); printf("Priority Level: %d\n", priorityLevel); fclose(file); return 0; }
推荐说明
优先选择方法1,因为它不依赖姓名的内容限制,能适配更多场景(比如姓名含数字、多空格分隔等),代码逻辑也更清晰。
内容的提问来源于stack exchange,提问作者Player1 ready
相关产品推荐
相关产品推荐

