为什么我的程序在使用scanf后暂停?
#include<stdio.h>
#include<stdlib.h>
int main()
{
char *userInput;
userInput = (char*)malloc(sizeof(userInput));
printf("Commands:\n");
printf("\ta name - adds given name to list\n");
printf("\tr name - removes given name from list\n");
printf("\tp - prints out list\n");
printf("\te - exits\n");
printf("\n\nEnter a command: ");
scanf("%s\n",userInput);
printf("\nThe user input was: %s\n", userInput);
return 0;
}
予编译代码“GCC -std = gnu99 -m32 -Wall -g -o名称列表namelist.c” 每当我运行所有的第一个printf被显示在可执行文件和我得到提示上的输入。每当我输入的输入,然后按回车,我没有得到提示未来的printf直到我把另一个观点。。为什么我的程序在使用scanf后暂停?
只要采取了“\ n”在您的
scanf("%s\n",userInput)
OMG非常感谢你这是逼我疯了 – Programmer
那么您有超过4个字节,例如任何输入缓冲区溢出'foobar' –
@BasileStarynkevitch我相信,输入超过3个字符('\ 0'的最后一个字符)发生缓冲区溢出。这个:'malloc(sizeof(char *)) - 1'确切地说。 – babon
仔细阅读scanf(3)。注意,gcc -m32
你有sizeof(userInput)
等于4(所有指针的大小是相同的;没有-m32
它将是8)。因此,如果用户正在输入类似working
(或任何四个字符或更多字符的输入,而不是像a
这样的一个字母),则您有undefined behavior(因为buffer overflow),这实际上是bad。你可能应该考虑使用getline(3)来代替(或者甚至可以使用readline(3)),例如
char* userInput=NULL;
size_t sizeInput= 0;
printf("Commands:\n");
/// put your other printfs here, then
ssize_t lengthInput = getline(&userInput, &sizeInput, stdin);
if (lengthInput < 0 || userInput==NULL)
{ perror("input error"); exit(EXIT_NULL); };
现在,你必须在userInput
整个类型化线(包括终止换行符),你知道,它的长度为lengthInput
。您可以使用parse那行,也许使用sscanf(3)(提示:使用它的返回计数,并考虑使用%n
)或者只使用其他技术(某些strcmp
或strtok(3) ...)。完成后,您应该free(userInput)
。
请注意,scanf
(或sscanf
)不会为解析的数据分配任何内存,除非您使用%ms
(这可能是POSIX特定的)。与%s
它总是期待一些固定长度的缓冲区,并为阵列缓冲区宣布char buf[64];
你最好给与%63s
大小;顺便说一句,你应该总是测试结果计数scanf
。所以,你可能代码(以上)之后
char nambuf[64];
if (sscanf(userInput, "a %63s", nambuf)==1) {
// use nambuf to add it
}
else if (sscanf(userInput, "r %63s", nambuf)==1) {
// use nambuf to remove it
}
(不过上面是一个有点傻,我们读到一个任意大小的线,但在63个字节的过程nambuf
)。您可以使用scanf
,如if (scanf("a %63s", nambuf)==1)
,而不需要任何userInput
。
或者,你可以使用Linux特有的%as
或更好的POSIX特定%ms
像:
char* nameptr=NULL;
if (scanf("a %ms", &nameptr)==1) {
那么成功scanf
将有malloc
-ed和充满nameptr
建议您稍后free(nameptr)
。如果你想只接受小写字母考虑编码类似if (scanf("a %m[a-z]", &nameptr)==1)
等...
虽然字符(char
)或字符集(char*
)从stdin
未来具有相似功能的scanf
Enter键推\n
(结果)保持在缓冲区中。因此,下输入前程序应该清除该\n
以及所有其他的混乱,可以在输入缓冲区(如12asw
例如后不正确输入数字, - scanf
需要12
,并在缓冲区离开asw\n
)。
请看下面的例子,注意,我建议使用clnInpBuf()
:
#include <stdio.h>
void clnInpBuf()
{
char c;
while ((c = getchar()) != '\n' && c != EOF);
}
int main(void)
{
char str[10];
char ch;
scanf("%c", &ch);
fflush(stdin); // in some cases that works for input stream
// (but fflush is better to use only for output streams)
scanf("%9s", str);
clnInpBuf(); // this works always
printf("char was %c.\n", ch);
printf("string was %s.\n", str);
}
UPDATE:
为贵 “的命令处理器” 模板可以是:
int main(void)
{
char name[21];
char command;
while (1)
{
scanf("%c", &command);
clnInpBuf();
switch (command)
{
case 'a':
case 'r': scanf("%20s", name);
clnInpBuf();
printf("Command was:\n%c %s\n", command, name); // if ('a'==command) addRecord(name); else removeRecord(name);
break;
case 'p': // TODO: add output
break;
case 'e': return 0;
break; // this is not realy needed
default:
printf("Wrong command\n");
}
}
}
'fflush(标准输入)'是*错*,你只能'fflush'的*输出流*或'NULL' –
@BasileStarynkevitch是的,你说得对!...但我确实在某些情况下,写下了”那( fflush)的作品”和‘我推荐使用clnInpBuf()’ – VolAnd
由于userinput是指针,因此该语句将分配4个字节的数据。 userInput =(char *)malloc(sizeof(userInput));
由上述答案指出,这将导致缓冲区溢出当字符串大小大于3个字节。
#include <stdio.h>
#include <stdlib.h>
int main() {
// your code goes here
char *userinput = (char *)malloc(100);
fgets(userinput,100,stdin);
printf("%s",userinput);
return 0;
}
你给的唯一附加信息是使用'fgets'的建议。但是,你需要提供更多的代码。 –
为fgets添加了示例代码 – hariudkmr
使用'gdb'调试运行一步程序一步 -
也读字符串
示例代码时,我会建议在scanf函数与fgets()。 –
欢迎来到Stack Overflow! [请参阅此讨论,为什么不在'C'中投射'malloc()'和family的返回值。](http://stackoverflow.com/q/605845/2173917)。 –
提示:'\ n'用于回车。您是否在https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htm中看到任何'\ n'?的[scanf函数] –