int main(int argc, char *argv[]) {
int option;
char user[50];
system("COLOR b");
printf("~~~~~~~~~~~~~~~~ GLENMUIR HIGH SCHOOL LIBRARY MANAGEMENT SYSTEM ~~~~~~~~~~~~~~~~~~~~~~~ \n");
printf("Username:");
scanf("%c",&user);
checkPass();
printf("\n | Options Menu |\n");
printf(" | Check Out Book(1), Return Book(2) , Register(3), Admin Login (4) |\n");
printf("Option:");
scanf("%d",&option); /*compiler ignores this completely*/
我尝试在%d之前添加空格,但仍然无效。对于newb的任何解决方案?
你的问题来自这个声明:
scanf("%c",&user);
%c
转换说明符仅从输入流中读取单个字符,而不是字符串。如果您输入了像jbode
这样的用户名,则只从输入流中读取'j'
字符 - 剩余的字符将由下一个scanf
(或其他输入)调用读取。
不幸的是,由于scanf
转换说明符,下一个%d
调用期望一个十进制数字序列; 'b'
不是十进制数字,因此您得到匹配失败 - option
未更新,'b'
未从输入流中删除,scanf
返回0表示未成功转换发生。
正确的答案是不要使用scanf
来读取用户名,而是使用fgets
代替:
if ( !fgets( user, sizeof user, stdin ) )
{
// EOF or error detected on input, handle as appropriate
}
checkPass();
...
但是,如果你真的想使用scanf
,那么正确的方法是:
if ( scanf( "%49s", user ) != 1 ) // no & operator on user
{
// EOF or error detected on input, handle as appropriate
}
checkPass();
...
在将字符串读入&
数组时,您不需要使用char
运算符。表达式user
将隐式地从类型char [50]
转换(“衰减”)到char *
,并且结果指针值将是数组的第一个元素的地址。
来自转换说明符下的标准7.21.6.2及其含义:
s
匹配一系列非空白字符.286)如果不存在l长度修饰符,则相应的参数应该是指向大小足以接受序列和终止空字符的字符数组的初始元素的指针,将自动添加。
作为scanf
的替代品,您可以尝试查看fgets
。
所以答案将是scanf("%s",user);
或更正确的使用将是scanf("%49s",user)
。为了更好地了解为什么你应该考虑fgets
而不是scanf
读到这个discussion。
此外,没有必要在%d
格式说明符之前放置空格,因为根据标准7.21.6.2
除非规范包括
isspace
,[
或c
说明符,否则将跳过输入的空格字符(由n
函数指定)。
除了上面提到的变化,检查scanf
的返回值。
if( scanf("%49s",user) != 1){
fprintf(stderr,"You have given wrong input - use input just a word\n");
exit(1);
}
在您的情况下,如果您输入了错误,那么这将失败,您将收到错误消息。
您可以像这样在%d
中使用scanf
说明符,无需提供' '
。
if( scanf("%d",&option)!= 1){
/* handle error. Put appropriate meaningful error message. */
exit(1);
}
同样在Dev-cpp中尝试添加编译器标志-Wall -Wextra
,它将显示警告。
general
下的Adds the following command when compiler is called
标签和-Wall -Wextraand press
OK`,=。编译它。你会得到一些像这样的错误 - [警告]格式%c
期望char *
类型的参数,但参数2
的类型为char (*)[20]
[-Wformat =]
&user
表示指向包含20个字符的char
s数组的指针。但如上所述,你必须将char*
作为第二个参数传递给scanf
。