0

So this is a program I wrote for a CS lab in my class. It was modified so that it would take in input from a text file and output to another text file. After it does the calculations, it asks the user if they want to rerun the program, which is just a while loop in main. Why do I get this error when I the program reruns?

Thread 1: EXC_BAD_ACCESS (code=1, address=0x7ffeb1d82bc8)

it occurs at this line in the getPints function:

bloodInFile >> a[i];

#include <iostream>
#include <string>
#include <iomanip>
#include <math.h>
#include <fstream>

using namespace std;

const int MAX_HOURS = 7;

void getPints(double a[], int h);
double getAverage(double a[], int h);
double getHigh(double a[], int h);
double getLow(double a[], int h);
void displayInfo(double a, double b, double c);

int main()
{
    string again = "yes";
    double pints[MAX_HOURS];
    double getHigh(double pints[], int MAX_HOURS);

    while (again == "yes")
    {
        getPints(pints, MAX_HOURS);
        getHigh(pints, MAX_HOURS);
        displayInfo(getAverage(pints, MAX_HOURS), getHigh(pints, MAX_HOURS), getLow(pints, MAX_HOURS));

        cout << "Do you want to run again (yes or no)? ";
        cin >> again;
    }

    return 0;
}

void getPints(double a[], int h)
{
    int i;
    ifstream bloodInFile;

    bloodInFile.open("bloodDrive.txt");

    if (!bloodInFile)
        cout << "Cannot open file." << endl;

    while (!bloodInFile.eof())
    {
        bloodInFile >> a[i];
        i++;
    }

    bloodInFile.close();
}

double getAverage(double a[], int h)
{
    int i;
    double totalPints = 0;
    double averagePints;

    for (i = 0; i <= h - 1; i++)
        totalPints = totalPints + a[i];
    averagePints = totalPints / i;

    return averagePints;
}

double getHigh(double a[], int h)
{
    int i;
    double highest = a[0];

    for (i = 1; i < h; i++)
    {
        if (a[i] > highest)
            highest = a[i];
    }

    return highest;
}

double getLow(double a[], int h)
{
    int i;
    double lowest = a[0];

    for (i = 1; i < h; i++)
    {
        if (a[i] < lowest)
            lowest = a[i];
    }

    return lowest;
}
void displayInfo(double a, double b, double c)
{
    ofstream bloodOutFile;

    bloodOutFile.open("bloodResults.txt");

    bloodOutFile << "Average pints: " << setprecision(1) << showpoint<< fixed << a << endl;
    bloodOutFile << "Highest pints: " << setprecision(1) << showpoint<< fixed << b << endl;
    bloodOutFile << "Lowest pints: " << setprecision(1) << showpoint<< fixed << c << endl;
}
  • The `while (!bloodInFile.eof())` loop is only a trivial variation on [`while (!feof(file))` is always wrong](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong) except that's officially for C rather than C++. I believe you should be using `while (bloodInFile >> a[i]) i++` to avoid incrementing `i` when you actually get to EOF. – Jonathan Leffler Nov 23 '16 at 05:32
  • Enable all warnings and debug info when compiling (e.g. use `g++ -Wall -g` if compiling with [GCC](http://gcc.gnu.org/)...); improve the code till you get no warnings; **use the debugger** (e.g. `gdb`). BTW your *fix-my-code* question is off-topic here. – Basile Starynkevitch Nov 23 '16 at 05:38

1 Answers1

1

Check that you are not out of bound of array a in function getPints add check here

 while (!bloodInFile.eof())
 {
   if(i >= h)
       break;
   bloodInFile >> a[i];
   i++;
 }

Because if you can have more lines that MAX_HOURS in bloodDrive.txt file. Also I don't see that you initialize i somewhere i suppose it should be equal to 0 (i=0), so you're function should looks like that

void getPints(double a[], int h)
{
    int i = 0;
    ifstream bloodInFile;

    bloodInFile.open("bloodDrive.txt");

    if (!bloodInFile)
        cout << "Cannot open file." << endl;

    while (!bloodInFile.eof())
    {
        if(i > h)
            break;
        bloodInFile >> a[i];
        i++;
    }

    bloodInFile.close();
}

P.S. as @JonathanLeffler said (and I agree with him 100%) it's better to use dynamic array (vector e.g.) for such problem when you don't know how much input could be.

segevara
  • 610
  • 1
  • 7
  • 18
  • 1
    I'm just left wondering — how does the calling code know how many entries were created? If the data was stored in a `vector` passed by reference, there wouldn't be a problem... – Jonathan Leffler Nov 23 '16 at 05:34
  • @JonathanLeffler You can use `size()` method for checking current size of vector, if I understood you right – segevara Nov 23 '16 at 05:37
  • Yes, but you can't use `size` with a classic array. In fact, in C++, you should hardly ever use a classic array, not least for reasons like that (not to mention the difficulty of resizing them, and …). Note that this is as much a problem with the original code as with your answer. Nevertheless, it is an issue. In context, using a classic array, it would be appropriate to change the function to return an `int` and to return the value of `i` to indicate how many entries were read. – Jonathan Leffler Nov 23 '16 at 05:39
  • Do you mean that using vector is more suitable solution for this problem? Yes I agree but author of question used array so maybe he has strongly requirements (I don't know). I've just edited answer add your recomendation – segevara Nov 23 '16 at 05:50