У меня есть программа, где я читаю значения из файла. Затем программа подсчитает, сколько числовых значений было успешно прочитано в диапазоне 0,0–10,0, а сколько было вне диапазона.
Программа также будет записывать в файл каждый раз, когда возникает ошибка, например, когда значение чтения содержит что-то еще, кроме чисел.
Моя проблема заключается в том, что программа аварийно завершает работу после считывания 740 значений, значение с номером 741 начинается с буквы, поэтому я думаю, что проблема заключается в том, что моя программа не будет перехватывать исключения и просто аварийно завершает работу всей программы. Это не дает мне сообщений об ошибках в отладчике. Не во время компиляции и не после сбоя.
Что не так с моими исключениями (в DataFileReader.cpp)?
DataFileReader.h
#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
#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
#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
#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
#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 << "Numeric values read:\t" << vec.size() + rangeErrorCounter << endl;
cout << "Values outside of range:\t" << rangeErrorCounter << endl;
cout << "Total:\t\t\t" << summa << endl;
cout << "Avarage:\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