Dec 1, 2011 at 6:07am UTC
i'm trying to read this data from a .txt file into arrays and some of the data is surrounded by bad data. for example: A6.75w (for a double variable). this is what i currently have but it crashes my program.
i know how to skip the bad data in the front but how do i skip the bad data after it? or am i just looping my code wrong??
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
ifstream in;
in.open("FinalData.txt" );
bool flag1 = true ;
bool flag2 = true ;
for (int count = 0; count < size; count++)
{
in >> fname[count] >> lname[count] >> initial[count] >> empid[count] >> state[count] >> zip[count];
while (flag1 == true )
{
in >> hours[count];
if (in.fail())
{
in.clear(); // i blocked out parts of the code to find
// out that the error is within these 2
// lines. (in.clear & in.ignore)
in.ignore(1,'\n' );
cout << "error" << endl; // just to show the error
}
else
{
flag1 = false ;
}
}
while (flag2 == true )
{
in >> rate[count];
if (in.fail())
{
in.clear();
in.ignore(1,'\n' );
cout << "error" << endl;
}
else
{
flag2 = false ;
}
}
flag1 = true ;
flag2 = true ;
}
thank you so much for the help!!!
Last edited on Dec 1, 2011 at 7:00pm UTC
Dec 1, 2011 at 5:29pm UTC
any help or tip would be greatly appreciated :/
Dec 1, 2011 at 6:46pm UTC
I turned your code into a little test program. I'm assuming there should only be 1 "hours" column? The first thing I would do would be to use exception handling to figure out why the read failed.
Does your program work when all the lines are good?
What is an a full-line example of bad data?
Dec 1, 2011 at 6:59pm UTC
yes there is only one hours column and the column after that is rate, which is the last column for each row ( know i put hours twice but i just reran it with the correction and i'm still getting a crash).
yes, the bad data isn't until 5 lines down so it saves all the previous lines with good data into the arrays just fine (i even recalled a value from a previous line and it displays correctly)
the first line of data that has bad data looks like this:
Tyree Ek E 100005 CA 90755 A60B 15.60
Dec 1, 2011 at 7:16pm UTC
This may get you one step closer. I added exceptions around your fstream. My example data isn't including the rate column, since your original code never read it. Now we can work in the read_hours method to figure out what the exception was, and "do the right thing"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
bool read_hours(ifstream& in, double &val) {
string input;
try {
in >> input;
for (int i = 0; i < input.size(); i++) {
if (input[i] != 0
&& ( (input[i] >= '0' && input[i] <= '9' )
|| input[i] == '.' )) {
// valid character
}
else {
input[i] = ' ' ;
}
}
stringstream s(input);
s >> val;
} catch (ifstream::failure e) {
if (in.eof()) {
cout << "End of file reached" << endl;
}
if (in.bad()) {
cout << "Badbit set" << endl;
}
if (in.fail()) {
// failbit set, possibly a bad number
cout << "Failbit set" << endl;
}
in.clear();
in.ignore(1,'\n' );
cout << "error" << endl; // just to show the error
return false ;
}
return true ;
}
int main(int argc, char * argv[]) {
ifstream in;
in.exceptions(ifstream::failbit | ifstream::badbit | ifstream::eofbit);
try {
in.open("FinalData.txt" );
}
catch (ifstream::failure e) {
cout << "Exception reading file" << endl;
return -1;
}
bool flag1 = true ;
bool flag2 = true ;
string fname[3];
string lname[3];
string initial[3];
string empid[3];
string state[3];
string zip[3];
double hours[3];
int size = 3;
for (int count = 0; count < size; count++)
{
try {
in >> fname[count] >> lname[count] >> initial[count] >> empid[count] >> state[count] >> zip[count];
}
catch (ifstream::failure e) {
if (in.eof()) {
cout << "End of file reached" << endl;
return 0;
}
in.clear();
in.ignore(1,'\n' );
cout << "error" << endl; // just to show the error
}
if (!read_hours(in, hours[count]))
return 0;
}
return 0;
}
Last edited on Dec 1, 2011 at 7:36pm UTC
Dec 1, 2011 at 7:48pm UTC
Here is a better implementation. This will only do the iteration through the strings characters if a problem is encountered first.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
bool read_bad_double(string input, double &val) {
try {
for (int i = 0; i < input.size(); i++) {
if (input[i] != 0
&& ( (input[i] >= '0' && input[i] <= '9' )
|| input[i] == '.' )) {
// valid character
}
else {
input[i] = ' ' ;
}
}
stringstream s(input);
s.exceptions(istream::failbit | istream::badbit | istream::eofbit);
s >> val;
} catch (istream::failure e) {
return false ;
}
return true ;
}
bool read_hours(ifstream& in, double &val) {
string input;
stringstream s;
try {
in >> input;
s.str(input);
s.exceptions(istream::failbit | istream::badbit | istream::eofbit);
s >> val;
} catch (istream::failure e) {
if (in.eof() || s.eof()) {
cout << "End of file reached" << endl;
}
if (in.bad() || s.bad()) {
cout << "Badbit set" << endl;
}
if (in.fail() || s.fail()) {
if (read_bad_double(input, val))
return true ;
// failbit set, possibly a bad number
cout << "Failbit set" << endl;
}
in.clear();
in.ignore(1,'\n' );
cout << "error" << endl; // just to show the error
return false ;
}
return true ;
}
int main(int argc, char * argv[]) {
ifstream in;
in.exceptions(ifstream::failbit | ifstream::badbit | ifstream::eofbit);
try {
in.open("FinalData.txt" );
}
catch (ifstream::failure e) {
cout << "Exception reading file" << endl;
return -1;
}
bool flag1 = true ;
bool flag2 = true ;
string fname[3];
string lname[3];
string initial[3];
string empid[3];
string state[3];
string zip[3];
double hours[3];
int size = 3;
for (int count = 0; count < size; count++)
{
try {
in >> fname[count] >> lname[count] >> initial[count] >> empid[count] >> state[count] >> zip[count];
}
catch (ifstream::failure e) {
if (in.eof()) {
cout << "End of file reached" << endl;
return 0;
}
in.clear();
in.ignore(1,'\n' );
cout << "error" << endl; // just to show the error
}
if (!read_hours(in, hours[count]))
return 0;
}
return 0;
}
Last edited on Dec 1, 2011 at 7:50pm UTC