as ever I'm fairly new to C++ and I'm not exactly up with the lingo yet either so I apologize for sounding vague in advance!
My problem is I'm struggling to see why my while loop seems to stop the rest of my methods in my overloaded operator function;
#include "sample.h"
#include <iostream>
#include <vector>
#include <cstdlib>
using namespace std;
sample::sample(vector<double> doubles){}
sample::sample() {}
ostream& operator<< (ostream &out, sample &sample)
{
out << "<" << sample.n << ":";
return out;
}
istream& operator>> (istream &in, sample &sample)
{
char firstChar;
in >> firstChar;
if(firstChar != '<'){
cout << "You've not entered the data in a valid format,please try again!1 \n";
exit(1);
}
int n;
in >> n;
sample.n = n;
char nextChar;
in >> nextChar;
if(nextChar != ':'){
cout << "You've not entered the data in a valid format,please try again!2 \n";
exit(1);
}
vector<double> doubles;
double number;
while (in >> number){
doubles.push_back(number);
cout << in << " " << number;
}
in >> lastChar;
return in;
}
int main(void)
{
sample s;
while (cin >> s){
cout << s << "\n";
}
if (cin.bad())
cerr << "\nBad input\n\n";
return 0;
}
My input would be something like;
<6: 10.3 50 69.9>
I'm trying to get all the doubles after the ':' into a vector, which I can do if they're ints but once a '.' is entered it seems to stop.
If I only put integers in, it also seems to stop after the while(in >> number) has finished finding all the numbers, which is fine but the cout<< command in my main function doesn't seem to work!
Where have I gone wrong?
2 Answers 2
You have to obey the standard stream idioms: every stream is implicitly convertible to a bool (or void pointer) to allow a check like if (in >> n) to see if the operation succeeded. So first of all you have to make sure that your operator conforms to this (by ensuring that the stream is "good" if the extraction succeeded).
Second, when you write a loop like while (in >> x) { /*...*/ }, then after the loop terminates, you already know that your stream is no longer good. So you'll have to call clear() on it before returning it.
Maybe something like this:
std::istream& operator>> (std::istream &in, sample &sample)
{
char c;
int n;
double d;
std::vector<double> vd;
if (!(in >> c)) { return in; } // input error
if (c != '>') { in.setstate(std::ios::bad); return in; } // format error
if (!(in >> n)) { return in; } // input error
if (!(in >> c)) { return in; } // input error
if (c != ':') { in.setstate(std::ios::bad); return in; } // format error
while (in >> d)
{
vd.push_back(d);
}
in.clear();
if (!(in >> c)) { return in; } // input error
if (c != '>') { in.setstate(std::ios::bad); return in; } // format error
state.n = n;
state.data.swap(vd);
return in;
}
Note that we only modify the sample object if the entire input operation succeeded.
3 Comments
clear just resets the error flags so that the next extraction operation will be performed at all (no extraction is performed on a stream with error).cout << in << " " << number;
you probably meant
cout << " " << number;
or something