Search code examples
c++arraysclassrecursionknights-tour

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;
}

Solution

  • 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.)