1

I'm pretty new in c++ althought a bit experienced in java, and my problem it's the next one:

I'm doing a sudoku project where I'm creating an abstract data type of the box and the board. In the board one, I'm creating a bidimesional array of boxes, but when I want to create it as a public data so I can use it in the whole class and not only in the board constructor.

I'm creating it in the board constructor because If I don't create it there, I have no way of knowing the value of each dimension, and if I create the variable Box box[int][int] where I can use it in the class, I've got no way of knowing the dimensions. It'll be better understandable with some code.

This code allows me to create the Box array with the dimensions I want, because it's in the board constructor than when it's created it has as a parameters the number of boxes, but it don't let me use the "casilla" variable in the other part of the class nor other classes:

class tablero{

    int filas;
    int columnas;

public:


    tablero (int filas, int columnas){

    this->filas = filas;

    this->columnas =columnas;
    Casilla casilla[filas][columnas];


    }
    Casilla getCasilla(int n, int m){
        return casilla[n][m];  <- Here shows an error because casilla cannot be resolved.

    }

And this other code lets me use the casilla variable, but I have to give it the parameters to the dimensions before I know them:

class tablero{

    int filas;
    int columnas;

public:
    Casilla casilla[0][0];

    tablero (int filas, int columnas){

    this->filas = filas;

    this->columnas =columnas;



    }
    Casilla getCasilla(int n, int m){
        return casilla[n][m];

    }

No error, but the dimensions of the casilla array have to be given before I know them, and so, they may be the wrong ones (because the board may have different dimensions.

It's the first time I'm programming in c++, and I'm really frustated with this problem, can anyone help me to find a way to make it so it works both ways? (I already tried to leave both dimensions empty and then in the constructor put casilla[][] = Casilla cas[filas] [columnas] but it gives me an error..)

Thanks for the help everyone. Also, If you think the title is not clear enough, you can suggest one and I'll change it.

The Casilla code is this one:

class Casilla{

int fila;

int columna;

int numero;

   public:

      // constructor

      Casilla(int fila, int columna,int numero)
      {
          this->fila = fila;

          this->columna = columna;

          this->numero = numero;


      }

};

Thanks everyone for your answers, I've already found the answer I needed from 3 different people. I can't upvote all of you because I still don't have 15 reputation, but when I have it i'll upvote you all. Thanks for all your answers, really. I just need to know what I commented on the checked answer and it'll be all answered.

2
  • 2
    Use rather std::vector<std::vector<Casilla >> than a raw array. Commented Jan 15, 2015 at 23:46
  • If the dimentsions are not known, dynamic memory allocation is nevessary. Being a novice, you had better use std::vector, as suggested above. Commented Jan 15, 2015 at 23:56

4 Answers 4

2

A solution with an array

//----------------------------------------------------------------------------
#include <iostream>
#include <iomanip>
//----------------------------------------------------------------------------
class Casilla
{
    int fila;
    int columna;
    int numero;

   public:

      // default constructor
      Casilla()
      {
          this->fila = -1;
          this->columna = -1;
          this->numero = 0;
      }

      int GetNumero() {return numero;}  
      void SetCasilla (int _fila, int _columna) //set a cell position
      {
          fila = _fila;
          columna = _columna;
      }
      void SetCasilla (int _numero)             //set a cell value
      {
          numero = _numero;
      }
      void SetCasilla (int _fila, int _columna, int _numero) //set a cell position and value
      {
          fila = _fila;
          columna = _columna;
          numero = _numero;
      }

};

class Tablero
{
    int filas;
    int columnas;
    Casilla **casilla;

public:

    Tablero (int filas, int columnas)
    {
        this->filas = filas;
        this->columnas =columnas;
        casilla = new Casilla* [filas];
        for (int i = 0; i<filas; i++)
          casilla[i] = new Casilla [columnas];

        for (int i = 0; i<filas; i++)
            for (int j = 0; j<columnas; j++)
                casilla[i][j].SetCasilla(i,j);  //set the right position for each cell
                                                //the values = 0 by default
    }

    //destructor
    ~Tablero()
    {
        for (int i = 0; i<filas; i++)
            delete [] casilla[i];
        delete [] casilla;
    }

    //set a cell value in the table 
    void ChangeCasillaValue (int _fila, int _columna, int _numero)
    {
        casilla[_fila][_columna].SetCasilla (_numero);
    }


    Casilla getCasilla(int n, int m)
    {
        return casilla[n][m]; 
    }

    void PrintTablero ()
    {
         for (int i = 0; i<filas; i++)
        {     
            for (int j = 0; j<columnas; j++)
                  std::cout << std::setw(5)<<casilla[i][j].GetNumero();
            std::cout << "\n";
         }
         std::cout << "\n";
    }
};


//----------------------------------------------------------------------------
int main()
{   
    int N = 5, M = 6;
    Tablero table(N, M);
    table.PrintTablero();

    table.ChangeCasillaValue(1,1,-5); //change value in cell(1,1)
    table.PrintTablero();

    std::cin.get();
    return 0;
}
//-----------------------------------------------------------------------------

You have to add a bunch of setters and getters of your own. But, as a draft, it works.

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

1 Comment

Wow, that's awesome, can you explain me the asterisks think? The casilla** and the casilla = new *Casilla, I've never found this kind of thing in a code, and I don't understand pretty much. Also, I check your answer, thanks to E.C.Drew and Matt McNabb, those codes have helped my understanding the vector class much better than 5 "tutorials" in the internet that I've already readed.
2

C-style array dimensions must be known at compile-time in C++. So there is no variant of Casilla casilla[filas][columnas]; that will work.

Instead you should use a container which can hold the data you want to put in it. Use of C-style arrays in C++ is discouraged because they have some strange behaviour and rules, they are mainly there for backwards compatibility.

The simplest option is a 1-dimensional array with runtime size, that is called vector:

class tablero{

    int filas;
    int columnas;
    std::vector<Casilla> casilla;

public:
    tablero (int filas, int columnas)
        : filas(filas), columnas(columnas), casilla(filas * columnas)
    { }

    Casilla getCasilla(int f, int c) const
    {
        return casilla[f * columnas + c]; 
    }
};

Note the use of the constructor initializer list. You should provide initial values for class members this way, instead of using assignment statements inside the constructor.

Comments

1

In your first example, in your constructor, the line

Casilla casilla[filas][columnas];

declares casilla an array of arrays of Casilla objects local to your constructor. Once your constructor returns, casilla goes out of scope. There is no casilla member variable or local variable in your getCasilla function, so of course it cannot be resolved.

In your second example, your class has a public member casilla declared as 0 by 0 array of Casilla objects. Your getCasilla function would return the item in the nth row and mth column of the 0 by 0 array. In C++, there is no bound checking on array dereferences, so this is returning some out of bounds memory location and is very bad.

You can create dynamic C arrays yourself by using malloc and free, but since you are using C++ it will be easier to just use std::vector.

For example, you could use:

#include <iostream>
#include <vector>

class Casilla
{};

class tablero
{
  int filas_;
  int columnas_;
  std::vector<std::vector<Casilla> > casilla_; // a vector of vectors of Casillas
public:
  tablero(int filas, int columnas) : filas_(filas), columnas_(columnas), 
                                     casilla_(filas, std::vector<Casilla>(columnas))
  // The above is an initialization list
  // We initialize casilla_ as a vector of filas vectors of columnas Casillas
  {}

  std::vector<std::vector<Casilla> > getCasilla() const
  {
    return casilla_;
  }
};


int main(int argc, const char* argv[])
{
  tablero t(3, 3);

  std::cout << "casilla rows: " << t.getCasilla().size() << std::endl;
  std::cout << "casilla cols: " << t.getCasilla()[0].size() << std::endl;

  return 0;
}

Comments

0

First Casilla casilla[filas][columnas]; needs to be a class variable so it's accessible to all methods.
Second the sizes of rows and columns must be a fixed number e.g Casilla casilla[9][9];
If it need to be dynamically allocated you could you Vectors or Vectors of Vectors.
If it's 2d array, you can still create it as 1d array, but depends which is best for your purposes.

3 Comments

The only think I need is to create a bidimensional array, with the dimensions given in the tablero(board) constructor, that can be used in all the class and other classes. It's possible to create something like this or I have to make a vector of vectors? I'm too used to using arrays in java and I'm in trouble when I get out of that programming language.
The Casilla class description is necessary.
Casilla Code Added. Thanks everyone for your help until now, I'm already researching about the vectors in c++ so if I have to use them.

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.