这是我的代码。我不想用scanf()
来读取名称,我尝试使用fgets()
但是在我输入名字和年龄之后,我的程序第二次和第三次运行for循环时,它不需要年龄。
#include <stdio.h>
#include <string.h>
struct student
{
char name[15];
int age;
};
int main()
{
int i;
struct student s[A];
for (i = 0 ; i < A ; i++)
{
printf("enter the names and agen");
fgets(s[i].name, 10, stdin);
scanf("%d", &s[i].age);
}
printf("nn");
for (i = 0 ; i < A ; i++)
{
printf("%st%dn", s[i].name, s[i].age);
}
return 0;
}
它不起作用,为什么?
但是当我用
scanf("%s%d",s[i].name,&s[i].age);
它工作正常
fgets(( 和 scanf(( 之间的区别
fgets(...)
通常读取直到收到'n'
scanf("%d", ...)
通常:
1. 读取和丢弃前导空格。
2.读取数字输入(符号,数字(,直到扫描非数字。
3. 非数字被放回stdin
,用于下一个输入功能。
例:
J
o
h
n
Enter
"Johnn"
由fgets()
读成s[0].name
。
2
1
输入
21
被scanf("%d",...)
读成s[0].age
。 'n'
放回stdin
"n"
由fgets()
读成s[1].name
。
米
"M"
被scanf("%d",...)
阅读,则没有任何东西被放入s[1].age
。 'M'
放回stdin
.
a
r
y
输入
"Maryn"
被fgets()
读成s[2].name
。
1
9
输入
19
被scanf("%d",...)
读成s[2].age
。 'n'
放回stdin
"n"
由fgets()
读入s[3].name
。
替代方法:要读取 2 行,调用fgets()
两次,然后解析:
int Scan_student(struct student *dest) {
char buffer[2][80];
dest->name[0] = ' ';
dest->age[0] = -1;
printf("enter the names and agen");
for (int i=0; i<2; i++) {
if (fgets(buffer[i], sizeof buffer[i], stdin) == NULL) {
return EOF; // stdin was closed, no more input (or input error)
}
buffer[i][strcspn(buffer[i], "rn")] = ' '; // lop off potential trailing n
}
// parse the 2 buffers: MANY options here - something simple for now.
if (sscanf(buffer[0], " %14[-'A-Za-z ]", dest->name) != 1) {
return 0;
}
if (sscanf(buffer[1], "%d", &dest->age) != 1) {
return 0;
}
return 1;
}
int i;
struct student st[3];
for (i = 0 ; i < sizeof(st) / sizeof(st[0]) ; i++) {
if (Scan_student(&st[i]) != 1) break;
}
如果您在一行中同时输入名称和年龄,那么这是正常行为,因为fgets()
将读取整行,直到读取9
字节(在您的情况下(或找到'n'
。
您需要两者之一,例如,您只能使用这样的fgets()
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student
{
char name[100];
int age;
};
int main()
{
int i;
struct student s[1];
for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
{
char number[100];
char *unconverted;
printf("Name > ");
fgets(s[i].name, sizeof(s[i].name), stdin);
if ((unconverted = strchr(s[i].name, 'n')) != NULL)
*unconverted = ' '; // Remove the trailing 'n'
printf("Age > ");
fgets(number, sizeof(number), stdin);
s[i].age = strtol(number, &unconverted, 10);
if ((*unconverted != ' ') && (*unconverted != 'n'))
s[i].age = -1; // Invalid value indicating input error
}
for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
printf("Name: %snAge : %dn", s[i].name, s[i].age);
return 0;
}
或仅scanf()
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student
{
char name[100];
int age;
};
int main()
{
int i;
struct student s[1];
for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
{
printf("Name Age > ");
if (scanf("%99s%d", s[i].name, &s[i].age) != 2)
{
fprintf(stderr, "input errorn");
s[i].name[0] = ' ';
s[i].age = -1;
}
}
for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
printf("Name: %snAge : %dn", s[i].name, s[i].age);
return 0;
}
然后,您可以在一行中输入姓名和年龄。
fgets()
方法更好,因为您不需要处理scanf()
不会从stdin
中获取'n'
。如果您小心地强制用户在单独的行中输入值,则组合将起作用。
说实话,这里不需要 fgets((,因为您指定从 stdin 读取,您应该简单地使用 gets(( 默认情况下从 stdin 读取。如果你在scanf((语句和gets((语句之间移动,你应该使用fflush(stdin(来清除输入流,下面的示例:
scanf("%99s", s[i].name);
fflush(stdin);
gets(s[i].age);
一般来说,你最好坚持使用 scanf(( 或 gets((,而不是将它们组合在一起。