2016-05-13 2 views
0

У меня возникли проблемы с сохранением строки - например, имя - в поле структуры. Я использовал gets() и fgets() оба, но fgets() тоже не работает.Сохранение строк в structs с помощью 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's? Номер и ввод? Enter генерирует '\ n'. 'gets' /' fgets' потребляет его, поэтому не дожидается ввода furthur. Исправить? Добавьте 'getchar();' после каждого 'scanf'. –

ответ

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

Это ваше смешанное использование 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; 
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; 
} 
Смежные вопросы