2016-05-13 41 views
0

我遇到了一些问题,例如将字符串(例如名称)保存到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; 
} 
+4

切勿使用'gets()'。 –

+4

[永远不要使用gets()](http://stackoverflow.com/q/1694036/10077)。 –

+1

还记得按下* scanf的*键吗?数字和输入?输入生成'\ n'。 'gets' /'fgets'消耗它,因此不等待进一步的输入。修复?在每个scanf后添加'getchar();'。 –

回答

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(),为您额外换行符,所以你不必担心它,每次你调用该函数的输入。

0

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