我遇到了stdin缓冲区的问题,我很感激任何见解,我有这个函数接受用户输入的姓氏
void lastName(int *counter, User *pt) {
for (int i = *counter; i < (*counter + 1); i++) {
pt[i].lastName = calloc (MAX_LENGTH, sizeof(char));
printf("Enter Last Name: ");
fgets(pt[i].lastName, MAX_LENGTH, stdin);
strtok(pt[i].lastName, "\n");
}
}
我也有这个接受ID
用户输入的功能void id(int *counter, User *pt) {
char num[MAX_LENGTH];
long temp;
for (int i = *counter; i < *counter + 1; i++) {
printf("Enter the ID of %s: ", pt[i].firstName);
fgets(num, MAX_LENGTH, stdin);
strtok(num, "\n");
temp = strtol(num, NULL, 10);
pt[i].id = (int) temp;
}
}
这就是我在主要
中调用它们的方式lastName(&counter, pt);
id(&counter, pt);
如果我输入一个非常长的姓氏,它会被剪切并显示为MAX_LENGTH但是ID的fgets会被跳过,否则它会正常工作。我想知道我的fgets在这种情况下是如何工作的? MAX_LENGTH为10.我尝试用while(getchar()!='\ n')清除缓冲区;它有效,但我必须按两次输入。
Enter First Name: Test
Enter Last Name: Williamsamsmases
Enter the ID of Test: Would you like to enter a User?(Y/N):N
答案 0 :(得分:2)
如果输入的行长于目标缓冲区可以容纳的行,则fgets
将读取目标已满的所有内容。输入的其余部分保留在输入缓冲区中,因此下一个fgets
调用会读取已留下的内容。
如果目标缓冲区中不存在换行符,则有3个选项:
fgets
,直到换行符在缓冲区中。您可以使用此功能“清理”输入缓冲区:
void clean_stdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
然后当你意识到没有换行符时你可以调用它
目标缓冲区。但是每次拨打fgets
时都不要打电话给你,你只能这样做
当您知道输入中还有字符时调用此函数
缓冲区(当目标缓冲区中没有换行符时),
否则该功能将等待用户输入。
如果您的系统支持getline
,那么您可以使用它来阅读
整行和getline
将负责分配所需的内存
它:
char *line = NULL;
size_t n = 0;
if(getline(&line, &n, stdin) == -1)
{
// error
}
...
free(line);
如果您的系统上没有getline
,那么您可以编写一个函数
模仿getline
,如下所示:
char *fgets_long(FILE *fp)
{
size_t size = 0, currlen = 0;
char line[1024];
char *ret = NULL, *tmp;
while(fgets(line, sizeof line, fp))
{
int wholeline = 0;
size_t len = strlen(line);
if(line[len - 1] == '\n')
{
line[len-- - 1] = 0;
wholeline = 1;
}
if(currlen + len >= size)
{
// we need more space in the buffer
size += (sizeof line) - (size ? 1 : 0);
tmp = realloc(ret, size);
if(tmp == NULL)
break; // return all we've got so far
ret = tmp;
}
memcpy(ret + currlen, line, len + 1);
currlen += len;
if(wholeline)
break;
}
if(ret)
{
tmp = realloc(ret, currlen + 1);
if(tmp)
ret = tmp;
}
return ret;
}
此功能与fgets
类似,但它可以保证您阅读整个内容
在该行中,该函数负责为目标分配足够的内存。
答案 1 :(得分:1)
当您致电stdin
时,它会从int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
读取输入,直到插入的变量已满。一旦它,输入缓冲区上的其余输入仍然存在。一种解决方案是在读取每个值后清除输入缓冲区。
\n
您基本上是从缓冲区中读取并丢弃值,直到达到EOF
或Range
。