clevertrever1
clevertrever1

Reputation: 13

I'm getting a weird error for a program that seems like it should "just work."

I present to you all a program I'm working on for my college programming course. I still have a little ways to go before it completely meets my assignment's requirements, but I've gotten a basic draft of the program error-free (supposedly) and it appears to run… but then it suddenly kicks me into Xcode's debugger and gives me:

Thread 1: EXC_BAD_ACCESS(code=2, address=0x7fff95c1e5f5)

Here's the command line output, up until it kicks me out:

    -----------------------
    Quarterly_sales_taxator
    -----------------------


    How many company divisions will we be dealing with?  2


    Am I correct in assuming that there are 4 sales quarters?    yes



    Please enter the sales Company Division #1 brought in for Sales Quarter #1   20
    (lldb)

Here's my code:

    //
    //  quarterly_sales_taxator.cpp
    //  Ch. 7 program #7
    //
    //  Created by John Doe on 11/27/12.
    //

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <sstream>
    #include <cctype>
    using namespace std;

    void read_company_divisions_and_sales_quarters(double **, int, int);
        //void write_company_divisions_and_sales_quarters_to_array(double **, int, int);    // This will be used later on to read data from a file.
    void display_quarterly_sales_array(double **, int, int);

    string temp;    // A global temporary placeholder variable; I use this several times.


    int main()
    {
        int COMPANY_DIVISIONS,
            SALES_QUARTERS = 4;

        double **quarterly_sales_form;


        cout << "\n\n-----------------------\nQuarterly_sales_taxator\n-----------------------\n\n";

        cout << "\nHow many company divisions will we be dealing with?  ";
        getline(cin, temp);
        stringstream(temp)>>COMPANY_DIVISIONS;

        while (COMPANY_DIVISIONS < 1 || isdigit(COMPANY_DIVISIONS == false))
        {
            cout << "\n\n------"
                 << "\nError:"
                 << "\n------"
                 << "\n\nYou have entered an invalid choice."
                 << "\nPlease type a number greater than zero.    ";

            getline(cin, temp);
            stringstream(temp)>>COMPANY_DIVISIONS;
        }

        cout << "\n\nAm I correct in assuming that there are 4 sales quarters?    ";
        getline(cin, temp);

                // Convert to uppercase.
            for (int count = 0; count < temp.length(); count ++)
            {
                temp[count] = toupper(temp[count]);
            }

            if (temp == "NO" || temp == "NOPE" || temp == "INCORRECT" || temp == "YOU ARE NOT" || temp == "YOU ARE INCORRECT" || temp == "NEGATIVE" || temp == "NEGATORY")
            {
                cout << "\nOk, then how many sales quarters are we dealing with?    ";
                getline(cin, temp);
                stringstream(temp)>>SALES_QUARTERS;
            }

        cout << endl << endl;

            // This sets up the 2d array.
        quarterly_sales_form = new double *[COMPANY_DIVISIONS];
        for (int count = 0; count < COMPANY_DIVISIONS; count ++)
        {   quarterly_sales_form[COMPANY_DIVISIONS] = new double [SALES_QUARTERS];  }

        read_company_divisions_and_sales_quarters(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS);
            //  write_company_divisions_and_sales_quarters_to_array(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS);   // I'll add this feature later.


        cout << "\n\nHere's what you entered:\n\n";
        display_quarterly_sales_array(quarterly_sales_form, COMPANY_DIVISIONS, SALES_QUARTERS);

            // Since we used a series of pointers, we need to free the allocated space back up.
        for (int count = 0; count < COMPANY_DIVISIONS; count ++)
        {   delete[] quarterly_sales_form[COMPANY_DIVISIONS];  }
        delete[] quarterly_sales_form;



        return 0;
    }


    /*############################################
     # read_company_divisions_and_sales_quarters #
     ############################################*/
    void read_company_divisions_and_sales_quarters(double **array, int DIVISIONS, int QUARTERS)
    {

            for (int count = 0; count < QUARTERS; count++)
            {

                for (int index = 0; index < DIVISIONS; index++)
                {
                    cout << "\nPlease enter the sales Company Division #" << count+1 << " brought in for Sales Quarter #" << index+1 << "   ";
                    getline(cin, temp);
                    stringstream(temp) >> array[count][index];
                }
            }
    }


    /*################################
     # display_quarterly_sales_array #
     #################################*/
    void display_quarterly_sales_array(double **array, int DIVISIONS, int QUARTERS)
    {
        for (int count = 0; count < DIVISIONS; count++)
        {
            cout << "\nCompany division #" << count+1 << ":\n";
            for (int index = 0; index < QUARTERS; index++)
            {    cout << array[count][index] << ", ";    }
        }

    }

Can some kind soul please tell me what I'm doing wrong?

Upvotes: 1

Views: 139

Answers (2)

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 154025

In addition to what Dan Hulme said, it seems this line

stringstream(temp) >> array[count][index];

should really be

std::istringstream(temp) >> std::skipws >> array[index][count];

In addition to using std::istringstream rather than std::stringstream and making sure that an lvalue is at hand, which isn't strictly needed until the type read becomes more interesting, this also reverses the indices: index runs over COMPANY_DIVISIONS and count over SALES_QUARTERS.

The real question is, of course: Who hands out assignments like this? Pointer manipulations and allocations are best left to low-level library writers. This is C++ not C: we can and should use abstractions. Getting this code exception safe is a major challenge and there is no point in teaching people how to write broken (e.g. exception unsafe) code.

Upvotes: 2

Dan Hulme
Dan Hulme

Reputation: 15290

    {   quarterly_sales_form[COMPANY_DIVISIONS] = new double [SALES_QUARTERS];  }

In this line, COMPANY_DIVISIONS should be count.

Upvotes: 5

Related Questions