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