0
votes

My program should create a simple list: name(string), rating(int), watched/unwatched(string). I understand that using std::cin>> leaves an '\n' at the end so I have to use cin.ignore() but it seems it also fails the other way around somehow.

void write()
{
    int rating;
    string name, watch, wprint;
    cout << "Modifying" << endl;
    f_list.open ("TextFile.txt", ios::app);
    cout << "Name/Title?" << endl;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    getline(cin, name);
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cout << "Rating?" << endl;
    if (!(cin >> rating));
    {
        cin.clear();
        cout << "Error again" << endl;
    }
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cout << "Watched or unwatched?" << endl;
    getline(cin, watch);
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    if (watch == "w" || watch == "yes" || watch == "y")
    {
        watch = "W";
        wprint = "Watched";
    }
    else
    {
        watch = "DW";
        wprint = "Didn't watch";
    }
    cout << name << " (" << rating << "/10) (" << wprint << ") has been added to the list" << endl;
    f_list << name << " " << rating << " " << watch << endl;
}

First my cin >> rating was always zero, no matter what I did and it also returned errors and went in an infinite loop. Then I SOMEHOW fixed it but I dont know how and now my 2 getline()s need to be entered TWICE!

Could somebody explain why doesn't this work for me? And which parts of this code is unnecessary?

My input looks like this

2
std::getline doesn't leave the \n in the buffer, formatted extraction does! You're clearing the input. - LogicStuff
... the Q&A you feared to get your question flagged as duplicate of doesn't say call std::istream::ignore between every extraction. - LogicStuff

2 Answers

0
votes

You should not call std::istream::ignore() unless you really know that there is something to be ignored already in the buffer. If you call it with an empty buffer, it will first have to fill it up -- prossibly with otherwise useful data --, and then ignore everything.

0
votes

I understand that using std::cin>> leaves an '\n' at the end so I have to use cin.ignore()

The first part is true. The second part is true only if you want to follow it up with a call to getline.

However, you have calls to cin.ignore() even before the first call to std::cin >>. That will expect you to enter lines, which could be empty lines but lines nontheless, the lines will be read and discarded.

Replace the lines:

cin.ignore(numeric_limits<streamsize>::max(), '\n');
getline(cin, name);
cin.ignore(numeric_limits<streamsize>::max(), '\n');

with just

getline(cin, name);

Also a little bit later, you have:

getline(cin, watch);
cin.ignore(numeric_limits<streamsize>::max(), '\n');

You don't need the call to cin.ignore() here. Remove it.