Zoey A Zoey A - 16 days ago 5
C++ Question

Initialization of user-defined array in C++ class?

I'm working on knight's tour problem, and want to define a class, but I am having trouble with initialize an array defined by user. So the user inputs from the command line

argvs
are the chessboard lengths mX and nY; and a starting position(x,y). So basically, how do I initialize an array that's defined by the user?

First question: In the
public
part, is it right to declare
int ** tour
?

Second question: How do I refer to the array
tour
in the following functions in the same class?

Third question: In
main
, I called
K.knight
to initialize an array of dimension specified by the user, but it wasn't initialized. How do I initialize an array in
main
using the function
K.knigt()
, and be able to use the array in the following function
K.knightfunc()
?

class Ktour{
public:
int xSize; //m
int ySize; //n
int ** tour; //array to be initialized
int solutionsCount; //tracking solutions
int position; //position count, from 0 to m * n -1

// initialize tour matrix
void knight(int M, int N) {

position = 1;
solutionsCount = 0;

xSize = M;
ySize = N;

tour = new int * [xSize];
for (int i = 0; i < xSize; i++) {
for (int j = 0; j < ySize; j++) {
tour[i][j] = 0;
std::cout << tour[i][j] << std::endl;
}
}
}
....some other functions defined in between...
....
....
};
...
// main
int main(int argc, char *argv[])
{
Ktour K;

//user inputs chessboard length mX and nY; and a starting position(x,y)

int mX = atoi(argv[1]);
int nY = atoi(argv[2]);
int x = atoi(argv[3]);
int y = atoi(argv[4]);

//initialization
K.knight(mX, nY);

//run the recursive function;
K.knightFunc(x,y);

return 0;
}

Answer

Yeah, it seems more logical to initialize in the ctor. My take on this is you are creating an array of int pointers, and have not yet allocated the ints that are being pointed to.

You have a few possibilities:

  1. If we are to think of a common chessboard, then since the array size is known in advance, and it's not especially big, just create it in the class:

    class Ktour{
        ...
        int tour[8][8];
        ...
    }
    

although some purists might say you should only "new" such arrays. If it is a much larger array, you certainly should.

  1. A more straightforward syntax like what you're trying to do, for handling arrays of unknown size would be:

    class Ktour{
        ...
        int **tour=0;
    
    
        KTour(int M, int N) {
            tour = new int * [M];
            for (int i=0; i<M; ++i)
                tour[i] = new int [N];
        };
        ~KTour() {
            for (int i=0; i<M; ++i)
                delete [] tour[i];
            delete [] tour;
        };
        ...
    
    }

You access it quite simply, with:

std::cout << tour[i][j];
  1. The above kind of coding is error-prone. To reduce your future strife with memory access errors, you really should use STL container classes (or Boost ones, or Qt ones when using Qt, if their size isn't too limited - but you can use STL in Qt also), since they produce an error in debug when you access out-of-bounds subscripts for your arrays, instead of, e.g. overwriting important pointers, etc. Thus, you could use something like:

    class Ktour{ ... std::vector < std::vector<int> > Tour;

    KTour(int M, int N) {
        // tour.resize(M);    // not needed.
        tour.assign(M, std::vector <int> (N, 0));
    };
    ~KTour() {
        // No need to delete
    };
    ...
    

    }

and you access it with

std::cout << tour[i][j];

(Note: The extra lines in the code are some artifact of the <pre> and <code> tags; necessitated by not all of my indented lines being recognized as code.)