user69514
user69514

Reputation: 27629

C++ STD Cin error in while loop

Why when I entered the loop below and I type something the first instruction cmdstd:getline(std::cin,cmdInput); does not read the input entered. For instance if I entered "b 8" it should display "cmd is b 8", but it skips to the next read std::getline(std::cin, input); and displays "it is b" instead

while (editingMode == TRUE) {
    std::getline(std::cin, cmdInput); 
    istringstream cmdiss(cmdInput);
    cout << "you entered: " << cmdInput <<endl;
    if (cmdInput != "") {      
        copy(istream_iterator<string>(cmdiss), 
             istream_iterator<string>(), 
             back_inserter<vector<string> >(tokens));
        std::cout << "cmd is " <<tokens.at(0) << std::endl;
    }

    //*************************
    std::getline(std::cin, input);
    istringstream iss(input);
    if(input != ""){
        copy(istream_iterator<string>(iss), 
             istream_iterator<string>(), 
             back_inserter<vector<string> >(tokens));
        std::cout << "it is " << tokens.at(0) <<std::endl;
        createInstruction(tokens);
    }

Upvotes: 1

Views: 1995

Answers (4)

Roger Pate
Roger Pate

Reputation:

The problem is mixing >> extractions with getline, leaving a newline (or other input) in the buffer. Blindly using ignore will hide logic errors, such as input of "42 abc" followed by cin >> some_int; cin.ignore(...);. What you really have to do is "extract" the blank line:

int main() {
  using namespace std;
  int n;
  string s;

  cout << "Enter a number: "
  cin >> n >> blankline; // <---

  if (cin) {
    cout << "Enter a line of text: ";
    getline(cin, s);
  }

  if (!cin) {
    clog << "Sorry, I can't do that.\n";
    return 1;
  else {
    cout << "Input successful, now processing values: " << n << s << '\n';
  }
  return 0;
}

Thankfully, this is easy:

template<class C, class T>
std::basic_istream<C,T>& 
blankline(std::basic_istream<C,T>& s,
          typename std::basic_istream<C,T>::char_type delim) {
  if (s) {
    typename std::basic_istream<C,T>::char_type input;
    if (!s.get(input) && s.eof()) {
      s.clear(s.eofbit);
    }
    else if (input != delim) {
      s.putback(input);
      s.setstate(s.failbit);
    }
  }
  return s;
}

template<class C, class T>
std::basic_istream<C,T>& blankline(std::basic_istream<C,T>& s) {
  blankline(s, s.widen('\n'));
  return s;
}

Upvotes: 0

Thomas Padron-McCarthy
Thomas Padron-McCarthy

Reputation: 27652

Perhaps you have a newline character left in the input buffer, from an earlier input? This is a common error.

Lets say that your program first reads an integer with cin >> x, and then a line with getline(cin, cmdline). The user types an integer, followed by the ENTER key. The cin >> x will read the integer, but the ENTER key, interpreted as a newline character, will be left in the input buffer.

When your program then goes on to read a complete line with getline(cin, cmdline), it will read the very short line that consists of just that left-over newline character. This looks like the program "skips to the next read".

Upvotes: 3

Jonathan Graehl
Jonathan Graehl

Reputation: 9301

There's nothing wrong with the code. It just doesn't do what you think it should :) If you want to print the whole line entered rather than the first word, don't print tokens[0]; print the input line.

Both sections do the same thing:

  1. read a line into a string
  2. create an istream from that line
  3. read the words from that istream into an array of strings called 'tokens'
  4. print the first word

tokens.at(0) is the first word, obviously. check tokens.size() or iterate over tokens if you want to look for arguments like "8".

Upvotes: 1

just somebody
just somebody

Reputation: 19257

are you sure editingMode is TRUE?

Upvotes: 0

Related Questions