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

C语言中fgets、带%[^ ]格式的scanf_s不等待用户输入的原因是什么

根本原因

你代码里的问题是标准输入缓冲区残留换行符导致的:

  • 调用scanf_s("%d", &ch)读取数字时,只会提取输入流中的数字字符,用户输入完成后按下回车产生的\n换行符会残留在stdin缓冲区中,没有被读取处理。
  • fgets和%[^\n]格式符的读取规则是遇到换行符就终止读取,当缓冲区已经存在残留换行时,调用这两个接口会直接读取到该换行符,认为已经完成一行读取,自然不会阻塞等待用户输入。
  • 而%s格式符默认会跳过输入开头的所有空白字符(包含换行、空格、制表符等),残留的换行符会被自动忽略,所以使用%s时会正常等待用户输入非空白内容,没有阻塞问题。
修复方案

步骤1:清空输入缓冲区残留内容

每次调用scanf_s("%d", &ch)读取用户选项后,手动清空缓冲区中直到换行符的所有残留内容:

// 插入到scanf_s("%d", &ch); 之后,switch语句之前
int c;
while ((c = getchar()) != '\n' && c != EOF);

这段代码会把输入缓冲区中所有未读取的字符全部丢弃,确保后续读取整行的接口可以正常阻塞等待用户输入。

步骤2:修正writeMem实现

推荐使用fgets版本实现整行读取,同时可以根据需求去掉读取结果末尾的换行符,另外要注意strcpy_s的第二个参数是目标缓冲区的大小,你的目标是共享内存(大小为64KB),不要误传源缓冲区txt的大小:

void writeMem(void* p)
{
    char txt[128];
    printf(">>2 ");
    fgets(txt, _countof(txt), stdin);
    // 可选:去掉fgets读取到的末尾换行符
    size_t len = strlen(txt);
    if (len > 0 && txt[len - 1] == '\n') {
        txt[len - 1] = '\0';
    }
    // 目标缓冲区是64KB共享内存,传入正确的大小
    strcpy_s((char*)p, 1 << 16, txt);
}

如果要使用scanf_s的%[^\n]格式实现,注意格式符后面不需要加额外的s,很多开发者容易写错这个点:

void writeMem(void* p)
{
    char txt[128];
    printf(">>2 ");
    scanf_s("%[^\n]", txt, (unsigned)_countof(txt));
    // 读取完内容后同样要清空残留的换行符,避免影响后续操作
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
    strcpy_s((char*)p, 1 << 16, txt);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:15:05