0

I have a program where i read values from a file. The program will then count how many numeric values were succesfully read in the range 0.0-10.0 and how many were outside of range.

The program will also write to a file each time an error occurs, for instance when the read value contains anything else than numbers.

My problem is that the program crashes after 740 values has been read, value number 741 starts with a letter so i think the issue is that my program wont catch the exceptions and just crashes the whole program. It give me no error messages in the debugger. Not while compiling and not after the crash.

What is wrong with my exceptions (in 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
  • Stack Overflow isn't a free debugging service, and we expect you to show your attempts at debugging the code with a debugger or other simpler methods such as debug print statements. This won't be the only time you end up with a bug in your code, and learning to debug your programs will help you much more than having someone find the bug for you. http://idownvotedbecau.se/nodebugging/ – BessieTheCookie Apr 29 '18 at 19:38
  • @FeiXiang I dont get anything in my debugger... I use VS and the program compiles and runs but crashes at value 741, and no error codes in the debugger. – QifshaLopen Apr 29 '18 at 19:40
  • It doesn't tell you where the crash happened? There's no error message at all? Can you make a [minimal, complete, and verifiable example](https://stackoverflow.com/help/mcve)? – BessieTheCookie Apr 29 '18 at 19:40
  • @FeiXiang no, i only get a windows pop-up when the console crashes saying that Debug Error! - abort() has been called. But no errors in the debugger while compiling or after it crashes – QifshaLopen Apr 29 '18 at 19:41
  • @FeiXiang the program is very small, around 100 lines, so the minimal would be if i add the 4 other files. – QifshaLopen Apr 29 '18 at 19:46
  • Did You run the program in VS pressing F5? Then when a error occurs You should open the Debug > Windows > Call stack. Another way is to set the breakpoint on a line in the loop, right click and set a condition. – Robert Andrzejuk Apr 29 '18 at 20:06
  • Streams don't throw `bad_cast`, only `dynamic_cast` does. You can cut `readNextValue` down to three or four lines if you abandon the exception complications. – molbdnilo Apr 29 '18 at 20:07
  • @QifshaLopen Hallo QifshaLopen, I don't wanna demotivate you. But its true that when you post your entire project with a bug, its pretty hard for others to find it out or even hard to understand or give time for it. So please kindly, understand what exactly could be an minimal solution to your project/ program and paste here, so that we can just go through it quickly. – JeJo Apr 29 '18 at 20:07
  • @RobertAndrzejuk i am downloading another debugger and see if it finds more, thank you for your advice – QifshaLopen Apr 29 '18 at 20:09
  • Your use of `eof` is mistaken. Read about what `eof` means [here](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – molbdnilo Apr 29 '18 at 20:11
  • @JeJo yes thats why i didnt want to post the whole code, seems to much. Since i know when it crashes and not why, i thought that the DataFileReader.cpp would be enough but it wasnt. Its in that file that i have my exceptions, and im kind of sure the problem is there with the exceptions since it crashes at the first value that contains letters. – QifshaLopen Apr 29 '18 at 20:11
  • @molbdnilo ohh ok. I tried removing the exceptions but didnt help :/, thank you – QifshaLopen Apr 29 '18 at 20:15
  • @QifshaLopen *i am downloading another debugger* -- Are you using Visual Studio now? If so, why are you "downloading another debugger"? The debugger that comes with Visual Studio is one of, if not, the best debugger built for C++. – PaulMcKenzie Apr 29 '18 at 20:24
  • @PaulMcKenzie because it doesnt give me any errors even though my program crashes. – QifshaLopen Apr 29 '18 at 20:25
  • @QifshaLopen -- The debugger has no idea if your program is wrong or not -- only you know that. The debugger's job is to allow you to step through your program, watch variables, apply breakpoints and watchpoints to the program, etc. so that *you* can see where your program goes wrong. The debugger is not psychic and knows your intentions. Did you actually step through your program and apply breakpoints, or did you just say "run"? If you just ran your program, you didn't debug it. All you did was run the program at full speed using the debugger -- that is *not* debugging. – PaulMcKenzie Apr 29 '18 at 20:26
  • @PaulMcKenzie that is what i am trying to do with a new debugger, dont know hows its done on VS, i allways press "Debug" (F5), and it gives me errors of what is wrong. Ill google "breakpoints VS" and see how its done in VS. Thank you Paul – QifshaLopen Apr 29 '18 at 20:33
  • @QifshaLopen -- Did you try `F10`? That is how you single-step in the program. You should have seen a highlight on the first executable line of your program, waiting for you to step a line at a time. All `F5` does is run your program at full speed until a breakpoint is hit or your program terminates. – PaulMcKenzie Apr 29 '18 at 20:34
  • Try this: https://docs.microsoft.com/en-us/visualstudio/debugger/quickstart-debug-with-cplusplus – Robert Andrzejuk Apr 29 '18 at 20:39
  • @PaulMcKenzie yes i did no, was a lot of clicking til the error occured :'D. It was at the catcher for my exceptions at DataFileReader. Everything works fine in the loop until the first value that is not completely numeric(double) is read. – QifshaLopen Apr 29 '18 at 20:49

0 Answers0