提问人:Dat Tran 提问时间:4/30/2023 最后编辑:chqrlieDat Tran 更新时间:5/1/2023 访问量:87
Fgets 跳过第一个字符
Fgets skip first character
问:
当我将用户名作为输入并使用该信息执行另一项任务时,输出不包含第一个学生姓名的第一个字符。
int main() {
// Task1 - Enter student number
int i, number;
printf("Enter the number of students: ");
scanf("%d", &number);
getchar();
while (number > 1000) {
printf("Your number is too high. Maximum number of student is 1000. Please enter again: ");
scanf("%d", &number);
}
//Task2 - get student info
struct studentInfo students[number];
for (i = 0; i < number; i++) {
printf("\nEnter data for student %d:\n", i + 1);
printf("Enter student %d name: ", i + 1);
getchar(); // consume the newline character left in the input stream
fgets(students[i].fullName, sizeof(students[i].fullName), stdin); //use fgets instead of scanf
students[i].fullName[strcspn(students[i].fullName, "\n")] = 0; // Remove trailing newline
printf("Enter student %d ID: ", i + 1);
scanf("%s", students[i].ID);
printf("Enter student %d birthdate: ", i + 1);
scanf("%s", students[i].birthDate);
}
}
我已经更改并添加,但它仍然不起作用fgets
gets
getchar
答:
问题是在 之后,输入流中留下了一个换行符。使用 用于键盘输入是一个坏主意。请考虑改用 and。scanf("%d", ...)
scanf()
fgets()
sscanf()
例:
printf("Enter the number of students: ");
scanf("%d", &number);
将变为:
printf("Enter the number of students: ");
fgets(keyboard_line, 80, stdin);
sscanf(keyboard_line, "%d", &number);
您在顶部声明的位置keyboard_line
char keyboard_line[80];
main();
评论
"The problem is after scanf("%d", ...), a newline is left in the input stream."
getchar();
getchar();
fgets
char keyboard_line[80]; ... fgets(keyboard_line, sizeof keyboard_line, stdin);
问题是语句
scanf("%d", &number);
将在输入流上保留换行符,而语句
fgets(students[i].fullName, sizeof(students[i].fullName), stdin);
将读取包含换行符的整行输入(假设提供的内存缓冲区足够大,可以存储整行)。
您似乎试图通过使用语句来补偿在输入流上留下换行符的事实scanf
getchar();
在代码中的多个位置读取和丢弃换行符。但是,您没有正确地执行此操作。
如果用户在下面为语句输入数字1000
scanf("%d", &number);
然后你将执行该语句
getchar();
之后两次,因为该语句在您发布的代码中的两个位置。这意味着它可能会读取换行符以及用户下一行输入的第一个字符。
这就解释了为什么在第一个循环迭代中,缺少第一个字符。students[i].fullName
为了解决这个问题,我建议你总是有这个声明
getchar();
也
- 在每次函数调用后立即,或者
scanf
- 在每次函数调用之前。
fgets
您发布的代码中的问题是您正在混合执行两者。
请注意,解决方案 #2 仅在程序中的第一个语句是语句时才有效,因为如果第一个语句是语句,则没有要删除的换行符。出于这个原因,使用解决方案#1可能会更好。scanf
fgets
此外,使用语句
getchar();
仅当仅保留换行符时才有效。但是,如果用户输入scanf
6abc
则 的格式说明符将只匹配 ,但将保留在输入流上。在这种情况下,有必要呼叫四次而不是一次。%d
scanf
6
abc\n
getchar()
因此,通常最好改用以下循环:
int c;
do
{
c = getchar();
} while ( c != EOF && c != '\n' );
此循环可以缩短为以下两行:
for ( int c; ( c = getchar() ) != EOF && c != '\n' )
;
如果你在程序中多次使用它,那么简单地编写你自己的函数可能会更容易:
void discard_remainder_of_line()
{
int c;
do
{
c = getchar();
} while ( c != EOF && c != '\n' );
}
这样,你只需要写
discard_remainder_of_line();
在每句话之后。scanf
在使用 的结果之前始终检查 的返回值也会更安全。scanf
scanf
评论
while ( c != EOF && c != '\n' );
while ( c != '\n' && c != EOF);
'\n'
评论
#include
struct studentInfo
"the output does not contains first character of the first student name"
sscanf()
students[i].fullName
#include