2016-05-13 8 views
0

Ich habe Probleme mit dem Speichern einer Zeichenfolge - zum Beispiel eines Namens - in einem Strukturfeld. Ich habe gets() und fgets() beide verwendet, aber fgets() funktioniert auch nicht richtig.Speichern von Strings in Strukturen mit gets()?

Ich bekomme nie die Chance, den ersten Angestelltennamen einzugeben; es springt direkt zum Mitarbeitercode und überspringt dann auch die Adresse. Aus irgendeinem Grund kann ich bei der Eingabe des zweiten Mitarbeiters sowohl den Namen als auch den Code eingeben und dann die Adresse erneut überspringen.

Wer weiß, was ich falsch mache?

#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

Verwende niemals 'gets()'. –

+4

[Verwenden Sie niemals gets()] (http://stackoverflow.com/q/1694036/10077). –

+1

Denken Sie daran, * zwei * Tasten für die 'scanf's zu drücken? Die Nummer und die Eingabe? Enter erzeugt '\ n'. 'gets' /' fgets' konsumiert es und wartet somit nicht auf weitere Eingaben. Die Reparatur? Fügen Sie 'getchar();' nach jedem 'scanf' hinzu. –

Antwort

1

Die C-Bibliothek-Eingabe-Routinen sind nicht konsistent über die Art, wie sie Newline (\ n) behandeln. Einige lesen es als Teil der Eingabe, andere nicht. Da scanf() bekommt, was es vor dem Newline braucht, hat es keinen Grund es einzulesen, also müssen wir es explizit vor dem nächsten Input aus dem Buffer löschen. Es gibt verschiedene Techniken, aber nur Aufruf getchar() funktioniert für dieses Beispiel.

Da auch gets()unsicher betrachtet wird, und läßt eine neue Zeile am Ende Ihrer Eingabe baumelt, habe ich einen benutzerdefinierten my_gets() Wrapper hinzugefügt, die beiden Probleme beheben:

#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; 
} 

Sie eine machen könnten ähnliche Wrapper-Funktion für Ihre spezifische Verwendung von scanf(), die die zusätzliche Newline für Sie isst, so dass Sie sich nicht jedes Mal sorgen müssen, wenn Sie diese Funktion für die Eingabe aufrufen.

0

Es ist Ihre gemischte Verwendung von gets und scanf. Ich habe ähnliches Problem in C++, wenn ich die Verwendung von std::cin und >> Operator und std::getline Funktion gemischt.

Auch gets ist veraltet, verwenden Sie es nicht ...

Wie auch immer, wenn Sie wirklich die beide verwenden möchten, dann sollten Sie „flush“ stdin jedes Mal, wenn scanf, oder das nächste Mal verwenden Sie lesen stdin Sie werden den Rest bis zum Ende der Zeile (\n) lesen.

One way to do it, ist bis zum Ende der Zeile nach jeder scanf zu lesen:

/* define the function */ 
void flush() 
{ 
    while (getchar() != '\n'); 
} 

Dann verwenden Sie es in Ihrem Code wie folgt:

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

starten:

#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; 
}