1

I am creating a simple login program.

#include <iostream>
#include <string>
using namespace std;    

void showRegister()
{
    string user;
    string pw;
    cout << "Enter your username:";
    getline(cin, user);
    cout << "Enter your password:";
    getline(cin, pw);
    cout << "You have successfully registered!" << endl;
    writeIntoFile(user, pw);
    showMenu();
}
void showMenu() {
    int select;
    do {
        cout << "1. Register"<<endl;
        cout << "2. Login" << endl;
        cout << "3. Exit" << endl;
        cout << "Enter your choice: ";
        cin >> select;
    } while (select > 3);

    switch (select)
    {
    case 1:
        showRegister();
        break;
    case 2:
        showLogin();
        break;
    case 3:
    default:
        break;
    }
}

int main()
{
    showMenu();
    return 0;
}

This is the result when I choose 1: enter image description here

As you see, I can not enter username. In function showRegister(), when I add cin.ignore() before getline(cin, user), this is the result: enter image description here

As I understand, getline() reads a line until it reaches character \n and skip the rest. So why in this case, two successive getline() commands (getline(cin, user) and getline(cin, pw) lead to the fact that I can not enter username?

trangan
  • 341
  • 8
  • 22
  • I think the problem is your menu and this: [https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction](https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction) – drescherjm Sep 18 '21 at 14:10
  • @drescherjm: thanks for your answer. I have ready that article already. But I do not think it answers my question. Additionally, the user with the most upvotes has suggested that we should use `std::string age, name; std::getline(std::cin, age); std::getline(std::cin, name);`. I think that is what I used here, but it leads to no input.... – trangan Sep 18 '21 at 14:52
  • 2
    This is because you added a hidden character which is CR LF (in windows: '\n' '\r'). so when you call showRegister and will call getline() it will get the CR LF characters of the previous command (1) and not the username input – ol202020 Sep 18 '21 at 14:54

2 Answers2

2

The fact is getline takes input from buffer if something exists in buffer else it ask the user for value. What actually happens in your code is as soon as you enter value for select which is not greater than 3 it comes out of the loop after with a value you entered for select and the entered (which stands for \n) that you pressed get stored in buffer. So know when you come to getline for user it sees '\n' from the buffer as getline first check in buffer, so it skip the value insertion and buffer gets emptied and now when you come to getline that is used for password it ask the user for password as buffer was empty.

tx2
  • 724
  • 13
  • 26
2

This will happen always after an switch from a formatted input to an unformatted input. Like from std::cin >> select to std::getline

The formatted input will read your integer "select", but not the following CR LF. (You pressed the enter key).

To solve that problem, you can simply write:

    getline(cin >> std::ws, user);

std::ws will first consume the leading white space. Then the std::getline will work as expected.

Please read here about std::ws and do not forget to include <iomanip>

There are more severe bugs in your code. Like a cicrular call to "showMenu"

A M
  • 14,694
  • 5
  • 19
  • 44
  • Thank you very much! `cin >> std::ws` is actually new to me. And it worked as expected. I am still not clear why you say circular call to `showMenu` is a problem. That is actually what I meant to do. I wanted that after a register or login, we come back to the main menu. – trangan Sep 18 '21 at 16:19