我在想程序的问题是什么。键入quit时无法退出程序。
这是我所拥有的:
#include <stdio.h>
#include <string.h>
int main(void) {
char string[200];
printf("Enter a bunch of words: ");
do
{
scanf("%[^\n]c", string);
}while(strcmp(string,"quit")!=0);
return 0;
}
最佳答案
您的两个最大问题是使用scanf
困扰新C程序员的两个最常见问题:
让我们首先解决第一件事:
scanf("%[^\n]c", string);
您的格式字符串
"%[^\n]c"
使用字符类格式说明符"%[...]"
来读取string
的文本。然后是"c"
-仅与您输入字符串末尾的文字'c'
相匹配。由于"%[^\n]"
将读取不是'\n'
的所有字符,仅留下'\n'
进行读取,而这与'c'
不匹配,因此不会发生这种情况。此外,
"%[...]"
说明符与"%c"
说明符一起不占用前导空格('\n'
为空格)。因此,将'\n'
保留为未读状态时,您对stdin
的下一次调用将失败,因为scanf
不会读取"%[^\n]"
,并且它与'\n'
不匹配,从而导致匹配失败,因此'c'
仍未读入'\n'
中,事情很快就失去了控制。要解决所有问题,您需要记住上面的
stdin
,并使用field-width修饰符保护(2.)
的数组边界,然后应阅读并保存提取的字符并将其放在string
中以保存到中,以确保完整读取了输入行-如果没有,则是您的责任,负责在尝试下一次读取之前删除string
中剩余的所有多余字符。对于初学者,您可以使用格式适当受限的字符串,该字符串开头应包含
stdin
,这将导致space
放弃所有前导空格,例如 " %199[^\n]%c"
请注意,上面将保存最终字符,将进行两次转换,因此您将需要一个字符变量来处理最终转换说明符的结果,例如
do {
char c; /* final character read */
int retn; /* variable to save scanf return */
/* prompt */
fputs ("Enter a bunch of words ('quit' exits): ", stdout);
/* read saving scanf return */
retn = scanf (" %199[^\n]%c", string, &c);
(注意:,提示已在
scanf
循环内移动了)接下来的和负责每次检查
do {...} while (..);
的返回。您必须处理三个条件scanf
用户通过按Ctrl + d(或在Windows上Ctrl + z)生成手动(return == EOF)
来取消输入; EOF
,必须处理匹配或输入失败,并且必须考虑输入缓冲区中可能剩余的每个字符。 (通常,您将在输入缓冲区中向前扫描,直到找到(return < expected No. of conversions)
或'\n'
丢弃任何剩余的多余字符,请参见示例中的EOF
函数);和empty_stdin()
表示读取成功-然后由您检查输入是否满足任何其他条件(例如正整数,正浮点等)。 综上所述,您可以使用
(return == expected No. of conversions)
循环阅读并寻找scanf
作为提示退出的关键字,如下所示: do {
char c; /* final character read */
int retn; /* variable to save scanf return */
/* prompt */
fputs ("Enter a bunch of words ('quit' exits): ", stdout);
/* read saving scanf return */
retn = scanf (" %199[^\n]%c", string, &c);
if (retn == EOF) { /* check the return against EOF */
fputs ("(user canceled input)\n", stderr);
return 0;
}
else if (retn < 2) { /* checking both string and c read */
fputs ("input failure.\n", stderr);
empty_stdin();
}
else if (c != '\n') { /* check c is '\n', else string too long */
fprintf (stderr, "warning: input exceeds %d characters.\n",
MAXC - 1);
empty_stdin();
}
else /* good input, output string */
printf ("string: %s\n", string);
} while (strcmp (string,"quit") != 0);
最后,请勿在代码中使用幻数(
"quit"
是幻数)。相反,如果您需要一个常量,请使用200
一个(或多个)。您必须对数字进行硬编码的唯一地方是例如#define
字段宽度修饰符-不能使用变量,宏或命名常量。这是该规则的一个例外。同样,请勿对文件名或路径进行硬编码。所有函数都带有参数,甚至是scanf
,都将所需的信息传递给您的程序。综上所述,您可以执行以下操作:
#include <stdio.h>
#include <string.h>
#define MAXC 200 /* constant - maximum characters in string */
void empty_stdin (void)
{
int c = getchar();
while (c != EOF && c != '\n')
c = getchar();
}
int main (void) {
char string[MAXC]; /* use constants for array bounds */
do {
char c; /* final character read */
int retn; /* variable to save scanf return */
/* prompt */
fputs ("Enter a bunch of words ('quit' exits): ", stdout);
/* read saving scanf return */
retn = scanf (" %199[^\n]%c", string, &c);
if (retn == EOF) { /* check the return against EOF */
fputs ("(user canceled input)\n", stderr);
return 0;
}
else if (retn < 2) { /* checking both string and c read */
fputs ("input failure.\n", stderr);
empty_stdin();
}
else if (c != '\n') { /* check c is '\n', else string too long */
fprintf (stderr, "warning: input exceeds %d characters.\n",
MAXC - 1);
empty_stdin();
}
else /* good input, output string */
printf ("string: %s\n", string);
} while (strcmp (string,"quit") != 0);
return 0;
}
示例使用/输出
$ ./bin/scanf_string_quit
Enter a bunch of words ('quit' exits): Hello
string: Hello
Enter a bunch of words ('quit' exits): My dog has fleas and my cat has none.
string: My dog has fleas and my cat has none.
Enter a bunch of words ('quit' exits): quit
string: quit
使用Ctrl + d(或在windoze中为Ctrl + z)生成手动
main()
:$ ./bin/scanf_string_quit
Enter a bunch of words ('quit' exits): Hello
string: Hello
Enter a bunch of words ('quit' exits): (user canceled input)
将
EOF
重置为MAXC
并将字段宽度修饰符重置为20
更改为scanf
,您可以检查对太长的行的处理,例如第一个输入合适,第二个输入太长:$ ./bin/scanf_string_quit
Enter a bunch of words ('quit' exits): my dog has fleas and my cat has none.
warning: input exceeds 19 characters.
Enter a bunch of words ('quit' exits): 1234567890123456789
string: 1234567890123456789
Enter a bunch of words ('quit' exits): 12345678901234567890
warning: input exceeds 19 characters.
Enter a bunch of words ('quit' exits): quit
string: quit
仔细检查一下,如果您还有其他问题,请告诉我。