Search code examples
c++arrayspointersmatrix

Program to find out whether a Matrix is symmetric or not via Transpose


I think the problem is with the comparison of the pointer ptr and with the pointer of the new array ptr2. But I’m not sure at all.

First of all I let the user type in an array of 2D and then I turned the array via its pointer into a Transpose and since arrays in C++ are actually 1D arrays in row major order I tried to just compare the values the pointers to the two arrays are pointing at. Somehow I don't know why but it’s not working. I know that it is maybe not the most efficient way but I want to learn and know why it’s not working.

#include <iostream>

using namespace std;

bool transponierte(int *ptr, int groesse, int c, int r) {
  bool symmetrisch;
  int array_neu[r][c];
  for (int i = 0; i < c; i++) {
    for (int j = 0; j < r; j++) {
      array_neu[j][i] = *ptr;
      ptr++;
    }
  }

  int *ptr2 = &array_neu[0][0];
  for (int i = 0; i < groesse; i++) {
    if (*ptr == *ptr2) {
      symmetrisch = true;
    }
    if (*ptr != *ptr2) {
      symmetrisch = false;
      break;
    }
    ptr++;
    ptr2++;
  }

  return symmetrisch;
}

int main() {
  int r, c;
  cout << "how many columns " << endl;
  cin >> c;
  cout << "how many rows " << endl;
  cin >> r;

  int array[c][r];
  int groesse = r * c;
  for (int i = 0; i < r; i++) {
    for (int j = 0; j < c; j++) {
      cout << "type in elemts for the array" << endl;
      cin >> array[j][i];
    }
  }

  bool trans = transponierte((int *)array, groesse, c, r);
  if (trans == true) {
    cout << "the matrix is not symmetric " << endl;
  }
  if (trans == false) {
    cout << "the matrix is not symmetric" << endl;
  }
  return 0;
}

Solution

  • This is what I would do with pointers :

    #include <cassert>
    #include <vector>
    #include <stdexcept>
    
    class matrix_t
    {
    public:
        
        // Dont focus too much on this constructor
        // it helps me making initialization of the content of
        // the matrix more easy
        template<std::size_t rows_v, std::size_t cols_v>
        explicit matrix_t(const int (&values)[rows_v][cols_v]) :
            m_columns{cols_v},
            m_rows{rows_v},
            m_data{new int[m_rows * m_columns]} // <== Allocate memory (normally use std::vector)
        {
            // point into data
            int* ptr = m_data;
    
            // copy the initialization data into contiguous memory
            for(std::size_t row = 0; row < m_rows; ++row)
            {
                for(std::size_t col = 0; col < m_columns; ++col)
                {
                    *ptr = values[row][col];
                    ++ptr;
                }
            }
        }
    
        ~matrix_t()
        {
            // always match new with a delete and a new[] with a delete[]
            delete[] m_data;
        }
    
        // function for calculating the right pointer
        // for row and column
        int* at(const std::size_t row, const std::size_t column)
        {
            int* ptr = m_data;
            ptr += 
            (
                (row * m_columns) +  // for each row you have to advance the pointer by m_columns (this is called stride)
                column // then add the column you need
           );
    
           return ptr;
        }
    
        bool is_symmetric()
        {
            // width and height match
            if (m_columns == m_rows)
            {
                // we only have to check values
                // - not on diagonal (they always match)
                // - in top-right of matrix (otherwise we will check values twice)
                for(std::size_t row = 0; row < m_rows; ++row)
                {
                    for(std::size_t col = row + 1; col < m_columns; ++col)
                    {
                        int* value1 = at(col,row);
                        int* value2 = at(row,col);
                        if ( *value1 != *value2  ) 
                        {
                            return false;
                        }
                    }
                }
    
                return true;
            }
    
            return false;
        }
    
    private:
        std::size_t m_columns;
        std::size_t m_rows;
        int* m_data;
    };
    
    int main()
    {
        matrix_t m1
        {{
            {1,0},
            {0,1}
        }};
        assert(m1.is_symmetric());
    
        matrix_t m2
        {{
            {1,0,2},
            {0,1,0},
            {2,0,1}
        }};
        assert(m2.is_symmetric());
    
        matrix_t m3
        {{
            {1,2,3},
            {0,1,0},
            {2,0,1}
        }};
        assert(!m3.is_symmetric());
    }