这个程序本质上要求一个秘密字符串,然后要求用户反复猜测该字符串的单个字符,直到他猜到这一切。然而,它每隔一次运行while循环就会工作,它会跳过猜测的char的用户输入。我该如何解决这个问题?
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!");
}
答案 0 :(得分:1)
要快速而肮脏的解决方案,请尝试
// the space in the format string consumes optional spaces, tabs, enters
if (scanf(" %c", &guess) != 1) /* error */;
要获得更好的解决方案,请重新使用代码fgets()
,然后解析输入。
答案 1 :(得分:1)
正如其他一些答案和评论所指出的那样,你需要&#34;消费&#34; &#34;换行符&#34;在输入中。
原因是键盘到程序的输入由shell缓存,因此,程序不会看到任何内容,直到您实际告诉shell传递内容为止。它的缓冲程序&#34;。此时,程序将能够读取先前缓冲区中包含的数据,例如,您的输入,后跟一个用于验证shell中输入的字符:换行符。如果你不消费&#34;在执行另一个scanf
之前的新行,第二个scanf
将读取换行符,从而导致&#34;跳过scanf
&#34;你目睹了。要从输入中消耗额外的字符,最好的方法是阅读它们并丢弃你读的内容(下面的代码是什么,注意
while(getc(stdin) != '\n');
在scanf
之后排成一行。这一行的作用是:&#34;当从stdin
读取的字符不是'\n'
时,不做任何事情并循环。&#34;)。
作为替代方案,您可以通过termios(3)
函数告诉shell不缓冲输入,或者您可以使用curses / ncurses库中的任意一个/ O操作。
所以这就是你想要的:
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.
}
对您的代码的其他评论:
for
循环后打开了一个块,但从未关闭它。这可能会导致问题。main
声明为返回整数的函数...所以最后至少应该return 0;
。char * t = output;
复制output
的值,并使用t
作为新副本的名称。这是错的。您确实在复制某些内容,但只复制output
中t
的地址(a.k.a参考)。因此,output
和t
引用相同的数据,如果您修改output
,t
将被修改;而反之亦然。否则说,那些t
和s
变量在当前状态下是无用的。fgets
之后添加了一行。memset
功能而不是设置阵列的所有字节&#34;#34;而不是设置'\0'
功能。NULL
。#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;
}
终止时,输出字符串会被下划线填充。此外,&#34; _空格&#34;被称为&#34;下划线&#34; ;)
这是一个可以满足您需求的代码:
{{1}}
如果你没有得到什么,请随意在评论中提问。 :)
答案 2 :(得分:0)
scanf正在读取上一次迭代中输入的换行符。你可以接受&#39; \ n&#39;通过使用getc()如下:
scanf("%c",&guess);
getc(stdin);
...
这改变了对我有用。虽然正确的解释和更精简的代码是@ 7heo.tk给出的代码
答案 3 :(得分:0)
更改
scanf("%c",&guess);
与
scanf(" %c",&guess);
它应该忽略'\n'
。