C语言scanf复制额外的字符串 #包括 #包括 int main() { charx[5]; chary[10]; scanf(“%s”,x); scanf(“%s”,y); printf(“%s%s”,x,y); }

C语言scanf复制额外的字符串 #包括 #包括 int main() { charx[5]; chary[10]; scanf(“%s”,x); scanf(“%s”,y); printf(“%s%s”,x,y); },c,C,我在终端中输入了“hello world”,但printf结果是“helloworld world”。 我做错什么了吗?永远,永远,真的永远不要使用“%s”格式说明符(没有宽度)来告诉scanf()它可以将多少字符放入参数指向的内存中 #include <stdio.h> #include <string.h> int main() { char x[5]; char y[10]; scanf("%s",x); scanf("%s",y);

我在终端中输入了“hello world”,但printf结果是“helloworld world”。
我做错什么了吗?

永远,永远,真的永远不要使用
“%s”
格式说明符(没有宽度)来告诉
scanf()
它可以将多少字符放入参数指向的内存中

#include <stdio.h>
#include <string.h>
int main()
{
    char x[5];
    char y[10];
    scanf("%s",x);
    scanf("%s",y);
    printf("%s %s",x,y);
}

C中的字符串以空字节结尾。所以字符串“hello”实际上需要存储6个字节:5个用于“hello”中的字母,1个用于空字节

变量
x
只有5个字节宽,因此它不够大,无法存储字符串“hello”。因此,尝试将此字符串写入
x
时会写入超过数组末尾的内容。这将调用,在本例中表现为写入相邻变量

增加
x
的大小以防止阵列溢出。还应在格式说明符中使用字段宽度来指定要读取的最大字符数:

char str[5];
scanf("%4s", str);
当你申报时

char x[6];
char y[10];
scanf("%5s",x);
scanf("%9s",y);
在内存中,您有如下内容:

char x[5];
char y[10];
在第一次
scanf
之后,您将
hello\0
写入
x

                     1 1 1 1 1 
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 
+---------+-------------------+
|. . . . .|. . . . . . . . . .| 
+---------+-------------------+
 ^         ^
 \-- x     \-- y
在第二次
scanf
之后,在
y

                     1 1 1 1 1 
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 
+---------+-------------------+
|h e l l o|0 . . . . . . . . .| 
+---------+-------------------+
当您键入printf(“%s”,x)时您要求键入以从
x
写入 第一个
\0
,因此打印
“helloworld”

当您键入
printf(“%s”,y)时
您要求键入以从
y
写入 第一个
\0
,因此打印
“世界”

注:

内存安排是不确定的,你应该有各种其他的结果,甚至崩溃


你可以在这里找到一个很好的使用scanf的教程:

我仍然很好奇为什么它不在第二个“l”之后终止,比如打印“hell”(是的,这不是故意的),因为它是未定义的行为。这里没有什么有意义的“为什么”。任何事情都有可能发生。我看不出它为什么会在“第二个l之后”终止。对字符串使用scanf,即使使用宽度说明符,也有多频繁的意义?@supercat每年2到3次。在输入行可能包含或可能不包含空格字符的情况下,如何确保明智的行为?@supercat不使用
scanf()
在这种情况下。@supercat我不确定我是否在跟踪你。
                     1 1 1 1 1 
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 
+---------+-------------------+
|h e l l o|w o r l d 0 . . . .| 
+---------+-------------------+