-3

i'm trying to build a sample app for my students which should demonstrate how to enter multiple c-strings using cin.getline and cin.ignore but i'm getting weird results. in my code below there are two commented cin.ignore statements. if i uncomment first one then in runtime it is required to press Enter twice to input the first string and only once to input the second. if i uncomment second one instead then both strings inputted with one Enter but second string somehow lose first letter.

#include <iostream>
using namespace std;

struct Unit{
    int uid;
    char* name=new char[50];
    char* shname=new char[10];
};

int main() {
    Unit u;
    cout << "Record number: ";
    cin >> u.uid;
    cout << "Unit name: ";
    cin.ignore();
    cin.getline(u.name,50);
    //cin.ignore();
    cout << "Unit short name: ";
    //cin.ignore();
    cin.getline(u.shname,10);
    cout << "Record number: " << u.uid << endl
         << "Unit name: " << u.name << endl
         << "Unit short name: " << u.shname << endl;
    return 0;
}

i cant quite understand what am i doing wrong

  • 2
    "what am i doing wrong" using `new` and C style strings, for starters. – n. m. could be an AI Dec 25 '18 at 09:06
  • 3
    Possible duplicate of [C++ iostream: Using cin >> var and getline(cin, var) input errors](https://stackoverflow.com/questions/18348350/c-iostream-using-cin-var-and-getlinecin-var-input-errors) – Alan Birtles Dec 25 '18 at 09:07
  • 1
    `getline()` reads up to and including the newline, so there should be no need to `ignore()`. What happens when both are commented out? – Ken Y-N Dec 25 '18 at 09:08

2 Answers2

1

cin.ignore() ignores only one character, no matter if it is white space or not.

I guess you want to ignore until the first non-white character.

For example:

while (iswspace(cin.peek()))
   cin.ignore();

And as said in the comment, getline will read also the end of line. you need to ignore it after use the stream operator (>>) because then it stop before the end of line and the first getline will read just the new line.

SHR
  • 7,940
  • 9
  • 38
  • 57
  • `cin.ignore(std::numeric_limits::max(), '\n');` – n. m. could be an AI Dec 25 '18 at 10:38
  • @n.m it depends, do you want to ignore valid input till the new line, or take the input in the current line. what about spaces before the value? do you want to start from the spaces or in the beginning of not-white characters? and what about lines longer than size? there is no single answer for all cases. – SHR Dec 25 '18 at 11:12
  • ok, i get it. i don't need to use ignore if i'm reading several strings using getline. i need to use it only if i mix >> and getline calls. thank you all for the help – Philipp Mastyaev Dec 25 '18 at 14:32
1

You’ll need to understand why it is sometimes necessary to use ignore()! The built-in formatted input pperations (operator>>()) use any space chararcter as a separator which is not extracted. On the other hand, getline() scans the input for the first occurance of the newline character (by default ’\n’) and stores and stores and extracts all those characters. It finishes with extracting the newline character (the variation you are using also has a size constraint; I’d recomend using std::string with the non-memeber std::getline()).

The net effect is that after a formatted input function the next character in the buffer is a separating space. When intaracting with a user using the standard input it is most likely a newline character which causes a following getline() to immediately finish. Thus, it is common that these space characters are extract, preferably using in >> std::ws rather than in.ignore() to deal with other stray space characters. After using getline() there is generally no need to skip any characters as the newline is already extracted. Put differently: the commented ignore()s are best removed.

Also, make sure you always verify the input was successful after trying to read! The vaste majority of errors with inout are due to no checking (as is the case in the code you posted) or checking before the input operations. Learning to check afterwards is sufficiently important that the argument of “making the code simple” doesn’t hold: it isn’t making the code simple but plain wrong!

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380