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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 05:44:59