Foros del Web » Programación para mayores de 30 ;) » C/C++ »

problemas con punteros y matrices

Estas en el tema de problemas con punteros y matrices en el foro de C/C++ en Foros del Web. Hola amigos, estoy intentando hacer un ejercicio donde se pide la dimension de unas matrices y luego se suman y muestro el resultado de la ...
  #1 (permalink)  
Antiguo 07/02/2017, 05:16
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
problemas con punteros y matrices

Hola amigos, estoy intentando hacer un ejercicio donde se pide la dimension de unas matrices y luego se suman y muestro el resultado de la matriz final. El problema lo tengo en la parte donde solicito memoria dinamica para las matrices ya que da una excepcion. Este es mi codigo:
Código C++:
Ver original
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. void solicitar_dimensiones( int *f, int *c)
  6. {
  7.     cout << "Ingrese el numero de filas para la matriz : ";
  8.     cin >> *f;
  9.     cout << "\nIngrese el numero de columnas para la matriz : ";
  10.     cin >> *c;
  11. }
  12.  
  13. void pedir_memoria(int ***a,int f,int c)
  14. {
  15.     *a= new int*[f];
  16.     for (int i = 0; i <f; i++)
  17.     {
  18.         *(a[i]) = new int[c];
  19.     }
  20. }
  21.  
  22. void rellenar_matriz(int ***a,int indice,int f,int c)
  23. {
  24.     cout << "\nIngrese los valores de la matriz " << indice <<" : ";
  25.     for (int i = 0; i < f; i++)
  26.     {
  27.         for (int j = 0; j < c; j++)
  28.         {
  29.             cout << "\nIngrese el elemento [ " << i << ", " << j << " ]: ";
  30.             cin >> *(a[i][j]);
  31.         }
  32.         printf("\n");
  33.     }
  34. }
  35.  
  36. void sumar_matrices (int ***a,int ***puntm2,int ***puntm,int f, int c)
  37. {
  38.     for (int i = 0; i < f; i++)
  39.     {
  40.         for (int j = 0; j < c; j++)
  41.         {
  42.             *(a[i][j])= *(puntm[i][j]) + *(puntm2[i][j]);
  43.         }
  44.     }
  45. }
  46.  
  47. void liberar_memoria(int **a,int f)
  48. {
  49.     for (int i = 0; i <f; i++)
  50.     {
  51.         delete[] a[i];
  52.     }
  53.     delete[] a;
  54. }
  55.  
  56. void imprimir_matriz(int **a, int f, int c )
  57. {
  58.     cout << "\nLa matriz final es: \n";
  59.     for (int i = 0; i < f; i++)
  60.     {
  61.         for (int j = 0; j < c; j++)
  62.         {
  63.             cout << a[i][j] <<endl;
  64.         }
  65.     }
  66. }
  67.  
  68. int main()
  69. {
  70.     int f,c;
  71.     int **psumas;
  72.     int **pmatriz2;
  73.     int **pmatriz1;
  74.  
  75.     solicitar_dimensiones(&f,&c);
  76.     pedir_memoria(&pmatriz1,f,c);
  77.     pedir_memoria(&pmatriz2,f,c);
  78.     pedir_memoria(&psumas,f,c);
  79.  
  80.     rellenar_matriz(&pmatriz1,1,f,c);
  81.     rellenar_matriz(&pmatriz2,2,f,c);
  82.  
  83.     sumar_matrices(&psumas,&pmatriz2,&pmatriz1,f,c);
  84.  
  85.     imprimir_matriz(psumas,f,c);
  86.  
  87.     liberar_memoria(pmatriz1,f);
  88.     liberar_memoria(pmatriz2,f);
  89.     liberar_memoria(psumas,f);
  90.     return 0;
  91. }

¿alguien podria ayudarme indicando donde esta el fallo y como solucionarlo?
  #2 (permalink)  
Antiguo 07/02/2017, 06:25
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problemas con punteros y matrices

He estado intentando solucionarlo pero tengo un lio muy gordo. Ahora mismo lo tengo asi pero al rellenar el array lo desbordo y no veo como hacerlo de la forma correcta:
Código C++:
Ver original
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. void solicitar_dimensiones( int *f, int *c)
  6. {
  7.     cout << "Ingrese el numero de filas para la matriz : ";
  8.     cin >> *f;
  9.     cout << "\nIngrese el numero de columnas para la matriz : ";
  10.     cin >> *c;
  11. }
  12.  
  13. void pedir_memoria(int ***a,int f,int c)
  14. {
  15.     a[0]= new int*[f];
  16.     for (int i = 0; i <f; i++)
  17.     {
  18.         a[0][i] = new int[c];
  19.     }
  20. }
  21.  
  22. void rellenar_matriz(int ***a,int indice,int f,int c)
  23. {
  24.     cout << "\nIngrese los valores de la matriz " << indice <<" : ";
  25.     for (int i = 0; i < f; i++)
  26.     {
  27.         for (int j = 0; j < c; j++)
  28.         {
  29.             cout << "\nIngrese el elemento [ " << i << ", " << j << " ]: ";
  30.             cin >> *a[i][j];
  31.         }
  32.         printf("\n");
  33.     }
  34. }
  35.  
  36. void sumar_matrices (int ***a,int ***puntm2,int ***puntm,int f, int c)
  37. {
  38.     for (int i = 0; i < f; i++)
  39.     {
  40.         for (int j = 0; j < c; j++)
  41.         {
  42.             *(a[i][j])= *(puntm[i][j]) + *(puntm2[i][j]);
  43.         }
  44.     }
  45. }
  46.  
  47. void liberar_memoria(int **a,int f)
  48. {
  49.     for (int i = 0; i <f; i++)
  50.     {
  51.         delete[] a[i];
  52.     }
  53.     delete[] a;
  54. }
  55.  
  56. void imprimir_matriz(int **a, int f, int c )
  57. {
  58.     cout << "\nLa matriz final es: \n";
  59.     for (int i = 0; i < f; i++)
  60.     {
  61.         for (int j = 0; j < c; j++)
  62.         {
  63.             cout << a[i][j] <<endl;
  64.         }
  65.     }
  66. }
  67.  
  68. int main()
  69. {
  70.     int f,c;
  71.     int **psumas;
  72.     int **pmatriz2;
  73.     int **pmatriz1;
  74.  
  75.     solicitar_dimensiones(&f,&c);
  76.     pedir_memoria(&pmatriz1,f,c);
  77.     pedir_memoria(&pmatriz2,f,c);
  78.     pedir_memoria(&psumas,f,c);
  79.  
  80.     rellenar_matriz(&pmatriz1,1,f,c);
  81.     rellenar_matriz(&pmatriz2,2,f,c);
  82.  
  83.     sumar_matrices(&psumas,&pmatriz2,&pmatriz1,f,c);
  84.  
  85.     imprimir_matriz(psumas,f,c);
  86.  
  87.     liberar_memoria(pmatriz1,f);
  88.     liberar_memoria(pmatriz2,f);
  89.     liberar_memoria(psumas,f);
  90.     return 0;
  91. }
  #3 (permalink)  
Antiguo 07/02/2017, 06:26
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: problemas con punteros y matrices

Quizá te estás complicando la vida con tu manera de definir las matrices. En lugar de utilizar triples y dobles punteros, yo te sugiero el empleo de una estructura de datos, por ejemplo:

Código C++:
Ver original
  1. typedef struct
  2. {
  3.     int fil;
  4.     int col;
  5.     int **A;
  6. }
  7. T_Matriz;
  8.  
  9. void pedir_memoria(T_Matriz *M, int f, int c)
  10. {
  11.     M->fil = f;
  12.     M->col = c;
  13.     M->A = new int*[f];
  14.     for (int i=0; i<c; i++)
  15.         M->A[i] = new int[c];
  16. }

y de un modo similar para todas las funciones que vayas a crear para operar con matrices.

Si quieres, aprovecha para comprobar (en función de lo que quieras hacer) que el número de filas y/o columnas es el correcto, si el apuntador A corresponde o no a un bloque de datos válido, etc.

Ya que estás empleando C++, ¿Por qué no implementas las matrices y sus operaciones como una clase?

Saludos,
  #4 (permalink)  
Antiguo 07/02/2017, 10:51
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problemas con punteros y matrices

Es que es un ejercicio precisamente de punteros y matrices y la idea es acerlo así como hago para entender bien su uso. Tiene que ser como lo hago.
He visto que hacen algo similar en una duda de un foro y lo ponen asi:
Código C++:
Ver original
  1. *(*(*matS+i)+j) = *(*(matA + i) + j) + *(*(matB + i) + j);
Sí cojo ese mismo código y lo convierto usando indices:
Código C++:
Ver original
  1. *matS[i][j] = matA[i][j] + matB[i][j];
Ya no funciona. ¿alguien me puede explicar esto? ¿acaso no puedo usar índices para desplazarme por una matriz de este tipo cuando se usa memoria dinámica?

Última edición por aguml; 07/02/2017 a las 11:13
  #5 (permalink)  
Antiguo 07/02/2017, 14:42
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: problemas con punteros y matrices

Quieres representar una matriz mediante un doble puntero, con el fin de poder utilizar la notación clásica para los elementos de la matriz.

El primer fallo está en la función pedir_memoria():

Código C++:
Ver original
  1. void pedir_memoria(int ***a,int f,int c)

Con esa declaración, lo que estoy diciendo es "paso la dirección de un doble puntero para poderlo modificar". Es decir, el parámetro a representa un puntero a un doble puntero.

Para poder modificar un pàrámetro por referencia, tengo que decir "lo apuntado por a es igual a ...", luego ya tenemos fallo en la primera línea de la función. Debería ser:

Código C++:
Ver original
  1. *a = new int*[f]

o bien, empleando una variable intermedia (creo que te quedará más claro), dejar tu función pedir_memoria() como:

Código C++:
Ver original
  1. void pedir_memoria(int ***a,int f,int c)
  2. {
  3.     int **b;
  4.  
  5.     b = new int*[f];
  6.     for (int i = 0; i <f; i++)
  7.     {
  8.         b[i] = new int[c];
  9.     }
  10.     *a = b;
  11. }

Ves que dentro del bucle solamente se emplea un índice. Ese era otro fallo en tu código original, ten en cuenta que, ahora, b es un arreglo de punteros, cada uno de ellos apuntará a un arreglo de enteros. que es lo que constituirán las filas.

Una vez establecido que las matrices las estabas generando mal, ya sabes por qué te daba la excepción: estabas metiendo en memoria lo que no debías en donde no debías.

Para las demás funciones ya no necesitas el triple puntero puesto que ya no necesitas modificar el doble puntero. Pasando éste directamente, ya tienes acceso a los elementos sin necesidad de complicarte la vida (ya estás pasando las direcciones al pasar el puntero). Por ejemplo:

Código C++:
Ver original
  1. void rellenar_matriz(int **a, int indice, int f, int c)
  2. {
  3.     cout << "\nIngrese los valores de la matriz " << indice <<" : ";
  4.     for (int i = 0; i < f; i++)
  5.     {
  6.         for (int j = 0; j < c; j++)
  7.         {
  8.             cout << "\nIngrese el elemento [ " << i << ", " << j << " ]: ";
  9.             cin >> a[i][j];
  10.         }
  11.         printf("\n");
  12.     }
  13. }

y de una forma similar deberás modificar la función sumar_matrices().

En tu función main(), las llamadas a pedir_memoria() serían correctas, pero no las llamadas a rellenar_matriz() y sumar_matrices(). También serán correctas las llamadas a imprimir_matriz() y liberar_memoria(). Pero, en el caso de la función liberar_memoria(), ten en cuenta que pmatriz1, pmatriz2 y psumas siguen apuntando a un bloque de memoria que ya se liberó. En este caso no tiene importancia, dado que el programa se acaba, pero puede dar lugar a problemas si no tienes cuidado en programas grandes en donde pretendas reutilizar esas variables.

Sobre la conversión usando índices... bueno, si partíamos de una matriz mal creada... pero, de todos modos, con lo que te he contado, no necesitarás el triple índice más que en la creación de la matriz.

Espero haber arrojado algo de claridad sobre el tema.

Saludos,
  #6 (permalink)  
Antiguo 07/02/2017, 17:01
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problemas con punteros y matrices

No termino de entenderlo porque en mi primer código lo tenia como indicas y usaba un solo indice y fallaba igual. ¿te importaría coger la función pedir_memoria de mi primer código y corregir lo que veas mal? Y así puedo ver el fallo porque me tiene loco y no lo termino de entender. Me gustaría hacerlo sin usar una variable intermedia porque la idea es enterarse bien de como hacerlo directamente. Gracias por tu tiempo.
  #7 (permalink)  
Antiguo 08/02/2017, 03:27
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: problemas con punteros y matrices

Te incluyo un programa de ejemplo, hecho con Codeblocks versión 16.01 y MinGW 4.9.2 (32 bits)

Las funciones pedir_memoria_1() y borrar_memoria_1(), que utilizan directamente el puntero, me provocan ambas un error de segmentación.

Las funciones pedir_memoria_2() y borrar_memoria_2(), que (en teoría) funcionan como las versiones _1, pero utilizando una variable intermedia, me funcionan perfectamente. La función borrar_memoria_2() lo que hace es poner el puntero original a NULL una vez que libera la memoria (ya te comenté por qué hacerlo así).

La función borrar_memoria_3() es la tuya original.

La función matriz_prueba() es para comprobar que la matriz se ha creado correctamente.

¿Por qué funcionan las versiones que usan una variable intermedia y las otras no? Francamente, no lo sé, pero habiendo un modo de que funcione...

Código C++:
Ver original
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. void pedir_dimension (int *f, int *c);
  6. void pedir_memoria_1 (int ***a, int f, int c);
  7. void pedir_memoria_2 (int ***a, int f, int c);
  8. void matriz_prueba   (int **a,  int f, int c);
  9. void imprimir_matriz (int **a,  int f, int c);
  10. void borrar_matriz_1 (int ***a, int f, int c);
  11. void borrar_matriz_2 (int ***a, int f, int c);
  12. void borrar_matriz_3 (int **a, int f, int c);
  13.  
  14. int main()
  15. {
  16.     int    fils, cols;
  17.     int    **A;
  18.  
  19.     pedir_dimension(&fils, &cols);
  20.     //pedir_memoria_1(&A, fils, cols);
  21.     pedir_memoria_2(&A, fils, cols);
  22.     matriz_prueba(A, fils, cols);
  23.     imprimir_matriz(A, fils, cols);
  24.     //borrar_matriz_1(&A, fils, cols);
  25.     borrar_matriz_2(&A, fils, cols);
  26.     //borrar_matriz_3(A, fils, cols);
  27.  
  28.     return 0;
  29. }
  30.  
  31. void pedir_dimension (int *f, int *c)
  32. {
  33.     cin >> "Filas: "
  34.     cin >> *f;
  35.     cin >> "Columnas: ";
  36.     cin >> *c;
  37.  
  38.     cout << endl;
  39. }
  40.  
  41. void pedir_memoria_1 (int ***a, int f, int c)
  42. {
  43.     *a = new int*[f];
  44.     for (int i=0; i<f; i++)
  45.     {
  46.         *a[i] = new int[c];
  47.     }
  48. }
  49.  
  50. void pedir_memoria_2 (int ***a, int f, int c)
  51. {
  52.     int **b;
  53.  
  54.     b = new int*[f];
  55.     for (int i=0; i<f; i++)
  56.     {
  57.         b[i] = new int[c];
  58.     }
  59.     *a = b;
  60. }
  61.  
  62. void matriz_prueba (int **a, int f, int c)
  63. {
  64.     for (int i=0; i<f; i++)
  65.         for (int j=0; j<c; j++)
  66.             a[i][j] = 10*(i+1) + (j+1);
  67. }
  68.  
  69. void imprimir_matriz (int **a, int f, int c)
  70. {
  71.     for (int i=0; i<f; i++)
  72.     {
  73.         for (int j=0; j<c; j++)
  74.         {
  75.             cout << a[i][j] << " ";
  76.         }
  77.         cout << endl;
  78.     }
  79. }
  80.  
  81. void borrar_matriz_1 (int ***a, int f, int c)
  82. {
  83.     for (int i=0; i<f; i++)
  84.         delete[] *a[i];
  85.     delete[] *a;
  86.     *a = NULL;
  87. }
  88.  
  89. void borrar_matriz_2 (int ***a, int f, int c)
  90. {
  91.     int **b;
  92.  
  93.     b = *a;
  94.     for (int i=0; i<f; i++)
  95.         delete[] b[i];
  96.     delete[] b;
  97.     *a = NULL;
  98. }
  99.  
  100. void borrar_matriz_3 (int **a, int f, int c)
  101. {
  102.     for (int i=0; i<f; i++)
  103.         delete[] a[i];
  104.     delete[] a;
  105. }

De todos modos, me pica la curiosidad, voy a probar utilizando C puro y duro con malloc() a ver qué pasa. Ya te comentaré.

Saludos,
  #8 (permalink)  
Antiguo 22/02/2017, 16:01
 
Fecha de Ingreso: junio-2009
Mensajes: 64
Antigüedad: 14 años, 9 meses
Puntos: 6
Respuesta: problemas con punteros y matrices

Fw190, esta muy bueno, pero marco un detalle, escribis:

Código C:
Ver original
  1. cin >> "Filas: "
  2.     cin >> *f;
  3.     cin >> "Columnas: ";
  4.     cin >> *c;

debería ser:

Código C:
Ver original
  1. cout >> "Filas: "
  2.     cin >> *f;
  3.     cout >> "Columnas: ";
  4.     cin >> *c;

Sino tira muchos errores...
  #9 (permalink)  
Antiguo 23/02/2017, 05:16
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: problemas con punteros y matrices

Tienes razón, no fue más que un simple error de copia/pega.

Etiquetas: int, main, matrices, punteros
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 05:56.