Go to Post Anyways, before we all get worked up over this setup, let's wait and see what details emerge. It can't be as bad as everyone is making it seem. - Karthik [more]
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
 
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 22-03-2012, 15:41
ctccromer's Avatar
ctccromer ctccromer is offline
Animus
AKA: Tucker Campbell
FRC #3753 (Bulah Bots)
Team Role: Alumni
 
Join Date: Jan 2012
Rookie Year: 2012
Location: Baton Rouge, Louisiana
Posts: 190
ctccromer is a name known to allctccromer is a name known to allctccromer is a name known to allctccromer is a name known to allctccromer is a name known to allctccromer is a name known to all
Re: C++ help: Understanding pointers?

Okay so after reading all of this and getting (what I think is) a better understanding of pointers, I attempted my book's chapter's next practice problem:
Quote:
Write a function that takes 3 arguments, a length, width and height, dynamically allocates a 3-dimensional array with those values and fills the 3-dimensional array with multiplication tables. Make sure to free the array when you are done.
I'm just filling it with an incrementing value rather than multiplication tables

Here's the code I wrote. It has 2 main errors that repeat many times that the compiler picked up and I wouldn't be surprised if there were several more. It looks like a lot, but you'll quickly realize that it's very small, quick, and (hopefully) simple so please don't be put off by its size.
So what's wrong with this and how can I fix it?
Please ignore the fact that I made it a 3x? 2dimensional array instead of a 3dimensional array. I noticed that towards the end of writing this but that's not the main focus of the exercise so I'll fix that later.
Code:
//get 3 user-input values and make a 3dimensional array with those dimensions.  Allocate that much memory.

#include <iostream>
using namespace std;

void setValues(int *a, int *b, int *c, int *arrayOne[], int *arrayTwo[], int *arrayThree[]);
void showValues(int *a, int *b, int *c, int *arrayOne[], int *arrayTwo[], int *arrayThree[]);

int main()
{
    int firstNumber;
    int *p_firstNumber = & firstNumber;
    int secondNumber;
    int *p_secondNumber = & secondNumber;
    int thirdNumber;
    int *p_thirdNumber = & thirdNumber;

    //get the 3 sizes
    cout << "Give me a length, width, and height!\n";
    cout << "Length: "; cin >> firstNumber;
    cout << "Width: "; cin >> secondNumber;
    cout << "Height: "; cin >> thirdNumber;

    //create the pointer version of the 3dimensional array
    int **p_p_fullArray = new int[3];
    int *p_firstArray = new int[firstNumber];
    int *p_secondArray = new int[secondNumber];
    int *p_thirdArray = new int[thirdNumber];

    //set the 3 1dimensional arrays to the full array
    p_p_fullArray[0] = & p_firstArray;
    p_p_fullArray[1] = & p_secondArray;
    p_p_fullArray[2] = & p_thirdArray;

    //create normal variables for the 3dimensional array
    int firstArray[firstNumber];
    int secondArray[secondNumber];
    int thirdArray[thirdNumber];

    //set the 3 1dimensional pointers to the 3 1dimensional variables
    p_firstArray = & firstArray;
    p_secondArray = & secondArray;
    p_thirdArray = & thirdArray;

    //assign something to every cell in the array
    setValues(int *p_firstNumber, int *p_secondNumber, int *p_thirdNumber, int *p_firstArray[], int *p_secondArray[], int *p_thirdArray[]);

    //show the array (easy way to make sure the program worked)
    cout << "\nCool thanks.  Here's your array:" << endl;
    showValues(int *p_firstNumber, int *p_secondNumber, int *p_thirdNumber, int *p_firstArray[], int *p_secondArray[], int *p_thirdArray[]);

    //free the allocated memory and make sure the pointers don't grab on to anything random and cause issues
    delete p_p_fullArray;
    p_p_fullArray = NULL;
    delete p_firstArray;
    p_firstArray = NULL;
    delete p_secondArray;
    p_secondArray = NULL;
    delete p_thirdArray;
    p_thirdArray = NULL;
    delete p_firstNumber;
    p_firstNumber = NULL;
    delete p_secondNumber;
    p_secondNumber = NULL;
    delete p_thirdNumber;
    p_thirdNumber = NULL;
}

void setValues(int *a, int *b, int *c, int *arrayOne[], int *arrayTwo[], int *arrayThree[])
{
    int value = 0;

    for (int i = 0; i < a; i++)
    {
        *arrayOne[i] = value;
        ++value;
    }

    for (int j = 0; j < b; j++)
    {
        *arrayTwo[j] = value;
        ++value;
    }

    for (int k = 0; k < c; k++)
    {
        *arrayThree[k] = value;
        ++value;
    }
}

void showValues(int *a, int *b, int *c, int *arrayOne[], int *arrayTwo[], int *arrayThree[])
{
    cout << "first row: ";
    for (int i = 0; i < a; i++)
    {
        cout << arrayOne[i] << " ";
    }

    cout << "\nsecond row: ";
    for (int j = 0; j < b; j++)
    {
        cout << arrayTwo[j] << " ";
    }

    cout << "\nthird row: ";
    for (int k = 0; k < c; k++)
    {
        cout << arrayThree[k] << " ";
    }
}
__________________
Team 3753 BulahBots
  #2   Spotlight this post!  
Unread 22-03-2012, 15:45
ebarker's Avatar
ebarker ebarker is offline
Registered User
AKA: Ed Barker
FRC #1311 (Kell Robotics)
Team Role: Mentor
 
Join Date: Jan 2006
Rookie Year: 2006
Location: Kennesaw GA
Posts: 1,437
ebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond reputeebarker has a reputation beyond repute
Re: C++ help: Understanding pointers?

the function pointer tutorial website

http://www.newty.de/fpt/index.html
__________________
Ed Barker
  #3   Spotlight this post!  
Unread 22-03-2012, 20:50
Bongle's Avatar
Bongle Bongle is offline
Registered User
FRC #2702 (REBotics)
Team Role: Mentor
 
Join Date: Feb 2004
Rookie Year: 2002
Location: Waterloo
Posts: 1,069
Bongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond reputeBongle has a reputation beyond repute
Send a message via MSN to Bongle
Re: C++ help: Understanding pointers?

You're very close with your code, but you actually need a 3rd level of indirection.

int*** p3Dimensions = new int**[width];
for(int x = 0;x < width; x++)
{
p3Dimensions[x] = new int*[height];
for(int y = 0;y < height; y++)
{
p3Dimensions[x][y] = new int[depth];
for(int z = 0;z < depth; z++)
{
p3Dimensions[x][y][z] = x*y*z;
}
}
}

I'm pretty tired from practice day at waterloo, so I'll let you figure out how that works ... if it compiles, which it might not.
  #4   Spotlight this post!  
Unread 22-03-2012, 21:17
Ginto8's Avatar
Ginto8 Ginto8 is offline
Programming Lead
AKA: Joe Doyle
FRC #2729 (Storm)
Team Role: Programmer
 
Join Date: Oct 2010
Rookie Year: 2010
Location: Marlton, NJ
Posts: 174
Ginto8 is a glorious beacon of lightGinto8 is a glorious beacon of lightGinto8 is a glorious beacon of lightGinto8 is a glorious beacon of lightGinto8 is a glorious beacon of light
Re: C++ help: Understanding pointers?

Quote:
Originally Posted by ctccromer View Post
Okay so after reading all of this and getting (what I think is) a better understanding of pointers, I attempted my book's chapter's next practice problem:

I'm just filling it with an incrementing value rather than multiplication tables

Here's the code I wrote. It has 2 main errors that repeat many times that the compiler picked up and I wouldn't be surprised if there were several more. It looks like a lot, but you'll quickly realize that it's very small, quick, and (hopefully) simple so please don't be put off by its size.
So what's wrong with this and how can I fix it?
Please ignore the fact that I made it a 3x? 2dimensional array instead of a 3dimensional array. I noticed that towards the end of writing this but that's not the main focus of the exercise so I'll fix that later.
[code]
So I looked at your code and fixed it. As I did, I added comments and showed what I changed it from. To distinguish them, my comments are not indented:
Code:
//get 3 user-input values and make a 3dimensional array with those dimensions.  Allocate that much memory.

#include <iostream>
using namespace std;

// See at implementation
void setValues(int *a, int *b, int *c, int arrayOne[], int arrayTwo[], int arrayThree[]); // void setValues(int *a, int *b, int *c, int *arrayOne[], int *arrayTwo[], int *arrayThree[]);
void showValues(int *a, int *b, int *c, int arrayOne[], int arrayTwo[], int arrayThree[]); // void showValues(int *a, int *b, int *c, int *arrayOne[], int *arrayTwo[], int *arrayThree[]);

int main()
{
    int firstNumber;
    int *p_firstNumber = & firstNumber;
    int secondNumber;
    int *p_secondNumber = & secondNumber;
    int thirdNumber;
    int *p_thirdNumber = & thirdNumber;

    //get the 3 sizes
    cout << "Give me a length, width, and height!\n";
    cout << "Length: "; cin >> firstNumber;
    cout << "Width: "; cin >> secondNumber;
    cout << "Height: "; cin >> thirdNumber;

    //create the pointer version of the 3dimensional array
    int **p_p_fullArray = new int*[3]; // int **p_p_fullArray = new int[3];
    int *p_firstArray = new int[firstNumber];
    int *p_secondArray = new int[secondNumber];
    int *p_thirdArray = new int[thirdNumber];

    //set the 3 1dimensional arrays to the full array
    p_p_fullArray[0] = p_firstArray; // p_p_fullArray[0] = & p_firstArray;
    p_p_fullArray[1] = p_secondArray; // p_p_fullArray[1] = & p_secondArray;
    p_p_fullArray[2] = p_thirdArray; // p_p_fullArray[2] = & p_thirdArray;

// this part is trying to statically allocate an array with a length derived from
// a runtime value (illegal), and then leaks memory because you're removing the arrays
// you allocated using new
/*
    //create normal variables for the 3dimensional array
    int firstArray[firstNumber];
    int secondArray[secondNumber];
    int thirdArray[thirdNumber];

    //set the 3 1dimensional pointers to the 3 1dimensional variables
    p_firstArray = & firstArray;
    p_secondArray = & secondArray;
    p_thirdArray = & thirdArray;
*/

// functions are called by passing values, not by declaring what types those values are
    //assign something to every cell in the array
    setValues(p_firstNumber, p_secondNumber, p_thirdNumber, p_firstArray, p_secondArray, p_thirdArray); // setValues(int *p_firstNumber, int *p_secondNumber, int *p_thirdNumber, int *p_firstArray[], int *p_secondArray[], int *p_thirdArray[]);

    //show the array (easy way to make sure the program worked)
    cout << "\nCool thanks.  Here's your array:" << endl;
// same as before
    showValues(p_firstNumber, p_secondNumber, p_thirdNumber, p_firstArray, p_secondArray, p_thirdArray); // showValues(int *p_firstNumber, int *p_secondNumber, int *p_thirdNumber, int *p_firstArray[], int *p_secondArray[], int *p_thirdArray[]);

// delete is not enough for arrays. delete normally just calls a destructor and deallocates memory for a single instance.
// If you want to deallocate an array, you should use delete [].
//
// Although setting pointers to NULL when you're done with them is a good idea, if you aren't
// going to use them again (in a situation like, for example, your program ending), there's no point
    //free the allocated memory and make sure the pointers don't grab on to anything random and cause issues
    delete [] p_p_fullArray; // delete p_p_fullArray;
    p_p_fullArray = NULL;
    delete [] p_firstArray; // delete p_firstArray;
    p_firstArray = NULL;
    delete [] p_secondArray; // delete p_secondArray;
    p_secondArray = NULL;
    delete [] p_thirdArray; // delete p_thirdArray;
    p_thirdArray = NULL;
// you tried to delete statically allocated memory. This messes stuff up.
/*
    delete p_firstNumber;
    p_firstNumber = NULL;
    delete p_secondNumber;
    p_secondNumber = NULL;
    delete p_thirdNumber;
    p_thirdNumber = NULL;
*/
}

// a note on parameters: arrays, when used as function parameters, degenerate and become identical
// to pointers. Therefore, you're asking for 3 int**s, which is definitely not what you passed. Pick
// either * or [], whichever better represents how you use it.
void setValues(int *a, int *b, int *c, int arrayOne[], int arrayTwo[], int arrayThree[]) // void setValues(int *a, int *b, int *c, int *arrayOne[], int *arrayTwo[], int *arrayThree[])
{
    int value = 0;

// you have to dereference a pointer to be able to use it as a normal value
//
// also, i j and k each go out of scope after each loop, so you don't have to
// choose a different name for each. Name them all i and they'll technically
// be different variables, but will still be called i. Consistency is good, and
// coming up with a new name for the iterator in each loop is pointless.
    for (int i = 0; i < *a; i++) // for (int i = 0; i < a; i++)
    {
// since you don't pass in an int**, don't use it as one        
        arrayOne[i] = value; // *arrayOne[i] = value;
        ++value;
    }

    for (int j = 0; j < *b; j++) // for (int j = 0; j < b; j++)
    {
        arrayTwo[j] = value; // *arrayTwo[j] = value;
        ++value;
    }

    for (int k = 0; k < *c; k++) // for (int k = 0; k < c; k++)
    {
        arrayThree[k] = value; // *arrayThree[k] = value;
        ++value;
    }
}

// same as above
void showValues(int *a, int *b, int *c, int arrayOne[], int arrayTwo[], int arrayThree[]) // void showValues(int *a, int *b, int *c, int *arrayOne[], int *arrayTwo[], int *arrayThree[])
{
    cout << "first row: ";
// same situation. Dereference, dereference, dereference!
    for (int i = 0; i < *a; i++) // for (int i = 0; i < a; i++)
    {
        cout << arrayOne[i] << " ";
    }

    cout << "\nsecond row: ";
    for (int j = 0; j < *b; j++) // for (int j = 0; j < b; j++)
    {
        cout << arrayTwo[j] << " ";
    }

    cout << "\nthird row: ";
    for (int k = 0; k < *c; k++) // for (int k = 0; k < c; k++)
    {
        cout << arrayThree[k] << " ";
    }
}
However, as you said, this does not actually do what it was supposed to do, and there were some things about it that could have been done better, so I wrote my own as an example:
Code:
#include <iostream>
#include <sstream>
using namespace std;

// once created, arr[i][j][k] will be the product i*j*k
int*** makeMultTable(int l,int w,int h) {
    if(l <= 0 || w <= 0 || h <= 0)
        return NULL;
    // allocate top-layer containing array
    int*** ret = new int**[l];
    for(int i=0;i<l;++i) {
        // allocate array to store rows
        ret[i] = new int*[w];
        for(int j=0;j<w;++j) {
            // allocate individual row
            ret[i][j] = new int[h];
            // set each row element to its value in the multiplication table
            for(int k=0;k<h;++k)
                ret[i][j][k] = i*j*k;
        }
    }
    return ret;
}

void printTable(int*** table,int l,int w,int h) {
    if(!table || l <= 0 || w <= 0 || h <= 0)
        return;
    // find longest possible int
    // used for prettifying the grid
    stringstream digitTest;
    // if i, j, and k are less than l, w, and h respectively,
    // then the largest value of i*j*k is (l-1)*(w-1)*(h-1)
    digitTest << (l-1)*(w-1)*(h-1);
    // find greatest amount of digits for prettification
    int digitLength = digitTest.str().length();
    // go by layers because text is only 2 dimensional at best
    for(int i=0;i<l;++i) {
        cout << "i = " << i << ":" << endl;
        for(int j=0;j<w;++j) {
            // go through each element in the row
            for(int k=0;k<h;++k) {
                // reset prettifying stream
                digitTest.str("");
                // single grid element
                digitTest << table[i][j][k];
                // prettify the element
                while(digitTest.str().length() < digitLength)
                    digitTest << " ";
                // no extra space needed at the end of a row
                if(k != h-1)
                    digitTest << " ";
                // output prettified element
                cout << digitTest.str();
            }
            // row done
            cout << endl;
        }
        // layer done
        cout << endl;
    }
}

void freeMultTable(int*** table,int l,int w,int h) {
    if(!table || l <= 0 || w <= 0 || h <= 0)
        return;
    // delete contents from the inside out
    for(int i=0;i<l;++i) {
        for(int j=0;j<w;++j)
            // delete individual row
            delete [] table[i][j];
        // delete one layer
        delete [] table[i];
    }
    // delete whole table
    delete [] table;
}

int main() {
    int l,w,h;
    
    cout << "Length? ";
    cin >> l;
    cout << "Width? ";
    cin >> w;
    cout << "Height? ";
    cin >> h;
    
    int*** table = makeMultTable(l,w,h);
    
    printTable(table,l,w,h);
    
    freeMultTable(table,l,w,h);
    
    return 0;
}
Then, since I noticed that the table could be well-represented as a class, I converted it to OOP:
Code:
#include <iostream>
#include <sstream>
#include <stdexcept>
using namespace std;

class MultTable {
    int*** table;
    int l,w,h;
public:
    MultTable(int l_,int w_,int h_) : l(l_),w(w_),h(h_) {
        if(l <= 0 || w <= 0 || h <= 0)
            throw runtime_error("Invalid dimensions");
        // allocate top-layer containing array
        table = new int**[l];
        for(int i=0;i<l;++i) {
            // allocate array to store rows
            table[i] = new int*[w];
            for(int j=0;j<w;++j) {
                // allocate individual row
                table[i][j] = new int[h];
                // set each row element to its value in the multiplication table
                for(int k=0;k<h;++k)
                    table[i][j][k] = i*j*k;
            }
        }
    }
    ~MultTable() {
        if(!table || l <= 0 || w <= 0 || h <= 0)
            return;
        // delete contents from the inside out
        for(int i=0;i<l;++i) {
            for(int j=0;j<w;++j)
                // delete individual row
                delete [] table[i][j];
            // delete one layer
            delete [] table[i];
        }
        // delete whole table
        delete [] table;
    }
    
    int get(int i,int j,int k) const {
        if(i <= 0 || j <= 0 || k <= 0 ||
           i >= l || j >= w || k >= h)
            throw runtime_error("Index out of range");
    }
    
    string toString() const {
        stringstream out;
        // find longest possible int
        // used for prettifying the grid
        stringstream digitTest;
        // if i, j, and k are less than l, w, and h respectively,
        // then the largest value of i*j*k is (l-1)*(w-1)*(h-1)
        digitTest << (l-1)*(w-1)*(h-1);
        // find greatest amount of digits for prettification
        int digitLength = digitTest.str().length();
        // go by layers because text is only 2 dimensional at best
        for(int i=0;i<l;++i) {
            out << "i = " << i << ":" << endl;
            for(int j=0;j<w;++j) {
                // go through each element in the row
                for(int k=0;k<h;++k) {
                    // reset prettifying stream
                    digitTest.str("");
                    // single grid element
                    digitTest << table[i][j][k];
                    // prettify the element
                    while(digitTest.str().length() < digitLength)
                        digitTest << " ";
                    // no extra space needed at the end of a row
                    if(k != h-1)
                        digitTest << " ";
                    // output prettified element
                    out << digitTest.str();
                }
                // row done
                out << endl;
            }
            // layer done
            out << endl;
        }
        return out.str();
    }
};

ostream& operator<<(ostream& o,const MultTable& multTable) {
    return o << multTable.toString();
}

int main() {
    int l,w,h;
    
    cout << "Length? ";
    cin >> l;
    cout << "Width? ";
    cin >> w;
    cout << "Height? ";
    cin >> h;
    
    MultTable table(l,w,h);
    
    cout << table;
    
    return 0;
}
I tried to comment on some of the things that might confuse you. I hope these help!
Closed Thread


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 01:39.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi