Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
奇怪的行为scanf、strings和C_C_String_Scanf - Fatal编程技术网

奇怪的行为scanf、strings和C

奇怪的行为scanf、strings和C,c,string,scanf,C,String,Scanf,我对C中的一些代码有问题: char opt, name[10], path[25]; printf("Things\nMore things\n"); printf("Even more things\n"); printf("\nChar: "); scanf("\n%c",&opt); printf("\nTask name: "); scanf("%s",name); printf("Name: %s\n", name); printf("\nFolder name: "); s

我对C中的一些代码有问题:

char opt, name[10], path[25];
printf("Things\nMore things\n");
printf("Even more things\n");
printf("\nChar: ");
scanf("\n%c",&opt);
printf("\nTask name: ");
scanf("%s",name);
printf("Name: %s\n", name);
printf("\nFolder name: ");
scanf("%s",path);
printf("Name: %s\n", name);
printf("Path: %s\n", path);

这是在“干净”模式下制造麻烦的代码。问题是,当数据大小大于10或25时,它将混合“名称”和“路径”,而不是剪切字符串。在某些情况下,它甚至将部分“路径”放在“名称”中。这是一种未定义的行为,还是我遗漏了什么?

它只是将名称重载到路径,因为它们彼此相邻地占用内存空间。

当您尝试在
Name
中写入超过10个字符,在
Path
中写入超过25个字符时,会导致缓冲区溢出

在这种特殊情况下,
name
path
在堆栈上分配,
path
name
之后。但由于堆栈是自上而下的,如果您在
路径中写入更多内容,则可以将
名称
写入空格


阅读维基百科

如果您不想有任何问题,请将字符串的
scanf
替换为:

fgets(name, 10, stdin);

其中第二个参数是数组的大小。这样,即使您尝试写入更多字符,它们也会被忽略。

如果您想将用户输入限制为精确的字符数,请尝试

scanf("%24s",path);

它应该可以防止字符数组的缓冲区过载。

使用scanf时,应该指定要读取的最大大小,以避免缓冲区溢出:

scanf("%10s", name);

scanf不知道变量的大小(尤其是变量字符串)。它只是将字节放入内存空间,您必须自己检查是否存在溢出


由于数据结构对齐,没有SEGFULT。

您需要告诉
scanf
您的输入字符串可以占用多少字节。您还需要告诉
scanf
放弃直到行尾的所有输入。由于提示不会以换行结束,因此应该刷新输出

printf("\nChar: ");
fflush(stdout);
scanf("\n%c%*[^\n] ",&opt);
printf("\nTask name: ");
fflush(stdout);
scanf(" %9[^\n]%*[^\n] ", name);
printf("\nFolder name: ");
fflush(stdout);
scanf(" %24[^\n]%*[^\n] ", path);

是的,正如您所怀疑的,在数组末尾写入是未定义的行为。scanf没有自动“阵列满时停止读取”。当它不知道数组的大小时,它怎么能这样做呢?有一些方法可以将格式更改为例如
%10s
,以解决此问题,但规则是令人讨厌的。阅读您友好的scanf手册页!PS:换行符应该在printf字符串的末尾,而不是开头;否则,标准输出流可能不会被刷新,您将等待提示。(或添加fflush(stdout))。这与使用(*)scanf系列中的函数时有关溢出的其他问题非常相似,例如。此解决方案有效,但在按enter键显示输入结束时会出现奇怪的情况,因此我将应用Pablo Lemurr发布的解决方案,这就足够了。谢谢谢谢你的解决方案,虽然不完美,但对我来说已经足够了!