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
相关产品推荐
相关产品推荐

