I am reading from a file, specifically BLS data in text files. Some of the metro names are long and so the data for that city extends to the next line. A snippet from the file:
999 26380 Houma-Thibodaux, LA 42 42 0 0 0 0 94
288 26420 Houston-The Woodlands-Sugar Land,
TX 4424 3046 4 0 1374 34 100
170 26580 Huntington-Ashland, WV-KY-OH 7 1 0 6 0 0 85
I need to save the ints after the state into vectors, so first am placing them into the string variables "total, one,..., per." I omitted the vectors I am placing them in for brevity. When the first two ints, the city, state, and next seven ints are on the same line (as they are for Houma and Huntington) my program works fine.
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main() {
ifstream BLS;
vector <string> cities = {"Houston-The Woodlands-Sugar Land"};
string city, state, total, one, two, three, five, struc, per, temp;
BLS.open("trial.txt");
if (BLS.is_open()) {
string line;
while(getline(BLS, line)) {
istringstream sin(line);
getline(sin, temp, ' ');
getline(sin, temp, ' ');
getline(sin, city, ',');
for (int i = 0; i < (int) cities.size(); i++) {
if (city == cities[i]) {
if (getline(sin, line) ) {
istringstream in(line);
in >> state >> total >> one >> two >> three >> five >> struc >> per;
}
else {
sin.ignore();
getline(sin, line);
istringstream in(line);
in >> state >> total >> one >> two >> three >> five >> struc >> per;
}
cout << " " << city << " " << state << " " << total << " " << five << endl;
}
}
}
}
}
As with Houston, the getline in the "if" statement is empty, so "else" executes. But I would expect sin.ignore() and getline(sin, line) again to then read the following line:
TX 4424 3046 4 0 1374 34 100
but it never does. getline(sin, line) seems to continue to read the empty line.
Any help would be massively appreciated.
Don't use
getlineIf the data are not structured cleanly into lines, then don't use
std::getline. At least, that is, not in this case.This solution uses a struct named
BLS_Table_3uto contain the information from one record. It requires that thecityfield does not contain any commas, and also that eachcityis followed by a comma, and then thestate. A scan of the data file on the BLS website confirms that these are valid assumptions.The struct defines
operator<<andoperator>>to handle I/O.operator>>reads one record from the data file, and stores the data it aBLS_Table_3ustruct. Similarly,operator<<writes the record stored in aBLS_Table_3ustruct.First, of course, you must open the file.
With the file successfully opened, you can read a record into a
BLS_Table_3ustruct like this. If you have reached the end-of-file, the read attempt will fail.More often than not, you will want to read the records in a loop. The test in the while-loop below is analogous to the test in the foregoing if-statement. The loop ends when you hit end-of-file.
When an error is detected by
operator>>, it throws astd::runtime_error. This might happen, for instance, if a field is missing, or non-numeric characters are encountered when a number was expected.The test program below simply copies the file onto the screen. This is the data file I used for testing.
And this is the complete test program. It contains the full definition for struct
BLS_Table_3u. This is the one you should copy.Output: