使用gets()将字符串保存到结构?

时间:2016-05-13 16:12:39

标签: c struct gets

我在将字符串(例如名称)保存到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;
}

3 个答案:

答案 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)

这是getsscanf的混合使用。当我混合使用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;
}