cin и getline пропускают ввод

ранее я отправил вопрос о пропуске ввода cin, и я получил результаты для сброса и использования istringstream, но теперь я перепробовал все возможные решения, но ни одно из них не работает.

вот мой код:

void createNewCustomer () {
    string name, address;

    cout << "Creating a new customer..." << endl;
    cout << "Enter the customer's name: "; getline(cin, name);
    cout << "Enter the customer's address: "; getline(cin, address);

    Customer c(name, address, 0);
    CustomerDB::addCustomer(c);

    cout << endl;
}

но я все еще получаю то же самое, пропуская ввод, и когда он принимает ввод, он берет их и сохраняет в имени пустое ничего, а в адресе берет то, что я написал в имени, но со 2-й буквы до конца

что не так с моим кодом?

Я пробовал cin.ignore(), cin.get() и cin.clear() все вместе и по отдельности, ни один из них не работал

РЕДАКТИРОВАТЬ:

основной метод в main.cpp вызывает только mainMenu()

void mainMenu () {
    char choice;

    do {
        system("cls");
        mainMenuDisplay();
        cin >> choice;
        system("cls");

        switch (choice) {
            case '1':
                customerMenu();
                break;

            case '2':
                dvdMenu();
                break;

            case '3':
                receiptMenu();
                break;

            case '4':
                outro();
                break;

            default:
                cout << '\a';
        }

        cin.ignore();
        cin.get();
    } while (choice != '4');
}

я выберу 1 для примера клиента, это customerMenu()

void customerMenu () {
    char choice;

    do {
        system("cls");
        manageCustomerMenu();
        cin >> choice;
        system("cls");

        switch (choice) {
            case '1':
                createNewCustomer();
                break;

            case '2':
                deleteCustomer();
                break;

            case '3':
                updateCustomerStatus();
                break;

            case '4':
                viewCustomersList();
                break;

            case '5':
                mainMenu();
                break;

            default:
                cout << '\a';
        }

        cin.ignore();
        cin.get();
    } while (choice != '5');
}

Я снова выбираю 1, чтобы создать новый объект клиента, который теперь перейдет к MainFunctions.cpp, который вызовет функцию createNewCustomer(), которая является первой.

void createNewCustomer () {
    string name, address;

    cout << "Creating a new customer..." << endl;
    cout << "Enter the customer's name: "; cin.getline(name,256);
    cout << "Enter the customer's address: "; cin.getline(address,256);

    Customer c(name, address, 0);
    CustomerDB::addCustomer(c);

    cout << endl;
}

person hakuna matata    schedule 11.05.2012    source источник
comment
Пожалуйста, покажите полный компилируемый пример. Если это сложно, пожалуйста, покажите хотя бы функцию, из которой эта функция вызывается.   -  person Benjamin Lindley    schedule 11.05.2012
comment
хорошо, я отредактирую вопрос, включив в него то, что чем-то напоминает трассировку стека и снимок экрана с примером   -  person hakuna matata    schedule 11.05.2012
comment
вы сказали, что пробовали cin.ignore. дай код, должно было сработать.   -  person J-16 SDiZ    schedule 11.05.2012


Ответы (4)


Если вы используете getline после cin >> something, вам нужно сбросить новую строку из буфера между ними.

Мой личный фаворит для этого, если не нужны символы после новой строки, — это cin.sync(). Однако это определяется реализацией, поэтому может работать не так, как у меня. Для чего-то твердого используйте cin.ignore(). Или используйте std::ws для удаления начальных пробелов, если это необходимо:

int a;

cin >> a;
cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n'); 
//discard characters until newline is found

//my method: cin.sync(); //discard unread characters

string s;
getline (cin, s); //newline is gone, so this executes

//other method: getline(cin >> ws, s); //remove all leading whitespace
person chris    schedule 11.05.2012
comment
sync() не предназначен для этого, хотя в некоторых случаях он может работать. Это не работает для меня. - person Benjamin Lindley; 11.05.2012
comment
@BenjaminLindley, у меня это всегда отлично работало. Можете ли вы найти документацию, в которой не предполагается очищать непрочитанные символы? - person chris; 11.05.2012
comment
я не использовал cin перед getline в функции createNewCustomer(), но он используется в функциях, вызывающих createNewCustomer(), как в mainMenu() и customerMenu() - person hakuna matata; 11.05.2012
comment
@aizen92, каждый раз, когда вы cin >> something, в буфере будет оставаться новая строка. Буфер остается, когда вы переключаете функции, пока вы все еще используете cin. Если следующей операцией с cin будет getline, она прочитает эту оставшуюся новую строку и, похоже, пропустит ввод. - person chris; 11.05.2012
comment
Я принесу вам ссылку на документ через минуту. А пока вам есть над чем подумать: ideone.com/7ICvn - person Benjamin Lindley; 11.05.2012
comment
я добавлял cin.sync() после каждого cin >> <something>, который я использовал, и это сработало, спасибо - person hakuna matata; 11.05.2012
comment
@BenjaminLindley, я понимаю вашу точку зрения, но, учитывая, как я использую GCC, может ли этот пример иметь какое-то отношение к тому факту, что вы вводите все данные заранее? Это как бы меняет логику таких вещей. - person chris; 11.05.2012
comment
Вот, пожалуйста. n3242, последний черновик C++11, §27.9.1.5/19 -- int sync() Эффекты: если область размещения существует, вызывается filebuf::overflow для записи символов в файл. Если область получения существует, эффект определяется реализацией. - person Benjamin Lindley; 11.05.2012
comment
@BenjaminLindley, ах вот оно. Я отражу это в своем ответе. - person chris; 11.05.2012
comment
@chris: Какую ОС ты используешь? - person Benjamin Lindley; 11.05.2012
comment
@BenjaminLindley, Windows работает на XP так же, как и на 7. - person chris; 11.05.2012
comment
@chris: Это объясняет разницу. Я не думаю, что имеет значение, что вы находитесь на GCC. Я предполагаю, но не уверен, что это как-то связано с тем, как Linux воспринимает все как файл. - person Benjamin Lindley; 11.05.2012
comment
@BenjaminLindley, это имело бы смысл. Я не слишком часто использую Linux, поэтому я не так хорошо знаком с ним. - person chris; 11.05.2012
comment
Что делать, если пользователь вводит более 80 символов в строке? Предпочтение: std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); - person Robᵩ; 11.05.2012
comment
@Robᵩ, я как бы оставил ограничение на количество символов, подразумеваемое в комментарии. Я также не читал подробно входной буфер. Я предпочитаю его для консоли, так как он короче, чем ignore(), и там достигается тот же эффект. Я согласен, что это не лучший выбор для файлов и, по-видимому, не для консолей, если код используется более чем в одном месте. - person chris; 11.05.2012
comment
@Rob: если ввод осуществляется с терминала, .sync() уничтожает оставшуюся часть строки. -- Для меня это не так. Результаты на моей машине точно такие же, как в примере, который я дал от ideone. То есть cin.sync() абсолютно ничего не делает. - person Benjamin Lindley; 11.05.2012
comment
@BenjaminLindley - Ваш опыт и дальнейшие исследования с моей стороны показывают, что мое предыдущее заявление было чушью. Я удаляю этот комментарий. К вашему сведению: gcc.gnu.org/bugzilla/show_bug.cgi?id= 46624#c1 - person Robᵩ; 11.05.2012
comment
@Robᵩ По этой причине мне всегда не нравился ignore(). Спасибо, что упомянули std::numeric_limits<std::streamsize>::max(). Я не знал об этом, и теперь я снова могу использовать ignore(). - person DuncanACoulter; 27.03.2014
comment
Спасибо, долго мучался с этим. - person Saheb; 05.01.2015
comment
cin.ignore() сработало для меня! - person mbaros; 23.01.2017

Структура вашего кода меню является проблемой:

cin >> choice;   // new line character is left in the stream

 switch ( ... ) {
     // We enter the handlers, '\n' still in the stream
 }

cin.ignore();   // Put this right after cin >> choice, before you go on
                // getting input with getline.
person jrok    schedule 11.05.2012
comment
Это сработало для меня довольно хорошо. - person Patrick Mutwiri; 15.03.2020

Здесь '\n', оставленный cin, создает проблемы.

do {
    system("cls");
    manageCustomerMenu();
    cin >> choice;               #This cin is leaving a trailing \n
    system("cls");

    switch (choice) {
        case '1':
            createNewCustomer();
            break;

Этот \n потребляется следующей строкой getline в createNewCustomer(). Вместо этого вы должны использовать getline -

do {
    system("cls");
    manageCustomerMenu();
    getline(cin, choice)               
    system("cls");

    switch (choice) {
        case '1':
            createNewCustomer();
            break;

Я думаю, это решит проблему.

person theharshest    schedule 11.05.2012
comment
Чтобы использовать getline, вам нужно изменить choice на строку, тогда его нельзя было бы использовать так в switch: вы могли бы использовать choice[0], но это скрыло бы ошибки (например, «11» будет обработано как 1, но это также case для принятой ошибки, которая игнорирует остальную часть строки. - person Tony Delroy; 15.09.2015

Я столкнулся с этой проблемой и решил эту проблему, используя getchar(), чтобы поймать ('\n') новый char

person user2135533    schedule 11.12.2014