Reading doubles from file, using exceptions to write to file

Hi everybody. I am writing a program that will take in values through inFile, all these values will be read as strings and converted to doubles. The range is 0.0 to 10.0, all values that cannot be converted will be written to a certain file "ReadErrors" and all values that are out of range will be written to "RangeErrors". To do this i am trying to implement exceptions.

The program is compiling and running even though it crashes after it has run to its end. Except the crash, the program only reads 700~ of my 20 000 values, and only finds 10 range errors even though there is around 200 of them.

What am I doing wrong?

DataFileReader.H
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
#ifndef DataFileReader_H
#define DataFileReader_H

#include <string>
#include <iostream>
#include <fstream>

using namespace std;

template <typename T>
class DataFileReader {

private:
	string dataFileName;
	string errorFileName;
	ifstream& dataFileStream;
	ofstream& errorFileStream;

public:
	DataFileReader(string aDataFileName, string aErrorFileName) : dataFileName(aDataFileName), errorFileName(aErrorFileName), dataFileStream(*(new std::ifstream(""))), errorFileStream(*(new std::ofstream(""))) {};
	/* pre: A file named aDataFile contains values to read. */
	~DataFileReader() { dataFileStream.close(); errorFileStream.close(); }
	/* post: Files are closed */
	void openFiles(); // throw (runtime_error);
					  /* post: An input stream from the file named aDataFile and an output stream to the file named aErrorFile are opened.
					  If either of these operations fails a runtime_error exception is thrown. */
	bool readNextValue(T &aValue);
	/* pre: openFiles has been successfully called.
	post: If a value has been successfully read, aValue holds that value and true is returned.
	Else, the read operation encountered an end-of-file and false is returned. */
};

#endif 


DataFileReader.cpp
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
#include "DataFileReader.h"
#include <iostream>
#include <ostream>
#include <typeinfo>
#include <istream>
#include <sstream>

template <typename T>
void DataFileReader<T>::openFiles() {
	dataFileStream.open(dataFileName);
	errorFileStream.open(errorFileName, ios::app);
	if (!(dataFileStream.is_open() && errorFileStream.is_open()))
		throw(runtime_error("Couldn't open at least one of the files."));
}

template <typename T>
bool DataFileReader<T>::readNextValue(T &aValue) {
	ios_base::iostate mask = ios::eofbit | ios::failbit | ios::badbit;
	dataFileStream.exceptions(mask);
	while (true) {
		string readValue;
		try {
			if (!(dataFileStream >> readValue)) // did I/O fail?
				return false;
			istringstream iss(readValue);
			if (!(iss >> aValue)) // did parsing fail?
				return false;
			return iss.eof(); // was the entire value consumed?
		}
		catch (bad_cast &bc) {
			errorFileStream << readValue << " - " << bc.what() << endl;
		}
		catch (ios_base::failure &eo) {
			if (dataFileStream.eof())
				return false;
		}
	}
}


DataFilter.H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef DataFilter_H
#define DataFilter_H
#include "DataFileReader.h"

template <typename T>
class DataFilter {

private:
	DataFileReader<T> fileReader;
	T min, max;

public:
	DataFilter(DataFileReader<T> *aReader, T aMin, T aMax) : fileReader(*aReader), min(aMin), max(aMax) {};
	/* pre: aReader points to an instance of DataFileReader<T> for which openFiles() has been succesfully called. */
	bool getNextValue(T &aValue); // throw (range_error); 
								  /* pre: an earlier call to getNextValue() has not returned false.
								  post: true is returned if aValue holds a value read from aReader. If a value could not be read, false is returned.
								  If a value is read but is not within the interval specified by aMin and aMax parameters to the constructor, a range_error exception is thrown. */
};

#endif



DataFilter.cpp
1
2
3
4
5
6
7
8
9
10
11
#include "DataFilter.h"

template <typename T>
bool DataFilter<T>::getNextValue(T &aValue) {
	if (fileReader.readNextValue(aValue)) {
		if (aValue > max || aValue < min)
			throw(range_error("Outside of range"));
		return true;
	}
	return false;
}


DataTestClass.cpp
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
#ifndef DataTestClass_H
#define DataTestClass_H

#include "DataFilter.cpp"
#include "DataFileReader.cpp"
#include <iostream>
#include <fstream>
#include <string>
#include <exception>
#include <vector>

//---------------------------------------------------------------------------

vector<double> vec;
int rangeErrorCounter = 0;

void printResults() {
	double summa(0), medel(0);
	vector<double>::iterator first, last, it;
	first = vec.begin();
	last = vec.end();
	for (it = first; it != last; ++it)
		summa += *it;
	medel = summa / vec.size();

	cout << "Lästa numeriska värden:\t" << vec.size() + rangeErrorCounter << endl;
	cout << "Värden utanför intervallet:\t" << rangeErrorCounter << endl;
	cout << "Summa:\t\t\t" << summa << endl;
	cout << "Medelvärde:\t\t" << medel << endl;
}

int main(int args[])
{
	DataFileReader<double> dr("Values.dat", "ReadErrors.dat");

	try {
		dr.openFiles();
	}
	catch (runtime_error &rt) {
		cout << "Error reading files: " << rt.what() << endl;
		return 0;
	}

	DataFilter<double> df(&dr, 0.0, 10.0);
	ofstream os("RangeErrors.dat");

	if (os.is_open())
		while (true) {
			double value;
			try {
				while (df.getNextValue(value))
					vec.push_back(value);
				printResults();
				os.close();
				return 0;
			}
			catch (range_error) {
				rangeErrorCounter++;
				os << value << endl;
			}
		}
	else
		cout << "Couldn't open RangeErrors.dat" << endl;
}

#endif 
Topic archived. No new replies allowed.