[英]Scanf skipped in loop (Hangman)
This program essentially asks for a secret string, then asks a user to repeatedly guess single chars of that string until he guesses it all. 该程序本质上要求输入一个秘密字符串,然后要求用户反复猜测该字符串的单个字符,直到他完全猜测为止。 It works however every second time the while loop is run it skips user input for the guessed char.
它每隔运行一次while循环便会工作,它会跳过用户输入的猜测字符。 How do I fix this?
我该如何解决?
int main(){
char guess;
char test2 [50];
char * s = test2;
char output [50];
char * t = output;
printf("Enter the secret string:\n");
fgets(test2, 50, stdin);
for (int i=0;i<49;i++){ //fills ouput with _ spaces
*(output +i)='_';
while(strcmp(s,t) != 0){
printf("Enter a guess:");
scanf("%c",&guess);
printf("You entered: %c\n", guess);
showGuess(guess,s, t ); // makes a string "output" with guesses in it
printf("%s\n",t);
}
printf("Well Done!");
}
For a quick and dirty solution try 快速而肮脏的解决方案请尝试
// the space in the format string consumes optional spaces, tabs, enters
if (scanf(" %c", &guess) != 1) /* error */;
For a better solution redo your code to use fgets()
and then parse the input. 为了获得更好的解决方案,请重做代码以使用
fgets()
,然后解析输入。
As pointed out in some other answers and comments, you need to "consume" the "newline character" in the input. 如在其他答案和注释中指出的那样,您需要在输入中“使用”“换行符”。
The reason for that is that the input from your keyboard to the program is buffered by your shell, and so, the program won't see anything until you actually tell your shell to "pass the content of its buffer to the program". 这样做的原因是,从键盘到程序的输入由外壳程序缓冲,因此,在您真正告诉外壳程序“将其缓冲区的内容传递给程序”之前,程序看不到任何东西。 At this point, the program will be able to read the data contained in the previous buffer, eg your input, followed by one the character(s) used to validate your input in the shell: the newline.
此时,程序将能够读取先前缓冲区中包含的数据,例如您的输入,然后是用于验证外壳中输入内容的字符:换行符。 If you don't "consume" the newline before you do another
scanf
, that second scanf
will read the newline character, resulting in the "skipped scanf
" you've witnessed. 如果您在执行另一个
scanf
之前不“使用”换行符,则第二个scanf
将读取换行符,从而导致您目击到“ skf scanf
”。 To consume the extra character(s) from the input, the best way is to read them and discard what you read (what the code below does, notice the 要使用输入中的多余字符,最好的方法是读取它们并丢弃所读取的内容(以下代码会做什么,请注意
while(getc(stdin) != '\n');
line after your scanf
. 在
scanf
。 What this line does is: "while the character read from stdin
is not '\\n'
, do nothing and loop."). 该行的作用是:“虽然从
stdin
读取的字符不是'\\n'
,但不执行任何操作并循环。”)。
As an alternative, you could tell your shell to not buffer the input, via the termios(3)
functions, or you could use either of the curses / ncurses libraries for the I/O. 或者,您可以通过
termios(3)
函数告诉shell不要缓冲输入,或者可以将curses / ncurses库之一用于I / O。
So here is what you want: 所以这是您想要的:
int main(){
char guess;
char test2 [50];
char * s = test2; // 3. Useless
char output [50];
char * t = output; // 3. Useless
int i; // 8. i shall be declared here.
printf("Enter the secret string:\n");
fgets(test2, 50, stdin);
for (i=0;i<50;i++) if (test2[i] == '\n') test2[i] = '\0'; // 4. Remove the newline char and terminate the string where the newline char is.
for (int i=0;i<49;i++){ // 5. You should use memset here; 8. You should not declare 'i' here.
*(output +i)='_';
} // 1. Either you close the block here, or you don't open one for just one line.
output[49] = '\0'; // 6. You need to terminate your output string.
while(strcmp(s,t) != 0){ // 7. That will never work in the current state.
printf("Enter a guess:");
scanf("%c",&guess);
while(getc(stdin) != '\n');
printf("You entered: %c\n", guess);
showGuess(guess,s, t );
printf("%s\n",t);
}
printf("Well Done!");
return 0; // 2. int main requires that.
}
Other comments on your code: 您的代码的其他注释:
for
loop and never closed it. for
循环之后打开了一个块,但从未关闭它。 That might be causing problems. main
as a function returning an integer... So you should at least return 0;
main
声明为返回整数的函数...因此,至少应return 0;
at the end. char * t = output;
char * t = output;
copies output
's value and uses t
as a name for the new copy. output
的值,并使用t
作为新副本的名称。 This is wrong. output
in t
. t
中output
的地址(即引用)。 As a result, output
and t
refer to the same data, and if you modify output
, t
will get modified; output
和t
引用相同的数据,如果您修改output
,则t
将被修改; and vice versa . t
and s
variables are useless in the current state. t
和s
变量在当前状态下是无用的。 fgets
for that. fgets
之后添加了一行。 memset
function instead. memset
考虑使用memset
函数。 '\\0'
in last position. '\\0'
。 NULL
terminated after its meaningful content. NULL
终止时,输出1会用下划线填充。 Also, "_ spaces" are called "underscores" ;) 此外,“ _个空格”也称为“下划线”;)
Here is a code that does what you want: 这是执行您想要的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 50
int main()
{
char phrase[LEN];
char guessed[LEN];
char guess;
int i, tries = 0;
puts("Please enter the secret string:");
if(fgets(phrase, LEN, stdin) == NULL)
return 1;
for(i = 0; i < LEN && phrase[i] != '\n'; i++); // Detect the end of input data.
for(; i < LEN; i++) // For the rest of the input data,
phrase[i] = '_'; // fill with underscores (so it can be compared with 'guessed' in the while loop).
phrase[LEN - 1] = '\0'; // NULL terminate 'phrase'
memset(guessed, '_', LEN); // Fill 'guessed' with underscores.
guessed[LEN - 1] = '\0'; // NULL terminate 'guessed'
while(strcmp(phrase, guessed) != 0) // While 'phrase' and 'guessed' differ
{
puts("Enter a guess (one character only):");
if(scanf("%c", &guess) != 1)
{
puts("Error while parsing stdin.");
continue;
}
if(guess == '\n')
{
puts("Invalid input.");
continue;
}
while(getc(stdin) != '\n'); // "Eat" the extra remaining characters in the input.
printf("You entered: %c\n", guess);
for(i = 0; i < LEN; i++) // For the total size,
if(phrase[i] == guess) // if guess is found in 'phrase'
guessed[i] = guess; // set the same letters in 'guessed'
printf("Guessed so far: %s\n", guessed);
tries++;
}
printf("Well played! (%d tries)\n", tries);
return 0;
}
Feel free to ask questions in the comments, if you are not getting something. 如果您没有收到任何意见,请随时在评论中提问。 :)
:)
Newline character entered in the previous iteration is being read by scanf. scanf正在读取上一次迭代中输入的换行符。 You can take in the '\\n' by using the getc() as follows:
您可以使用getc()来输入“ \\ n”,如下所示:
scanf("%c",&guess);
getc(stdin);
.. ..
This changed worked for me. 这改变了对我的工作。 Though the right explanation and c leaner code is the one given by @7heo.tk
尽管正确的解释和更精简的代码是@ 7heo.tk给出的解释
Change 更改
scanf("%c",&guess);
with 与
scanf(" %c",&guess);
It should ignore '\\n'
. 它应该忽略
'\\n'
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.