C语言scanf使用%*c%c时第二段代码无法正常接收输入问题
问题根因与解决方法
先搞懂核心原理(不用记底层,记规则就行)
所有你从键盘敲的内容,包括按的回车、不小心敲的空格,都会先存在一块叫「输入缓冲区」的临时内存里,scanf不是直接读你实时敲的键,是从这个缓冲区里取内容。不同格式符的读取规则差很多:
%d(读整数):会自动跳过缓冲区开头所有的空白(空格、回车、Tab缩进),碰到数字才开始读,读完数字就停下,数字后面跟着的回车/空格会留在缓冲区里。%c(读单个字符):不跳过任何内容,缓冲区当前排在第一个的字符是什么,它就直接读走,哪怕这个字符是你上一次输入完按的回车。
你教授说的%*c,作用是读1个字符但不存到变量里、直接扔掉,本意是想扔掉上一次输入残留的回车,再读你新输入的有效字符。
为什么会出现跳过输入的bug
%*c%c这个写法本身有很大的局限性,它只能在「缓冲区里恰好剩1个需要扔掉的残留字符」的场景下生效,只要不符合这个前提就会出问题:
- 如果缓冲区是空的(比如程序刚启动跑第一个输入、或者上一次把缓冲区内容读完了),
%*c不会等你输完有效选项再扔,它会直接把你敲的第一个有效字符(比如选咖啡类型敲的L/B)扔掉,后面的%c就读到你按的回车,相当于这步输入白敲了。 - 如果你输完上一个内容后多按了一次回车、或者不小心敲了空格,缓冲区里残留的空白字符就不止1个,
%*c只能扔掉1个,剩下的回车/空格会被后面的%c直接读走,scanf不会停下来等你输入,直接执行下一行代码,就是你看到的「跳过输入环节直接显示后续内容」的现象。
你第一段代码能正常跑只是巧合:你输入的时候每次都刚好只按一下回车,不多敲多余字符,刚好凑上了%*c只扔1个字符的要求,跑到第二段的时候只要有一次输入多带了一个空白字符,整个后续输入流程就全乱了。
零出错的简单改法
根本不需要用%*c来手动算要扔几个字符,只要记住一个规则:所有用来读单个字符的%c,前面加一个空格就行。
格式串里的空格,对scanf来说意思是「跳过缓冲区里所有连续的空白字符,不管有多少个,直到碰到第一个非空白的有效字符再开始读」,不管你之前残留了多少回车、空格,全都会被自动跳过,不会读走你输入的有效字符,也不会出现跳过输入的问题。
改完的代码如下:
printf("COFFEE-1...\n"); printf("Type ([L]ight,[B]lend): "); scanf(" %c", &type1); // 注意%c前的空格,不要漏 printf("Grind size ([C]ourse,[F]ine): "); scanf(" %c", &grind1); printf("Bag weight (g): "); scanf("%d", &weight1); // %d默认会跳过空白,不需要修改 printf("Best served with cream ([Y]es,[N]o): "); scanf(" %c", &cream1); printf("Ideal serving temperature (Celsius): "); scanf("%d", &temp1); printf("\nCOFFEE-2...\n"); printf("Type ([L]ight,[B]lend): "); scanf(" %c", &type2); printf("Grind size ([C]ourse,[F]ine): "); scanf(" %c", &grind2); printf("Bag weight (g): "); scanf("%d", &weight2); printf("Best served with cream ([Y]es,[N]o): "); scanf(" %c", &cream2); printf("Ideal serving temperature (Celsius): "); scanf("%d", &temp2);
改完之后不管你输入的时候多按几次回车、不小心敲了空格,都不会出现输入被跳过的问题。
内容的提问来源于stack exchange,提问作者DavidsBeard
相关产品推荐
相关产品推荐

