fgets из проблем с stdin

Я пишу программу, которая работает с файлами. Мне нужно иметь возможность вводить данные в виде структур и, в конце концов, читать их. Проблема, которую я сейчас имею в этом коде:

typedef struct { char* name; ..... }employeeRecord; employeeRecord record; char name[50]; if(choice == 1) { /*Name*/ printf("\nEnter the name:"); fgets(name,50,stdin); record.nameLength = strlen(name) -1; record.name = malloc(sizeof(char)*record.nameLength); strcpy(record.name,name); /*Other data, similar format...*/ 

Если я хочу, например, указать адрес и номер телефона, и спросить каждого в строке (так что адрес в значительной степени идентичен приведенному выше, за исключением замены «name» на адрес), я нахожу, что он пропускает ввод. Я имею в виду, что у меня нет возможности ввести его. На самом деле вывод: Введите имя: Введите адрес: (и здесь он запрашивает меня для ввода)

Я пробовал ваш код и не могу воспроизвести проблему. Следующий код работает так, как вы ожидали, он запрашивает имя, дожидается ввода имени, затем запрашивает адрес и т. Д.

Мне интересно, не нужно ли читать stdin и пустить его, прежде чем запрашивать больше ввода?

 typedef struct { char* name; char* address; }employeeRecord; int readrecord(employeeRecord &record) { char name[50]; char address[100]; printf("\nenter the name:"); fgets(name, sizeof(name), stdin); record.nameLength = strlen(name) + 1; record.name = malloc(sizeof(char)*record.nameLength); strcpy(record.name,name); printf("\nenter the address:"); fgets(address, sizeof(address), stdin); ... } 

Кстати, вы хотите добавить 1 к strlen (имя), а не вычесть 1. или, если вы хотите, чтобы имя было сохранено в вашей записи без завершающего нуля, вам нужно использовать memcpy для копирования строки в вашу запись, а не strcpy.

Редактировать:

Я вижу из комментариев, что вы используете scanf для чтения значения выбора, это оставляет \ n во входном буфере, который затем выбирается вашим первым вызовом fgets . Вместо этого вы должны использовать fgets для чтения в строке выбора, а затем sscanf для анализа значения вне ввода. как это

 int choice; char temp[50]; fgets(temp, sizeof(temp), stdin); sscanf(temp, "%d", &choice); 

это должно привести к тому, что вся проблема промывки stdin спорна.

Новая строка все еще находится в режиме stdin из предыдущего вызова функции, которая не читала новую строку с ввода. Очистите stdin , прочитав, пока вы не зачитали новую строку – не помыв stdin как предложили другие.

EDIT: Спасибо Alok, за исправление!

Вероятно, вы использовали scanf для чтения, прежде чем вызывать fgets для чтения имени. scanf возможно, оставил новую строку в stdin которую ваш код ошибочно вводит для ввода пустого имени. Если это действительно так, попробуйте не использовать scanf (используйте fgets для извлечения choice и используйте atoi для преобразования в int или strcmp для сравнения с «1 \ n» и т. Д.). В противном случае код должен работать, причем нижеуказанные изменения учитывают тот факт, что fgets также считывает завершающую новую строку в буфер (который вы, вероятно, хотите удалить):

  #define MY_LENOF(x) (sizeof(x)/sizeof((x)[0])) char choice[3] = { 0 }; /* example of how to initialize to all NULs */ if (!fgets(choice, MY_LENOF(choice), stdin)) { fprintf(stderr, "Premature end of input\n"); exit(1); } if (strcmp(choice, "1\n") == 0) { /*Name*/ printf("\nEnter the name:"); if (!fgets(name, MY_LENOF(name), stdin)) { /* if fgets fails it leaves name unchanged, so we reset it to "" */ name[0] = '\0'; } /* good practice to use srtnlen in order not to overrun fixed buffer */ /* not necessarily a problem with fgets which guarantees the trailing NUL */ size_t nameLength = strnlen(name, MY_LENOF(name)); assert(name[nameLength] == '\0'); if (nameLength - 1 > 0 && name[nameLength - 1] == '\n') { /* strip trailing newline */ name[--nameLength] = '\0'; } else if (nameLength >= MY_LENOF(name) - 1) { fprintf(stderr, "Name is too long\n"); exit(1); } else { fprintf(stderr, "Premature end of input\n"); exit(1); } record.nameLength = nameLength; record.name = malloc(sizeof(char)*(record.nameLength + 1)); strcpy(record.name, name);