使用gets()将字符串保存到结构中?
问题描述:
我遇到了一些问题,例如将字符串(例如名称)保存到struct字段中。我已经使用gets()
和fgets()
,但fgets()
也无法正常工作。使用gets()将字符串保存到结构中?
我从来没有机会输入第一个员工的名字;它直接跳到员工代码,然后跳过地址。出于某种原因,输入第二名员工时,我输入姓名和代码,然后再次跳过地址。
任何人都知道我在做什么错了?
#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;
}
答
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()
,为您额外换行符,所以你不必担心它,每次你调用该函数的输入。
答
这是你的混合使用gets
和scanf
。我在C++中面临类似的问题,当我混合使用std::cin
和>>
运算符和std::getline
函数。
此外,gets
已过时,不使用它......
无论如何,如果你真的想都使用了,那么你就应该“刷新”下一次你使用scanf
每一次,或标准输入你读了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;
答
试试这个:
#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;
}
切勿使用'gets()'。 –
[永远不要使用gets()](http://stackoverflow.com/q/1694036/10077)。 –
还记得按下* scanf的*键吗?数字和输入?输入生成'\ n'。 'gets' /'fgets'消耗它,因此不等待进一步的输入。修复?在每个scanf后添加'getchar();'。 –