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

C语言fscanf读取带空格姓名的竖线分隔文件出错求助

问题根源与解决办法

为什么会出现乱码和无限循环?

  1. %s格式符的缺陷:%14s会在遇到第一个空格时停止读取,所以姓名只能读到Larry,剩下的Normal留在输入流中,导致后续的|匹配失败。此时fscanf返回的是成功读取的字段数(比如1),既不是预期的4,也不是EOF,所以循环会无限执行。未正确读取的变量内存未被初始化,输出时就会出现乱码。
  2. 循环条件错误:用!= EOF作为循环终止条件是错误的。当fscanf匹配失败时,它不会返回EOF,而是返回成功读取的字段数量,这会导致循环一直运行。
  3. 缓冲区风险:部分字段的缓冲区大小刚好卡着长度,没有预留字符串结束符的位置,容易出现溢出问题。

解决方法

方法一:整行读取后分割(推荐,兼容性更强)

先用fgets读取整行内容,再用strtok按|分割字段,能完美处理含空格的姓名:

#include <stdio.h>
#include <string.h>

int main() {
    FILE* patientFile = NULL;
    char line[100];
    int patientNum;
    char patientName[30];
    char phoneDescription[5];
    char phoneNumber[11];

    patientFile = fopen("patientData.txt", "r");

    if (patientFile != NULL) {
        while (fgets(line, sizeof(line), patientFile) != NULL) {
            char* token = strtok(line, "|");
            if (!token) continue;
            patientNum = atoi(token);

            token = strtok(NULL, "|");
            if (!token) continue;
            strncpy(patientName, token, sizeof(patientName)-1);
            patientName[sizeof(patientName)-1] = '\0';

            token = strtok(NULL, "|");
            if (!token) continue;
            strncpy(phoneDescription, token, sizeof(phoneDescription)-1);
            phoneDescription[sizeof(phoneDescription)-1] = '\0';

            token = strtok(NULL, "|\n");
            if (!token) continue;
            strncpy(phoneNumber, token, sizeof(phoneNumber)-1);
            phoneNumber[sizeof(phoneNumber)-1] = '\0';

            printf("%d %s %s %s\n", patientNum, patientName, phoneDescription, phoneNumber);
        }
        fclose(patientFile);
    } else {
        printf("Failed to open patients file\n");
    }
    return 0;
}

方法二:修改fscanf格式串

使用%[^|]格式符匹配到|之前的所有字符(包括空格),同时调整循环条件为判断成功读取4个字段:

#include <stdio.h>

int main() {
    FILE* patientFile = NULL;
    int patientNum;
    char patientName[30];
    char phoneDescription[5];
    char phoneNumber[11];

    patientFile = fopen("patientData.txt", "r");

    if (patientFile != NULL) {
        // %29[^|] 表示读取最多29个字符(留1位给结束符),直到遇到|为止
        while (fscanf(patientFile, "%d|%29[^|]|%4[^|]|%10s\n", &patientNum, patientName, phoneDescription, phoneNumber) == 4) {
            printf("%d %s %s %s\n", patientNum, patientName, phoneDescription, phoneNumber);
        }
        fclose(patientFile);
    } else {
        printf("Failed to open patients file\n");
    }
    return 0;
}

关键注意点

  • 读取含空格的字符串时,%s不适用,必须用%[^分隔符]或者整行读取后分割。
  • 循环条件必须判断fscanf的返回值等于预期读取的字段数,避免匹配失败时的无限循环。
  • 所有字符数组必须预留至少1位的空间给字符串结束符\0,防止内存溢出和乱码。

内容的提问来源于stack exchange,提问作者user3385214

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 10:55:18