Segmentation fault (core dumped)

2

I'm working with makefiles, when compiling the following code, the random option works perfectly, but in the option to enter the matrix using the keyboard, this Segmentation fault (core dumped) comes out, could you tell me why this is wrong or what is wrong in the code? , please.

The error originates after entering the matrix ( user(b, N, P); ). I think the error is in the printm(b, N, P); function.

function.h

#ifndef function_H
#define function_H

int user(int **m, int N, int P);
void printm(int **m, int N, int P);
int generator(int **m, int N, int P);
void lmax(int **m, int N, int P);

#endif

function.cc

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include "function.h"

using namespace std;

int user(int **m, int N, int P)
{
    for (int i=0; i<N; i++)
    {
        for (int j=0; j<P; j++)
        {   
            cin >> m[i][j];
        }
    }
    return 0;
}

void printm(int **m, int N, int P)
{
    int i;
    for (i=0; i<N; i++);
    {
        for (int j=0; j<P; j++)
        {
            cout << " " << m[i][j] << " ";
        }
        cout << endl;
    }
}

int generator(int **m, int N, int P)
{
    srand(time(NULL));
    for (int i=0; i<N; i++)
    {
        for (int j=0; j<P; j++)
        {
            m[i][j] = rand()%50-0;
            cout << " " << m[i][j] << "\t";
        }
        cout << endl;
    }
    cout << endl;

    return 0;
}

void lmax(int **m, int N, int P)
{
    int j_max;
    for (int i=0; i<N; i++)
    {
        j_max = 0;
        for (int j=1; j<P; j++)
            if (m[i][j_max] < m[i][j]) 
            {
                j_max = j;
            }
        m[i][j_max] = 0;
    }

    for (int i=0; i<N; i++) {
        for (int j=0; j<P; j++)  {
            cout << " " << m[i][j] << "\t";  }
        cout << endl;  }
    cout << endl;

    bool kl = true;
    for (int i=1; i<N; i++)
    {
        for (int j=0; j<i; j++)
        {
            if (m[i][j] != m[j][i])
                kl = false;
        }
    }
    if (kl)
    {
        cout << " Symetric matrix." << endl;
    }
    else
    {
        cout << " Not symetric matrix." << endl;
    }

    cout << endl;
}

test.cc

#include <stdio.h>
#include <iostream>
#include "function.h"

using namespace std;

int main()
{
    int N, P, **a, **b;
    char ch;

    cout << "\n 1 - Initialize matrix by using a random number generator." << endl;
    cout << " 2 - Initialize matrix via user input." << endl;
    cout << " 0 - Exit." << endl;
    cout << "\n Your choice: ";

    do {
        ch = getchar();
        switch(ch)
        {
            case '1':
                cout << "\n Rows: ";
                cin >> N;  
                cout << " Columns: ";
                cin >> P;  cout << endl;
                a = new int *[N];
                for (int i=0; i<N; i++)
                {
                    a[i] = new int [P];
                }
                generator(a, N, P);
                lmax(a, N, P);
                return 0;

            case '2':
                cout << "\n Rows: ";
                cin >> N;  
                cout << " Columns: ";
                cin >> P;  cout << endl; 
                b = new int *[N];
                for (int i=0; i<N; i++)
                {
                    b[i] = new int [P];
                }
                user(b, N, P);
                printm(b, N, P);
                lmax(b, N, P);
                return 0;
        }
    }
    while(ch != '0');

    return 0;
}
    
asked by Neon 25.05.2016 в 16:17
source

2 answers

3

These are the functions that had an error. They are already corrected.

int user(int **m, int N, int P)
{
    for (int i=0; i<N; i++)
    {
        for (int j=0; j<P; j++)
        {   
            cin >> m[i][j];
        }
    }

     return 0;
}

void printm(int **m, int N, int P)
{
    int i;
    for (i=0; i<N; i++)
    {
        for (int j=0; j<P; j++)
        {
            cout << " " << m[i][j] << " ";
        }
        cout << endl;
    }
}

You had a bad return in the user function and a ; in the first cycle of the printm function

    
answered by 25.05.2016 / 18:38
source
3

In this answer I will assume that a requirement of the practice is to use dynamic memory. If not, you should consider rewriting the program using vectors or encapsulating the use of dynamic memory in a class (if you do not violate any rule marked by practice).

The duplicate code is usually a good friend of the errors because before the need to make a change or make exactly the same change in all the places where the duplicates are or the program will start giving problems.

We're going to do some refactoring to see if we can get a more readable code.

Your program handles matrices. Unless it is an explicit requirement of the practice the ideal would be that all the information concerning the matrix travel always together:

struct Matrix
{
  int** datos;
  int Filas;
  int Columnas;
};

At the moment we are not going to complicate the example with the use of constructors.

The fact is that in your exercise you are creating matrices in two different places. Therefore, the idea of having a mechanism that allows creating a matrix is interesting. A function is perfectly adapted to our needs

Matrix NuevaMatriz(int filas, int columnas)
{
  Matrix matriz;
  matriz.datos = new int[filas];

  for( int i=0; i<filas; i++ )
    matriz.datos[i] = new int[columnas];

  return matriz;
}

Of course we can not consider in a program to make memory reservations without cleaning it later ... it is necessary to create another function to release the reserved memory:

void BorrarMatriz(Matrix & matriz)
{
  for( int i=0; i<filas; i++ )
    delete[] matriz.datos[i];

  delete[] matriz.datos;

  matriz.datos = nullptr;
}

Another element that you have duplicated is the function to fill the matrix. In your specific case you could do this with a single function, since the only difference lies in the data source (standard input or random generator).

It is in this part of your code where your error is found. Compare the two functions carefully:

int user(int **m, int N, int P)
{
    for (int i=0; i<N; i++)
    {
        for (int j=0; j<P; j++)
        {   
            cin >> m[i][j];
        }
        return 0;
    }
}

int generator(int **m, int N, int P)
{
    srand(time(NULL));
    for (int i=0; i<N; i++)
    {
        for (int j=0; j<P; j++)
        {
            m[i][j] = rand()%50-0;
            cout << " " << m[i][j] << "\t";
        }
        cout << endl;
    }
    cout << endl;

    return 0;
}

In spite of doing exactly the same they look quite different ... especially it is striking to find us with a return in the function user within the first loop (your error).

How can this be simplified? There is a whole range of options. Here are some ideas:

An option, since traversing the matrix is usually recurrent in your exercise, you can encapsulate that loop in a function and execute "something" in each iteration:

void MatrixLoop(Matrix& matriz, std::function<void(int&,int,int)> func)
{
  for( int i=0; i<matriz.Filas; i++ )
  {
    for( int j=0; j<matriz.Columnas; j++ )
    {
      // A la función le proporcionamos el valor actual de la matriz por
      // referencia para poder modificarlo, la fila y la columna.
      func(matriz[i][j],i,j);
    }
  }
}

void RellenarPorUsuario(int& dato, int fila, int columna)
{
  std::cout << "Valor para (" << fila << "," << columna << "): ";
  std::cin >> dato;
}

void RellenarAleatoriamente(int& dato, int fila, int columna)
{
  static bool init = false;

  if( !init )
  {
    init = true;
    srand(time(NULL)); 
  }

  dato = rand()%50;
}

// ...
case 1:
{
  int filas, columnas;
  std::cout << "\n Rows: ";
  std::cin >> filas;  
  std::cout << " Columns: ";
  std::cin >> columnas;

  Matrix matriz = NuevaMatriz(filas,columnas);
  MatrixLoop(matriz, RellenarAleatoriamente);
  // ...
  BorrarMatriz(matriz);

  break;
}

case 2:
{
  int filas, columnas;
  std::cout << "\n Rows: ";
  std::cin >> filas;  
  std::cout << " Columns: ";
  std::cin >> columnas;

  Matrix matriz = NuevaMatriz(filas,columnas);
  MatrixLoop(matriz, RellenarPorUsuario);
  // ...
  BorrarMatriz(matriz);

  break;
}

You can also use lambdas to get a more readable code:

void MatrixLoop(Matrix& matriz, std::function<void(int&,int,int)> func)
{
  for( int i=0; i<matriz.Filas; i++ )
  {
    for( int j=0; j<matriz.Columnas; j++ )
    {
      // A la función le proporcionamos el valor actual de la matriz por
      // referencia para poder modificarlo, la fila y la columna.
      func(matriz[i][j],i,j);
    }
  }
}

void RellenarPorUsuario(Matrix& matriz)
{
  std::function<void(int&,int,int)> lambda = [](int& dato, int fila, int columna )
  {
    std::cout << "Valor para (" << fila << "," << columna << "): ";
    std::cin >> dato;
  };

  MatrixLoop(matriz,lambda);
}

void RellenarAleatoriamente(Matrix& matriz)
{
  std::function<void(int&,int,int)> lambda = [](int& dato, int, int)
  {
    dato = rand()%50;
  };

  srand(time(NULL)); 
  MatrixLoop(matriz,lambda);
}

// ...
case 1:
{
  int filas, columnas;
  std::cout << "\n Rows: ";
  std::cin >> filas;  
  std::cout << " Columns: ";
  std::cin >> columnas;

  Matrix matriz = NuevaMatriz(filas,columnas);
  RellenarAleatoriamente(matriz);
  // ...
  break;
}

case 2:
{
  int filas, columnas;
  std::cout << "\n Rows: ";
  std::cin >> filas;  
  std::cout << " Columns: ";
  std::cin >> columnas;

  Matrix matriz = NuevaMatriz(filas,columnas);
  RellenarPorUsuario(matriz);
  // ...

  break;
}

And well, it would only be necessary to print the matrix:

void Imprimir(Matrix const& matriz)
{
  auto lambda = [](int& dato, int, int columna)
  {
    if( columna == 0 )
      std::cout << '\n';
    else
      std::cout << ' ';

    std::cout << dato;
  }

  LoopMatrix(matriz, lambda);
}

Another option, with a simpler and modest but also more rigid code, could be that you have a single function RellenarMatriz that receives a bool (or even a enum if you want to be more flexible). Depending on the value of that variable, it will take one data entry or another:

void RellenarMatriz(Matrix & matriz, bool esRandom)
{
  srand(time(NULL)); 

  for( int i=0; i<matriz.Filas; i++ )
  {
    for( int j=0; j<matriz.Columnas; j++ )
    {
      if( esRandom )
        matriz[i][j] = rand()%50;
      else
      {
        std::cout << "Valor para (" << i<< "," << j<< "): ";
        std::cin >> matriz[i][j];
      }
    }
  }
}

In a similar way you could act before the entry of the values fila and columna , that I leave it to you to practice if you see yourself with energy.

Of the segmentation fault that you mention, I do not see a trace, but it is also true that the implementation of lmax is missing ...

Greetings.

    
answered by 25.05.2016 в 17:00