0

This is part of a quick&dirty program I wrote to do some statistics calculations. Sometimes I gives me the expected output, which is:

42 1 1
48 13 14
54 12 26
60 11 37
66 6 43
72 13 56
78 23 79
84 14 93
90 6 99
96 0 99
102 0 99
108 1 100

But sometimes (about 50% of the times I run the program) the last line of the output differs and looks like this:

108 2 101

I'm compiling with gcc 7.3.0 on Debian 64bit with no compiler flags except -o

I know, the program could be written more elegantly but I don't see where this strange behavior comes from.

#include <iostream> //cout, endl
#include <algorithm> //sort
#include <iomanip> // setw(), setfill(), left, right

using namespace std;

void classes(int, int, int[]);

static int sizeOfData = 0;

int main()
{
    int data[] ={
                    80, 71, 57, 80, 75, 77, 60, 86, 77, 56, 81, 50, 89, 54, 90, 73, 60, 83, 65, 82, 84, 54, 85, 58, 79,
                    57, 88, 68, 76, 78, 74, 85, 75, 65, 76, 58, 91, 50, 87, 48, 93, 54, 86, 53, 78, 52, 83, 60, 87, 49,
                    80, 60, 92, 43, 89, 60, 84, 69, 74, 71, 108, 50, 77, 57, 80, 61, 82, 48, 81, 73, 62, 79, 54, 80, 73,
                    81, 62, 81, 71, 79, 81, 74, 59, 81, 66, 87, 53, 80, 50, 87, 51, 82, 58, 81, 49, 92, 50, 88, 62, 93
                    };

    sizeOfData = sizeof(data)/sizeof(data[0]);
    sort(data, data + sizeOfData);

    classes(42, 6, data);
}

void classes(int start, int step, int data[])
{
    int counter = 0;
    int classCounter = 0;

    const char separator = ' ';
    int tabWidth = 8;

    cout << endl;
    cout << left << setw(tabWidth) << setfill(separator) << "class";
    cout << left << setw(tabWidth) << setfill(separator) << "#";
    cout << left << setw(tabWidth) << setfill(separator) << "# cumulative";
    cout << endl << endl;

    int i = 0;
    while(i < sizeOfData)
    {
        classCounter = 0;
        while(data[i] < start + step)
        {
            classCounter++;
            counter++;
            i++;
        }
        cout << left << setw(tabWidth) << setfill(separator) << start;
        cout << left << setw(tabWidth) << setfill(separator) << classCounter;
        cout << left << setw(tabWidth) << setfill(separator) << counter;
        cout << endl;
        start = start + step;
    }
}
1
  • 2
    Your life would be a lot easier if instead of using these really clunky calculations for array size you just use a Standard Library container like std::vector. Commented Apr 14, 2018 at 21:32

3 Answers 3

5

Your program has undefined behavior on the last iteration. If i is 99 on the last iteration, you happily increment beyond the bounds of the array in the inner loop, after which data[i] is undefined behavior.

To fix this, the simplest thing to do would be to check that i is not larger than sizeOfData in the interior condition as well.

while((i < sizeOfData) && (data[i] < start + step))

It would be worthwhile to consider picking up an STL container like std::vector or std::array - it would simplify your handling of the array size, and you could make your classes function more generic.

Sign up to request clarification or add additional context in comments.

Comments

3

You don't check if i < sizeOfData in the nested loop. That's the problem. It can go out of bounds - undefined behaviour.

Comments

0

The counter i in the for loop is exceeding the boundary of the sizeOfData that you use in your code. Try check the i value to avoid this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.