我正在写一个有趣的程序(不是为了上学),我很难弄清楚为什么scanf
函数不是在我的循环的每次迭代中执行-我已经玩弄了'for'循环和'while'循环。
我知道这取决于我如何写scanf
函数(即scanf("%s", &variablename);
VS scanf("%99[^n]s", &variablename);
)会有所不同,但我已经尝试了一切,我很绝望!
当我对scanf
的输入进行printf
检查时,每次迭代它只输入一个字符串,所以如果我在第一次输入中输入两个单词,那么它需要两次迭代来处理-每次一个单词。下面是我要描述的代码段:
int main(void){
int tries = 0;
int score = 0;
char question[100];
char useranswer[100];
const char *phrase = {"our favorite saying "};
printf("nQuestion #3 (10 points): What is our secret saying?n");
sleep(1);
tries = 1;
while (tries<=3){
printf("YOUR ANSWER:");
scanf("%s[^n]", useranswer);
if(strncmp(useranswer, phrase, 15) != 0){
printf ("Nope, try again!n");
printf("You have used %d out of 3 tries!n", tries);
if (tries == 2){
printf("Here's your final hint:xxx...n");
}
if (tries == 3){
printf("You didn't get it. The answer is: our favorite saying!n");
}
tries++;
}
if (strncmp(useranswer, phrase, 15) == 0){
printf("Damn, you're good. Well done.n");
score += 10;
break;
}
}
该代码的输出是:
Question #3 (10 points): What is our secret saying?
YOUR ANSWER:our favorite saying
Nope, try again!
You have used 1 out of 3 tries!
YOUR ANSWER:Nope, try again!
You have used 2 out of 3 tries!
Here's your final hint:xxx...
YOUR ANSWER:Nope, try again!
You have used 3 out of 3 tries!
You didn't get it. The answer is: our favorite saying!
(它只允许我输入一次,我输入了"我们最喜欢的说法")
在注释中你可以找到为什么你的scanf
格式说明符不起作用
另一种选择是使用fgets
,可能在辅助函数中处理读取用户输入时可能出现的一些极端情况:
#include <ctype.h>
char *read_line( char *buf, size_t n, FILE *pfin )
{
ssize_t length = 0;
int ch;
if ( !buf || n == 0 )
return NULL;
/* Consume trailing control characters, like ' ','n', 'r', 'f'...
but also 't'. Note that ' ' is not skipped. */
while ( (ch = fgetc(pfin)) != EOF && iscntrl(ch) ) { }
if ( ch == EOF )
return NULL;
/* At least one char is printable */
*buf = ch;
++length;
/* Read from file till a newline or up to n-2 chars. The remaining chars
are left in the stream buffer. Return NULL if no char is read. */
if ( fgets(buf + 1, n - 1, pfin) )
{
/* Trim the string to the first control character */
while ( !iscntrl(buf[length]) )
{
++length;
}
buf[length] = ' ';
}
return buf;
}
我也会改变下面的逻辑。OP多次使用strncmp(useranswer, phrase, 15)
,但是这个神奇的数字15
比phrase
的大小小,所以它最终只比较一个子字符串。
while ( tries <= 3 ) {
printf("YOUR ANSWER:");
if ( !read_line(useranswer, sizeof useranswer, stdin) ) {
printf("Error: Unexpected end of input.n");
exit(EXIT_FAILURE);
}
if( strcmp(useranswer, phrase) == 0 ) {
printf("Damn, you're good. Well done.n");
score += 10;
break;
} else {
printf ("Nope, try again!n");
printf("You have used %d out of 3 tries!n", tries);
if (tries == 2) {
printf("Here's your final hint:xxx...n");
}
if (tries == 3) {
printf("You didn't get it. The answer is: our favorite saying!n");
}
tries++;
}
}
最后要说明的是,我发现
phrase
的OP声明有点奇怪(可能是拼写错误):
const char *phrase = {"our favorite saying "};
// string literals are already ^^ null terminated...
可以使用简单的数组声明,如:
const char phrase[] = "our favorite saying";
同时考虑sizeof phrase
在这两种不同情况下返回的值。
感谢@chux提供的所有有价值的提示和有趣的链接:
https://stackoverflow.com/a/27729970/4944425
https://stackoverflow.com/a/28462221/4944425
感谢@Dmitri在他的评论中指出,一旦我们确定两个字符串都是空终止的,我们可以使用
strcmp
而不是strncmp
。