ignoring bad data

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
any help or tip would be greatly appreciated :/
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?
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
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
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
Topic archived. No new replies allowed.