你好我正在创建一个包含用户列表的简单程序(基于下面的结构),我正在尝试根据用户输入创建新用户,我在其中分别使用 scanf
请求每个属性.但是我在结构限制方面遇到了麻烦,例如 id 最多应该有 10 个字符,nome 最多可以有 25 个字符。这是我的代码以获得更多上下文:
struct user {
char id[10];
char name[25];
char group;
float score;
};
struct user list[25];
int registered = 0;
void createNewUser() {
struct user *userPtr, newUser;
userPtr = &newUser;
printf("\nId: ");
scanf("%10s", &(*userPtr).id);
printf("\nName: ");
scanf("%25s", &(*userPtr.name);
printf("\nGroup: ");
scanf("%c", &(*userPtr).group);
printf("\nScore: ");
scanf("%f", &(*userPtr).score);
insert(newUser);
printf("%10s\n", list[0].id);
printf("%25s\n", list[0].name);
printf("%c\n", list[0].group);
printf("%.1f\n", list[0].score);
}
void insert(struct user newUser) {
if (registered < 25){
list[registered] = newUser;
registered += 1;
}
}
使用我上面提供的代码,如果我在第一个输入中键入超过 10 个字符,则接下来的 2 个将被忽略。而我的第 3 个 scanf 总是被忽略,那个是针对组的。这里有人可以帮我解决这个问题吗?
最佳答案
scanf
的问题在于,当它停止转换字符并且有
输入缓冲区中有更多字符(因为用户输入的字符多于您的预期),然后 scanf
会将这些字符留在那里。
特别是换行符(当用户按下 ENTER 时输入)
保留在输入缓冲区中,这会导致后续调用出现问题
scanf
读取字符或字符串。所以在这种情况下你必须“清理”输入缓冲区,
这样下一个 scanf
就不会消耗前一个 scanf
调用的剩余部分。
你可以在每次scanf
之后使用这个函数:
void clean_stdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
然后你可以这样做:
printf("\nId: ");
scanf("%10s", (*userPtr).id); // no need for &, id is char[]
clean_stdin();
printf("\nName: ");
scanf("%25s", (*userPtr).name); // same here
clean_stdin();
printf("\nGroup: ");
scanf("%c", &(*userPtr).group);
clean_stdin();
printf("\nScore: ");
scanf("%f", &(*userPtr).score);
另请注意,如果 ID 的最大长度为 10,则您的方式
缓冲区的长度必须为 11,因为在 C 中你需要用
'\0'
-终止字节。因此,将您的结构更改为:
struct user {
char id[11];
char name[26];
char group;
float score;
};
还要记住,使用这样的指针
struct user *userPtr, newUser;
userPtr = &newUser;
printf("\nId: ");
scanf("%10s", (*userPtr).id);
...
不是必需的,它实际上使代码更难阅读。你可以这样做:
void createNewUser() {
struct user newUser;
printf("\nId: ");
scanf("%10s", newUser.id);
clean_stdin();
...
printf("\nScore: ");
scanf("%f", &newUser.score);
...
}
关于c - 使用 scanf 创建新的结构对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49713566/