我在将字符串(例如名称)保存到struct字段时遇到了一些问题。我曾使用过gets()
和fgets()
,但fgets()
也无法正常使用。
我从未有机会输入第一个员工姓名;它直接跳到员工代码,然后也跳过地址。出于某种原因,当输入第二个员工时,我会输入名称和代码,然后再次跳过该地址。
任何人都知道我做错了什么?
#include <stdio.h>
typedef struct {
char name[150];
int code;
char add[300];
} tEmployee;
int main()
{
printf("How many employees would you like to register?\n");
int n;
scanf("%i", &n);
tEmployee employee[n];
for (int i = 0; i < n; i++)
{
printf("Name: ");
gets(employee[i].name);
printf("Code: ");
scanf("%i", &employee[i].code);
printf("Address: ");
gets(employee[i].add);
printf("%s\n", employee[i].name);
printf("%i\n", employee[i].code);
printf("%s\n", employee[i].add);
}
return 0;
}
答案 0 :(得分:1)
C库输入例程与处理换行符的方式不一致(\ n)。有些人认为它是输入的一部分,有些人不这样认为。由于scanf()
在换行之前得到了它所需的内容,因此没有理由将其读入,所以我们必须明确地在下一次输入之前将其清除出缓冲区。有不同的技术,但只是调用getchar()
适用于此示例。
此外,由于gets()
被视为不安全,并且在输入结尾处悬挂了换行符,因此我添加了一个自定义my_gets()
修补程序包装器两个问题:
#include <stdio.h>
#include <string.h>
typedef struct {
char name[150];
int code;
char add[300];
} tEmployee;
char *my_gets(char *str, int size)
{
char *pos;
char *result = fgets(str, size, stdin);
if (result != NULL && (pos = strchr(str, '\n')) != NULL)
*pos = '\0';
return result;
}
int main()
{
int n;
printf("How many employees would you like to register?\n");
scanf("%i", &n);
getchar(); // eat newline \n
tEmployee employee[n];
for (int i = 0; i < n; i++)
{
printf("Name: ");
my_gets(employee[i].name, 150);
printf("Code: ");
scanf("%i", &employee[i].code);
getchar(); // eat newline \n
printf("Address: ");
my_gets(employee[i].add, 300);
printf("%s\n", employee[i].name);
printf("%i\n", employee[i].code);
printf("%s\n", employee[i].add);
}
return 0;
}
您可以针对scanf()
的特定用途制作类似的包装功能,为您使用额外的换行符,这样您每次调用该函数进行输入时都不必担心它。
答案 1 :(得分:0)
这是gets
和scanf
的混合使用。当我混合使用std::cin
和>>
运算符和std::getline
函数时,我在C ++中遇到了类似的问题。
此外,gets
已弃用,请勿使用...
无论如何,如果你真的想要使用两者,那么每次你使用scanf
时都应该“刷新”stdin,或者下次你读stdin时你会读到其余部分直到行结束(\n
)。
One way to do it,是在每个scanf
之后阅读到行尾:
/* define the function */
void flush()
{
while (getchar() != '\n');
}
然后在您的代码中使用它,如下所示:
printf("How many employees would you like to register?\n");
int n;
scanf("%i", &n);
flush();
tEmployee employee[n];
for (int i = 0; i < n; i++)
{
printf("Name: ");
gets(employee[i].name);
printf("Code: ");
scanf("%i", &employee[i].code);
flush();
printf("Address: ");
gets(employee[i].add);
printf("%s\n", employee[i].name);
printf("%i\n", employee[i].code);
printf("%s\n", employee[i].add);
}
return 0;
答案 2 :(得分:0)
试试这个:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[150];
int32_t code;
char add[300];
} tEmployee;
typedef uint_fast8_t bool_t;
/*****************************************************************************
* flush stdin... this should be standard but somewhy you need to reinvent
* it all the time...
*****************************************************************************/
static inline void flush_stdin()
{
char ch;
do {
ch = getchar();
} while ((ch != '\n') && (ch != EOF));
}
/*****************************************************************************
* reads a line of text from a stream.
*****************************************************************************/
static inline bool_t xio_fgetline(FILE *stream, char *linebuf, size_t szline)
{
fgets(linebuf, szline, stream);
// find last character.
char *lc = linebuf + strlen(linebuf) - 1;
// the only case when lc is a null is if the program memory
// has been altered. In this case, it should crash anyway.
// therefore I skip a nullcheck before chomping.
// chomp linebuf.
if (*lc == '\n') {
*lc = 0;
}
// string is {0} after chomping.
if (strlen(linebuf) == 0) {
return 0;
}
return 1;
}
/*****************************************************************************
* reads a line of text from stdin.
*****************************************************************************/
static inline bool_t xio_getline(char *linebuf, size_t szline)
{
return (xio_fgetline(stdin, linebuf, szline));
}
int main(int argc, char **argv)
{
int32_t n;
tEmployee *employee = (tEmployee *)0;
printf("How many employees would you like to register?\n");
scanf("%i", &n);
flush_stdin();
employee = (tEmployee *)malloc(n * sizeof(tEmployee));
for (int32_t i = 0; i < n; ++i) {
printf("Name: ");
xio_getline(employee[i].name, sizeof(employee[i].name));
printf("Code: ");
scanf("%i", &employee[i].code);
flush_stdin();
printf("Address: ");
xio_getline(employee[i].add, sizeof(employee[i].add));
printf("%s\n", employee[i].name);
printf("%i\n", employee[i].code);
printf("%s\n", employee[i].add);
}
free(employee);
return 0;
}