奇怪的行为scanf,字符串和C.

时间:2013-05-29 13:10:12

标签: 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: ");
scanf("%s",path);
printf("Name: %s\n", name);
printf("Path: %s\n", path);

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

7 个答案:

答案 0 :(得分:2)

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

scanf("%24s",path);

它应该防止char数组的缓冲区重载。

答案 1 :(得分:2)

您需要告诉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);

答案 2 :(得分:1)

当您尝试在name中编写超过10个字符且在path中编写超过25个字符时,导致缓冲区溢出。

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

阅读维基百科Buffer overflow

答案 3 :(得分:1)

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

fgets(name, 10, stdin);

其中第二个参数是数组的大小。即便如此,即使您尝试编写更多字符,也会被忽略。

答案 4 :(得分:1)

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

由于数据结构一致,没有段错误。

答案 5 :(得分:0)

它只是将Name重载到Path,因为它们占用了内存中彼此靠近的空间。

答案 6 :(得分:0)

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

scanf("%10s", name);