символы новой строки в scanf

Ниже я написал программу, которая пытается прочитать и распечатать значения структуры. Я думал, что scanf игнорирует /n для всех типов данных, кроме char, но когда я запускаю приведенную ниже программу и предоставляю первый ввод как целое число. Я не получаю o/p для имени переменной. Почему??

#include <stdio.h>
#include <string.h>
struct employee
{
    int empno;
    char name[10];
    float p_money;
};

int main()
{
    struct employee e;
    struct employee *ptr;
    ptr = &e;
    printf("please enter the empno \n");
    scanf("%d", &(ptr->empno));
    printf("please enter the name \n");
    gets(ptr->name);
    //scanf("%d", &(ptr->empno));
    printf("please enter the money \n");
    scanf("%f", &(ptr->p_money));
    printf("Roll No: %d\n", ptr->empno);
    printf("Name: %s\n", ptr->name);
    printf("Money: %f\n", ptr->p_money);
    getchar();
    return 0;
}

Исполнение:

please enter the empno
10 
please enter the name
please enter the money
100.99

Номер рулона: 10 Имя: Деньги: 100,989998

please enter the empno
10jackal
please enter the name
please enter the money
100.99

Свиток №: 10 Имя: шакал Деньги: 100,989998


person Kung-fu-panda    schedule 20.11.2013    source источник
comment
Что именно вы ожидаете от результата, который отличается от того, что вы получаете?   -  person John Zwinck    schedule 20.11.2013
comment
IMO, у вас не должно быть тега C++.   -  person Abhishek Bansal    schedule 20.11.2013
comment
По этому поводу уже есть ряд вопросов. Проблема в том, что scanf(%d) оставляет завершающий символ новой строки во входном буфере, а затем gets() считывает оставшийся символ новой строки как (очень короткую) строку.   -  person Thomas Padron-McCarthy    schedule 20.11.2013
comment
Хорошо. Я понимаю, что мне следует использовать fgets, чтобы избежать проблем, связанных с пробелами. Но в моем втором o/p, как первый printf узнает, что он должен прекратить печать после 10? Почему первый printf не продолжает печатать значение ascii «шакала»??   -  person Kung-fu-panda    schedule 20.11.2013
comment
!!НИКОГДА!! используйте 1_. Это зияющая дыра в безопасности. См. раздел на странице руководства: Никогда не используйте gets(). Поскольку невозможно сказать, не зная заранее данных, сколько символов будет считано функцией gets(), и поскольку функция gets() будет продолжать хранить символы после конца буфера, ее использование крайне опасно. Он использовался для взлома компьютерной безопасности. Вместо этого используйте fgets().   -  person ThiefMaster    schedule 20.11.2013


Ответы (2)


Проблема не в scanf, а в gets — вместо этого используйте fgets.

char * получает ( char * str );

gets - считывает символы со стандартного ввода (stdin) и сохраняет их в виде строки C в str до тех пор, пока не будет достигнут символ новой строки или конец файла.

person Sadique    schedule 20.11.2013
comment
Спасибо за ответ акме. Я понимаю, что scanf удалит любые символы новой строки, введенные с консоли. Итак, если я введу 10, а затем нажму Enter, не следует ли удалить '/ n'? И не должен ли я запрашивать ввод имени строки?? к сожалению, я не понимаю, почему моя программа не ведет себя таким образом. - person Kung-fu-panda; 20.11.2013
comment
should not /n be removed? Никакой даже scanf не удалит его автоматически - нужно быть осторожным при вводе символов. - person Sadique; 20.11.2013
comment
scanf удалит любые символы новой строки, введенные с консоли, неверно. Директивы/спецификаторы, такие как "%d" и "%f" и " ", будут потреблять (сканировать) символы новой строки. Это результат строки формата, а не встроенная функция scanf(). - person chux - Reinstate Monica; 20.11.2013
comment
Спасибо, acme и @chux. Не могли бы вы объяснить причину второго o/p? Когда я предоставляю 10jackal в качестве значения переменной int, переменная int принимает значение 10, а имя строки принимает значение jackal. как scanf знает, что он должен остановиться после чтения 10 и что второе значение jackal должно быть помещено в строку? почему переменная int не печатает значение 10 и значение ascii шакала? - person Kung-fu-panda; 21.11.2013
comment
@Kung-fu-panda При вводе клавиш 10jackal‹Enter› или в C 10jackal\n, scanf () не знает, что ему нужно остановиться на 0. Он переходит к j. scanf() знает, что ищет int из-за "%d", и, поскольку j не является частью int, он тайком помещает его обратно в stdin. Следующее зло gets() попадает в шакал\n, сохраняя только шакала. - person chux - Reinstate Monica; 21.11.2013

1использовать fgets вместо gets... gets плохо.

Причина, почему gets плохой:

gets Считывает символы со стандартного ввода до тех пор, пока не будет нажата enter (обнаружена новая строка).

В вашем случае name[10], а вы делаете gets(name). gets не знает, насколько велика цифра name... Если вы введете 9 символов, все в порядке. Но что, если вы введете более 9 символов? gets() продолжает записывать все char за пределы памяти, которая вам не принадлежит, что приводит к "Undefined Behavior"

person Community    schedule 20.11.2013