1

I just want to create a 2D-array and assign values to it. How can I fix that? (I mentioned the error in the comment.)

using namespace std;

class array{
    private:
        size_t m; //error: invalid use of non-static data member 'array::m'|
        size_t n; //error: invalid use of non-static data member 'array::n'|
        int array[m][n];  
    public:
        array():m(0),n(0){
        }
        array(const int &m,const int &n):m(m),n(n){
        }
        //method set array
        void setArray(){
            for (size_t row=0;row<m;row++){
                for(size_t col=0;col<n;col++){
         cin>>array[row][col]; //error: expected primary-expression before '[' token
                }
            }
        }


};
Saif Faidi
  • 509
  • 4
  • 15
Jacky Teerapat
  • 125
  • 1
  • 10
  • Make array as pointer variable and allocate memory in the constructor (new int[m][n]). You can also use std::vector. – Srini Jul 17 '19 at 08:46

5 Answers5

1

The easy way to do this is to use a vector.

#include <vector>
#include <iostream>

class array {
private:
    std::vector<std::vector<int>> array;

public:
    array() {
    }

    array(int m, int n) : array(m, vector<int>(n)) {
    }

    void setArray() {
        for (size_t row = 0; row < array.size(); row++) {
            for (size_t col = 0; col < array[row].size(); col++) {
               std::cin>>array[row][col];
            }
        }
    }
};

Using a vector mean you don't have to do the dynamic memory allocation yourself, resulting in safer and more readable code.

john
  • 85,011
  • 4
  • 57
  • 81
  • If I want to declare vector 2d I must write vector name; ? – Jacky Teerapat Jul 17 '19 at 08:58
  • Yes, a 2d vector is a vector whose elements are also vectors, which is what `vector>` says. – john Jul 17 '19 at 09:00
  • When I want to get the data in that vector. I can use array[row][col] likes array? @john – Jacky Teerapat Jul 17 '19 at 09:02
  • @JackyTeerapat Yes, that is how to access them. You might want to read some basic tutorials, to fill some gaps aside from vectors. Plus, there is a lot of things to vectors that you probably don't know yet, like iterators, `std::sort`, `std::vector::reserve`, `std::vector::shrink_to_fit`... – Aziuth Jul 17 '19 at 09:15
  • I don't understand about this ```array(m, vector(n))``` – Jacky Teerapat Jul 17 '19 at 09:19
  • @JackyTeerapat array(N, v) creates an array of size N with initial value of v for all N elements. So array(m, vector(n)) is creating a vector of size m, with m vectors of size n as the initial values. A 2d array in other words. – john Jul 17 '19 at 10:07
1

First, you shouldn't name your array "array", it's a reserved class name. Second, you're trying to use 'm' and 'n' before you have declared a value for them. You should declare a value for them first. Hope that helps.

lord_bow
  • 11
  • 2
  • array is not a reserved name, it's an already used name in the `std` namespace, but it's perfectly legal to use it as your own class name. Maybe it's not advisable (especially in conjunction with `using namespace std;`) but it is legal. – john Jul 17 '19 at 08:52
  • OK thanks for telling me. I honestly don't know much about C++. – lord_bow Jul 19 '19 at 07:40
0

In your program, m and n are non-const, meaning they can change throughout the life of a program.

If an array is declared using the array[m][n] syntax, m and n have to be const. You have two options here: Make m and n const, or make the array dynamic (can change size). The easiest one by far is making m and n const:

using namespace std;

class array
{
    private:
        const size_t m = 10;
        const size_t n = 10;
        int array[m][n];  
    public:
        array() {}
        // method set array
        void setArray(){
            for (size_t row = 0; row < m; row++){
                for (size_t col = 0; col < n; col++){
                    cin>>array[row][col]; //error: expected primary-expression before '[' token
                }
            }
        }
};

Making the array dynamic requires knowledge of dynamic memory allocation, pointers, the stack and the heap, and the new and delete operators.

Why don't you just use a std::vector or std::vector<std::vector> so it can manage this stuff for you?

Sabrina Jewson
  • 1,478
  • 1
  • 10
  • 17
0

If m and n are variables, in most cases, you cannot write

int foo[m][n];  

unless m and n are const variables known at compile time, or you use Gnu C++ which has such extension, or maybe they are template parameters (also have problems of its own, and workarounds).

Further reading:

Array[n] vs Array[10] - Initializing array with variable vs real number

Array initialization use const variable in C++

user31264
  • 6,557
  • 3
  • 26
  • 40
0

I assume here that the array dimensions cannot be known at compile time. The "vector of vectors" technique, as described by John, basically works. However, a drawback is the necessity of allocating many separate memory blocks, one per elementary vector.

For example, if the 2-dimensional integer array is meant to be a 1920x1080 bitmap image, with one integer value per pixel, this means we are going to call malloc 1080 times at object creation time, and we are also going to call free/delete 1080 times when the object is released. This can be quite costly. Also, a lot of functionality in existing graphic libraries will insist on having a single storage block per image.

To work around these problems, we can instead use a single, private 1-dimensional standard vector, and arrange access functions so that expression mat[i][j] still works as expected. The easiest way to do this is to have mat[i] overloaded, so it returns the address of the beginning of the row. That way, the mat[i] pointer value can naturally be re-indexed with [j]. The resulting array access is not range-checked, just like for a regular std::vector object.

The idea is implemented in the code sample below:

#include  <vector>
#include  <iostream>
#include  <fstream>


class array2d {
private:
    size_t  rowCount, colCount;
    std::vector<int>  vec;

public:
    array2d(size_t m, size_t n) : rowCount(m), colCount(n)
    {
        size_t  size  = m*n;
        vec           = std::vector<int>(size, 0);

        int*  basePtr = vec.data();

        for (size_t i=0; i < size; i++)
            basePtr[i] = 0;
    }

    inline size_t getRowCount() { return rowCount; }

    inline size_t getColCount() { return colCount; }


    inline int* operator[](size_t rowId)  // HERE !
    {
         // NOT range-checked just like std::vector
         return (vec.data() + (rowId*(this->colCount)));
    }


    void setArrayFromFile(std::istream& file) {
        for (size_t row = 0; row < rowCount; row++) {
            int*  rowStart = (*this)[row];
            for (size_t col = 0; col < colCount; col++) {
                file >> rowStart[col];
            }
        }
    }

    // specialized version to read from standard input:
    void setArray()
    {
        setArrayFromFile(std::cin);
    }
};

//---------------------------------------------------------

  // EXAMPLE OF USE:


void printIntegerMatrix(array2d& matrix)
{
    size_t  rowCount = matrix.getRowCount();
    size_t  colCount = matrix.getColCount();

    for (size_t row = 0; row < rowCount; row++) {
        for (size_t col = 0; col < colCount; col++) {
            std::cout << matrix[row][col] << " ";
        }
        std::cout << std::endl;
    }
}


void processIntegerMatrix(array2d& matrix, const std::string& fileName)
{
    // fill in matrix from a text file then print its contents on stdout:

    std::ifstream  inputStream{fileName};
    if (!inputStream) {
        std::cerr << " Cannot open file " << fileName << std::endl;
        exit(EXIT_FAILURE);
    }

    matrix.setArrayFromFile(inputStream);
    inputStream.close();

    std::cerr << "After reading from file." << std::endl;

    printIntegerMatrix(matrix);
}


int main(int argc, const char* argv[])
{
    size_t  rowCount = 3;
    size_t  colCount = 6;

    // have a text file with some numbers in it:

    std::string    fileName{"numbers1.dat"};

    std::cout << "matrix size: " << rowCount << 'x' << colCount << std::endl;

    // create zero-filled matrix:
    array2d  mat1(rowCount, colCount);

    processIntegerMatrix(mat1, fileName);

    return EXIT_SUCCESS;
}
jpmarinier
  • 4,427
  • 1
  • 10
  • 23