scanf 和来自先前输入的输入流中的左侧字符 → setvbuf?
scanf and a left character in the input stream from previous input → setvbuf?
我有一道理解题。好久没用过C了,今天翻了一下C语言的线程,偶然发现了下面这句话,我粗略地引用在这里:
“scanf 正在读取您输入的上一个输入中留在输入流中的字符。”
有件事进入了我的记忆。在那些日子里,我使用 setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, BUFSIZ);
来避免这种行为。这些行确保输入流中没有上一个输入留下的字符。
我现在的问题是:这是一个好的解决方案吗?这是我一直想知道的
我想你的意思是你会在 调用 scanf
之后调用 setvbuf
,并且至少在在一个 C 实现中,它具有丢弃标准输入缓冲区中 scanf
未使用的任何“剩余”字符的效果。
这不是丢弃“剩余”字符的好方法,因为 C 标准规定 setvbuf
“只能在流与打开的文件相关联之后且在任何其他操作之前使用(除了对 setvbuf 的不成功调用)在流上执行”。 (N1570 §7.21.5.6p2。)违反此规则 应该 只会导致 setvbuf 失败,但这意味着它不会执行您想要的操作。
做你想做的最好的方法是不使用scanf
。相反,为您的输入编写一个真正的解析器,并逐个字符(使用 getchar
)或逐行(使用 getline
或 fgets
)输入它。一个真正的解析器有原则地处理白色 space(包括换行符)和语法错误,因此永远不会发现自己有“遗留”输入。
不幸的是,编写真正的解析器是一本书长度的主题,所以我只会说 sscanf
在真正的解析器中也永远没有用。 ( 有用的标准库函数包括 strsep
、strchr
和 strto*
系列。)
在极少数情况下(通常涉及处理 interactive 输入),您确实必须丢弃行尾的垃圾。在那些情况下,方法是使用这个循环:
int c;
do c = getchar();
while (c != '\n' && c != EOF);
我有一道理解题。好久没用过C了,今天翻了一下C语言的线程,偶然发现了下面这句话,我粗略地引用在这里:
“scanf 正在读取您输入的上一个输入中留在输入流中的字符。”
有件事进入了我的记忆。在那些日子里,我使用 setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, BUFSIZ);
来避免这种行为。这些行确保输入流中没有上一个输入留下的字符。
我现在的问题是:这是一个好的解决方案吗?这是我一直想知道的
我想你的意思是你会在 调用 scanf
之后调用 setvbuf
,并且至少在在一个 C 实现中,它具有丢弃标准输入缓冲区中 scanf
未使用的任何“剩余”字符的效果。
这不是丢弃“剩余”字符的好方法,因为 C 标准规定 setvbuf
“只能在流与打开的文件相关联之后且在任何其他操作之前使用(除了对 setvbuf 的不成功调用)在流上执行”。 (N1570 §7.21.5.6p2。)违反此规则 应该 只会导致 setvbuf 失败,但这意味着它不会执行您想要的操作。
做你想做的最好的方法是不使用scanf
。相反,为您的输入编写一个真正的解析器,并逐个字符(使用 getchar
)或逐行(使用 getline
或 fgets
)输入它。一个真正的解析器有原则地处理白色 space(包括换行符)和语法错误,因此永远不会发现自己有“遗留”输入。
不幸的是,编写真正的解析器是一本书长度的主题,所以我只会说 sscanf
在真正的解析器中也永远没有用。 ( 有用的标准库函数包括 strsep
、strchr
和 strto*
系列。)
在极少数情况下(通常涉及处理 interactive 输入),您确实必须丢弃行尾的垃圾。在那些情况下,方法是使用这个循环:
int c;
do c = getchar();
while (c != '\n' && c != EOF);