Disclaimer: I must use c++ 98
As part of a class assignment, I have been tasked to convert space-delimited strings into floats (then calculate a span with those floats, but that is irrelevant to my problem). The strings are coming from text files. If there are any discrepancies with the float, I am supposed to ignore it and consider it corrupted. For example, a text file could consist of a line that looks like this:
34.6 24.2 18.a 54.3 20.0 15.6
In this case, 18.a would simply be considered corrupt and no further manipulation has to be done to it.
Now, I am having a problem clearing my stringstream of corrupt data. For reference, here is my code:
#include <vector>
#include <limits>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
//Open file
ifstream infile("dataFile");
//Get all file input into a single string
string line;
string buffer;
while (getline(infile, buffer)) {
line += buffer + " ";
}
infile.close();
//Populate vector
float temp;
//I have tried to clear the stream with `data >> dummy` for
//both string and single char types below, but `data >> string`
//always clears too much, and `data >> char` doesn't seem to clear
//correctly either
//string dummy;
//char dummy;
vector<float> temps;
istringstream data(line);
while (data) {
//values between -100 and 100 are also considered corrupt
if (data >> temp && (temp <= 100 && temp >= -100)) {
temps.push_back(temp);
}
else if (!data.eof()) {
data.clear();
//trying to ignore all characters until I reach a space
//but that doesn't work correctly either
data.ignore(numeric_limits<streamsize>::max(), ' ');
//data >> dummy;
//cout << "Dummy: " << dummy << endl;
temps.push_back(-101.0);
}
}
//display resulting vector values
for(int i=0; i<temps.size(); ++i) {
cout << temps[i] << " ";
}
cout << endl;
}
My issue lies within the while (data)
loop, specifically, inside the else if (!data.eof())
block. When data >> temp (type float)
fails, the else if
block runs. I clear the consequential failbit
and attempt to ignore the remaining characters until the next space-delimiter comes up. However, a text file with a line like such:
a *a -100.1 100.1 a 10.a a 13-6s 12abc -12.a
produces problems. 13 and -6 are both processed as valid floats. I want to ignore the entire chunk of 13-6s
, because these values are intended to be space-delimited.
What is the correct way to deal with this istringstream
issue, where the characters are not being ignored the way I want?
I have been told by my professor that I can accomplish this with very basic STL techniques. He explicitly recommended to use stringstream
as a way to parse floats. Is he in the wrong here?
Please comment for further clarity, if needed; I've been at this for quite some time now and would much appreciate some help.
Thank you!
This should do what you need.
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::string temp;
// cin will write to temp with each space delimited entry
while (std::cin >> temp) {
std::stringstream s(temp);
float f;
// the first case checks if the actual write the float succeeds
// the second case checks if the entire stringstream has been read
if (!(s >> f) || !s.eof()) {
std::cout << temp << " failed!" << std::endl;
}
else {
std::cout << f << std::endl;
}
}
}
Apologies for not being able to answer your stringstream
question but this solution should remove any necessity for that.
Note that input of 34.6 24.2 18.a 54.3 20.0 15.6
returns an output of:
34.6
24.2
18.a failed!
54.3
20
15.6
Edit: I added a case to the if
statement to handle the stranger cases (i.e. 13-6s). It's a neat solution I found here.
Edit 2: I annotated some of the more complicated parts.