我在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时,它会混合“名称”和“路径”,而不是剪切字符串。在某些情况下,它甚至将“路径”的一部分放入“名称”中。这是未定义的行为,还是我遗漏了什么?
答案 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个字符时,导致缓冲区溢出。
在这种特殊情况下,name
和path
在堆叠上分配,path
在name
之后。但是由于堆栈是自上而下的,如果您在path
中写更多内容,则可以在name
的空格中写入。
阅读维基百科Buffer overflow
答案 3 :(得分:1)
如果您不想遇到任何问题,请将scanf
字符串替换为:
fgets(name, 10, stdin);
其中第二个参数是数组的大小。即便如此,即使您尝试编写更多字符,也会被忽略。
答案 4 :(得分:1)
scanf不知道变量的大小(尤其是字符串变量)。它只是将字节放在一个内存空间中,你必须自己检查是否有溢出。
由于数据结构一致,没有段错误。
答案 5 :(得分:0)
它只是将Name重载到Path,因为它们占用了内存中彼此靠近的空间。
答案 6 :(得分:0)
使用scanf时应指定要读取的最大大小以避免缓冲区溢出:
scanf("%10s", name);