Hi guys/gals, I'm having a problem with a function that overloads the input stream. The problem is that the getline crashes on the second iteration of the while loop:

//overloaded input operator
istream& operator>>(istream& is, vector<EmailHeader>& ehVec)
{

  EmailHeader headerInput;
  cout << "Enter an email Header: Ctrl-D to quit" << endl;
  while(getline(is, headerInput.to))
    {
      getline(is, headerInput.from);

      // crash occurs after the user hits enter (second iteration)
      getline(is, headerInput.subject);

      is >> headerInput.Date.month;
      is >> headerInput.Date.day;
      is >> headerInput.Date.year;

      ehVec.push_back(headerInput);
      cout << "Enter another email Header: Ctrl-D to quit" << endl;
    }
  return is;
}

EmailHeader is a simple test class which holds string members for "From", "To", "Subject" fields and integer values for the dates.

I'm calling the overloaded input function from my main:

int main()
{
  vector<EmailHeader> emVec;

  cin >> emVec; 

  //other code
}

Any help and suggestions would be greatly appreciated. TIA.

Recommended Answers

All 6 Replies

I'm not entirely sure what the problem is, but something doesn't good in your code when you're mixing the getline() statements and in >> operators...

You see, when you use istream >> a_variable , it always leaves a trailing newline in the input stream. Then when you try to use getline(), you end up with a newline character instead of the input you expected to get.

The best solution would be to simply use all getline() statements instead of mixing them, however if you don't want to, you can simply clear the input buffer like this:

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

Hi JoeProgrammer, thanks for the prompt response. I basically wanted to read in 3 strings(with spaces) and 3 ints.

The getline() allows me to input a string with spaces where as the >> cuts it off before the first space character.

So I figured that I'd have to mix in order to get the desired results.

I didn't know the is >> variable always left a trailing newline though.

Thanks for your help. I'll try clearing out the input buffer.

Do you know of a better method of reading in the strings with spaces and ints?

This works, its essentially the same you had though. I added code to flush the keyboard buffer after each integer input. That may have been your problem.

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

class dt
{
public:
	int month,day,year;
	dt() {month = day = year = 0;}
};

class EmailHeader
{
public:
   string to;
   string from;
   string subject;
   dt Date;
};

//overloaded input operator
istream& operator>>(istream& is, vector<EmailHeader>& ehVec)
{
  EmailHeader headerInput;
  cout << "Enter an email Header: Ctrl-Z to quit" << endl;
  while(getline(is,headerInput.to))
  {
      getline(is, headerInput.from);
      getline(is, headerInput.subject); //crash occurs here on second iteration after the 
	  cout << "month: ";                                             // user hits the return key, so input below is skipped
      is >> headerInput.Date.month;
	  is.ignore();
	  cout << "day: ";
      is >> headerInput.Date.day;
	  is.ignore();
	  cout << "Year: ";
      is >> headerInput.Date.year;
	  is.ignore();

      ehVec.push_back(headerInput);
      cout << "Enter another email Header: Ctrl-Z to quit" << endl;
    }
  return is;
}

int main()
{
  vector<EmailHeader> emVec;

  cin >> emVec; 

  //other code
  return 0;
}

The getline() allows me to input a string with spaces where as the >> cuts it off before the first space character.

Well, yes I realized that. But many newbies don't realize the hidden gotchas of mixing functions which grab entire lines, such as fgets() and getline() with functions which simply scan for what they need, like cin >> and scanf().

cin >> works fine on its own, because although it leaves a trailing newline in the input buffer, it removes it when it reads next. So you can imagine this works perfectly until you use a function which reads until the first newline. Then you have problems.

The best thing to do is to only use cin >> when you know what you're doing (even though tons of online tutorials use it), so for most newbies it would in fact be much safer practice to only use getline() for grabbing their input.

Do you know of a better method of reading in the strings with spaces and ints?

The best method is to read in everything with getline(), and then parse out what you need from that. Although it sounds more complex, it's quite safe. And it's less complex if you pop that result into a string stream, which you can then safely use the >> operator without worrying about newlines.

JoeProgrammer: Thanks again for your suggestion and knowledge.

The initial method you'd posted that clears the input buffer did the trick:

char ch;
      while((ch=is.get()) != '\n' && ch != EOF);

For some reason, the other method you suggested didn't work though:

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

AncientDragon: thanks for your response as well. I tried using your method and it didn't work properly using GCC. It did work using DevC++(mingw compiler I beleive), so I'm not really sure why this happened, I can only attribute the erratic behavior to the different compilers.

-edit-

actually if I only use one "is.ignore()" then it does work using gcc. Thanks again!

I used VC++ 2005 Express to test your code.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.