我的代码:
int main(){
char readChars[3];
puts("Enter the value of the card please:");
scanf(readChars);
printf(readChars);
printf("done");
}
我所看到的只是: "完成" 在我为终端输入一些值并按Enter后,为什么?
编辑:
不是scanf的原型:
int scanf(const char *format, ...);
所以我应该只用一个参数就可以使用它?
答案 0 :(得分:6)
实际问题是您将未初始化的数组作为格式传递给scanf()
。
此外,您正在以错误的方式调用scanf()
尝试此
if (scanf("%2s", readChars) == 1)
printf("%s\n", readChars);
scanf()
以及printf()
使用格式字符串,这实际上是其名称中f
的原因。
是的,您只能使用一个参数,scanf()
根据格式字符串扫描输入,格式字符串使用与输入匹配的特殊值,如果您至少未指定然后scanf()
只对输入验证有用。
以下内容摘自C11草案
7.21.6.2 fscanf功能
- 醇>
格式应为多字节字符序列,以其初始移位状态开始和结束。格式由零个或多个指令组成:一个或多个空格字符,普通的多字节字符(既不是%也不是空白字符),或转换规范。每个转换规范由字符%引入。在%之后,以下顺序出现:
- 可选的赋值抑制字符*。
- 大于零的可选十进制整数,指定最大字段宽度 (字符)。
- 可选的长度修饰符,用于指定接收对象的大小。
- 转换说明符字符,指定要应用的转换类型。
正如您在上面所读到的,您需要传递至少一个转换说明符,在这种情况下,相应的参数用于存储转换后的值,如果您传递转换说明符但是没有为它提供参数,则行为未定义。
答案 1 :(得分:5)
是的,可以只用一个参数调用scanf
,有时它甚至可能有用。但它不会做你显然认为会做的事情。 (它只是期望输入流中的参数中的字符并跳过它们。)您没有注意到,因为您没有作为程序员进行尽职调查。我列出你应该做的事情:
RTFM。 scanf
的第一个参数是格式字符串。不是转换序列的一部分并且不是空格的普通字符在字面上在输入中是预期的。它们被读取并丢弃。如果它们没有出现,转换就会停止,并且输入流中出现意外字符的位置是后续读取的开始。在你的情况下,可能没有从输入中成功读取任何字符,但你不确定,因为你没有初始化格式字符串(见下文)。
另一个有趣的细节是scanf
的返回值,表示成功读取的项目数。我将在下面讨论以及检查返回值的重要性。
初始化本地人。由于性能原因,C不会自动初始化本地数据(在今天的情况下,可能会像其他语言一样强制执行用户初始化,或者将自动初始化设置为默认值选择退出几个内部循环的可能性,它会受到伤害)。因为您没有初始化readchars
,所以您不知道其中包含了什么,因此您不知道输入流中预期的scanf
。最重要的是它可能是名义上未定义的行为。 (但是在你的电脑上它不应该做任何意想不到的事情。)
检查返回值。 scanf
可能在您的示例中返回0。手册指出scanf返回成功读取的项目数,此处为0,即没有发生输入转换。这种类型的未检测到的故障在长序列的读操作中可能是致命的,因为以下scanf
可能会从一系列标记中读取一次性索引,或者也可能会停顿(并且根本不会更新它们的指针)等等。
请耐心等待 - 我并不总是阅读手册,检查返回值或(错误)初始化小测试程序的变量。但如果它不起作用,这是我调查的一部分。在我问任何人之前,更不用说世界了,我确实已经尽力确定我事先找出了我做错了什么。
答案 2 :(得分:3)
您未正确使用scanf
:
scanf(formatstring, address_of_destination,...)
是正确的方法。
修改强>
不,你不应该。请阅读不是scanf的原型:
int scanf(const char *format, ...);
所以我应该只用一个参数就可以使用它?
scanf
的文档; format
是一个字符串,用于指定scanf
应阅读的内容,...
是scanf
应将读入的内容。
答案 3 :(得分:1)
scanf的第一个参数是格式字符串。你需要的是:
scanf("%2s", readChars);
答案 4 :(得分:0)
它应该在scanf函数中提供格式说明符
char readChars[3];
puts("Enter the value of the card please:");
scanf("%s",readChars);
printf("%s",readChars);
printf("done");