Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: ERIK546 en 1 Julio 2012, 05:46 am



Título: ¿Cómo dimensionar un doble apuntador?
Publicado por: ERIK546 en 1 Julio 2012, 05:46 am
Hola a todos los expertos en programación en C, esta vez me han surgido dudas al hacer un programa que multiplique dos matrices de tamaños "m x n" y "n x p". Sin embargo no subiré tanto código esta vez para explicarles mi duda, ya que la considero un error de concepto acerca de los dobles apuntadores.
Lo que se pretende es dimensionar un doble apuntador, ya que yo considero un doble apuntador como un arreglo de dos dimensiones, sin embargo estas se pueden dimensionar con la función "malloc".
Viéndolo de esta forma la primera matriz sería "a[m][n]", la segunda matriz "b[n][p]" y la matriz resultante "c[m][p]". Sin embargo el doble apuntador; "a", "b" y "c", deben dimensionarse según los diferentes valores de "m", "n" y "p". Agradecería que me explicaran la forma de hacerlo, les dejo la forma en que lo dimensioné el doble apuntador "a" pero solo lo hice para el valor de "m" y para el valor correspondiente a "n" en ese doble apuntador no sabría como hacerlo. De forma que me quede un doble apuntador "a[m][n]". Gracias de antemano.

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6.    int **a;
  7.    a=(int**)malloc(sizeof(int*)*m);
  8.  
  9.  
  10.    system("PAUSE");
  11.    return 0;
  12. }  
  13.  
  14.  


Título: Re: ¿Cómo dimensionar un doble apuntador?
Publicado por: Anvil en 1 Julio 2012, 06:55 am
Código
  1. // ejemplo de http://www.eskimo.com/~scs/cclass/int/sx9b.html
  2.  
  3. #include <iostream>
  4.  
  5. int main(int argc, const char * argv[])
  6. {
  7. // numero de filas
  8. const int nrows = 5;
  9. // numero de columnas
  10. const int ncolumns = 3;
  11.  
  12. // declaración del arreglo
  13. int **array;
  14. array = (int **)malloc(nrows * sizeof(int *));
  15. // si no se pudo reservar memoria
  16. if(array == NULL)
  17. {
  18. // mandar mensaje de error
  19. fprintf(stderr, "out of memory\n");
  20. return 0;
  21. }
  22.  
  23. // recorremos las filas
  24. for(int i = 0; i < nrows; i++)
  25. {
  26. // reservamos memoria en cada fila
  27. array[i] = (int * )malloc(ncolumns * sizeof(int));
  28. if(array[i] == NULL)
  29. {
  30. fprintf(stderr, "out of memory\n");
  31. return 0;
  32. }
  33. }
  34.  
  35. // se llena el arreglo
  36. for(int i = 0; i < nrows; i++)
  37. {
  38. for(int j = 0; j < ncolumns; j++)
  39. {
  40. array[i][j] = i + j;
  41. }
  42. }
  43.  
  44. free(array);
  45.    return 0;
  46. }
  47.  


Título: Re: ¿Cómo dimensionar un doble apuntador?
Publicado por: david_BS en 1 Julio 2012, 19:00 pm

El ejemplo que te mostraron está muy bien. Pero para que entiendas el concepto de doble puntero te muestro este código de ejemplo que había publicado hace un tiempo aquí:
http://foro.elhacker.net/programacion_cc/manipulacion_de_punteros_ejemplo_con_float-t358223.0.html

Código
  1. float vec1[5]={ 0.5f, 0.2f, 0.22f, 0.01f, 0.0f };
  2. float vec2[5]={ 0.5f, 0.2f, 0.22f, 0.01f, 0.0f };
  3. float vec3[5]={ 0.5f, 0.2f, 0.22f, 0.01f, 0.0f };
  4. float* pf1[3]; //vector de punteros a vectores de float
  5. pf1[0]=&vec1[0];
  6. pf1[1]=&vec2[0];
  7. pf1[2]=&vec3[0];
  8.  
  9. float** ppf1;
  10. ppf1 = (float**)&pf1;//se le asigna la direccion de un vector de punteros a vectores de float
  11.  

osea, el concepto de que un doble puntero es un puntero el cual apunta a otro puntero. y dicho puntero debe apuntar a una región
de memoria asignada en el programa. si usás asignación dinámica, entonces si tenés que hacer como en el ejemplo que te mostraron.



Título: Re: ¿Cómo dimensionar un doble apuntador?
Publicado por: ERIK546 en 2 Julio 2012, 00:50 am
Muchas gracias a todos por sus respuestas, gracias a ellas he podido completar mi programa que multiplica matrices de cualquier tamaño (siempre y cuando sea posible). Pero mi programa presenta un error en la ejecución ya que aunque devuelve el resultado esperado, al finalizar el programa marca un error ".exe" que lo hace finalizar casi de inmediato. Agradecería que me ayudaran a identificar el problema ya que yo no he podido.
Les dejo el código:

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6.    int **a;
  7.    int **b;
  8.    int **c;
  9.    int m,u,n,p,i,j,k,t;
  10.    printf("Programa que multiplica dos matrices m * u y n * p y regresa la traza de la matriz resultante\n");
  11.    printf("Introdue m\n");
  12.    scanf("%d",&m);
  13.    printf("Introduce u\n");
  14.    scanf("%d",&u);
  15.    printf("Introduce n\n");
  16.    scanf("%d",&n);
  17.    printf("Introduce p\n");
  18.    scanf("%d",&p);
  19.    a=(int**)malloc(sizeof(int*)*m);
  20.    b=(int**)malloc(sizeof(int*)*n);
  21.    c=(int**)malloc(sizeof(int*)*m);
  22.  
  23.    if(u==n){
  24.             for(i=1;i<=m;i++){
  25.                               a[i]=(int*)malloc(sizeof(int)*u);
  26.                               }
  27.             for(i=1;i<=n;i++){
  28.                               b[i]=(int*)malloc(sizeof(int)*p);
  29.                               }
  30.             for(i=1;i<=m;i++){
  31.                               c[i]=(int*)malloc(sizeof(int)*p);
  32.                               }
  33.  
  34.             for(i=1;i<=m;i++){
  35.                      for(j=1;j<=u;j++){
  36.                                        printf("Introduce los valores %d-%d de la primera matriz\n",i,j);
  37.                                        scanf("%d",&a[i][j]);
  38.                                       }
  39.                      }
  40.  
  41.             for(i=1;i<=n;i++){
  42.                               for(j=1;j<=p;j++){
  43.                                                 printf("Introduce los valores %d-%d de la segunda matriz\n",i,j);
  44.                                                 scanf("%d",&b[i][j]);
  45.                                                 }
  46.                               }
  47.  
  48.                               for(i=1;i<=m;i++){
  49.                                                 for(j=1;j<=p;j++){
  50.                                                                   c[i][j]=0;
  51.                                                                   for(k=1;k<=n;k++){
  52.                                                                                     c[i][j]+=a[i][k]*b[k][j];
  53.                                                                                     }
  54.                                                                   }
  55.                                                 }
  56.             printf("La matriz resultante es:\n");
  57.                        for(i=1;i<=m;i++){
  58.                                          printf("\n");
  59.                                          for(j=1;j<=p;j++){
  60.                                                            printf("%d   ",c[i][j]);
  61.                                                            }
  62.                                          }
  63.                        }
  64.  
  65.             free(a);
  66.             free(b);
  67.             free(c);
  68.    system("PAUSE");
  69.    return 0;
  70. }
  71.  


Título: Re: ¿Cómo dimensionar un doble apuntador?
Publicado por: durasno en 2 Julio 2012, 06:44 am
Hola! una pregunta, empezas los indices de las matrices en 1 por que te parece mas comodo??? o porque no sabes que empieza en cero??

El problema es que estas accediendo fuera de la memoria asignada por malloc. Supongamos que creas un arreglo dinamico de 5 elementos, y si vos haces i=1 y en la condicion del for pones i<=5; cuando ingresas datos se almacenan en las posiciones 1 2 3 4 5 del arreglo, PERO los arreglos empiezan desde el cero, posiciones: 0 1 2 3 4 (cinco posiciones), por lo tanto arr[5] no pertenece al arreglo.... y a esto se debe el error del programa(aplicado a las matrices)

Soluciones: si usas i=1, vas a teneer q reservar un elemento mas; ó usas i=0 y en la condicion i<n (lo cual es mas optima ya que no desperdicias un elemento)


Para liberar la memoria reservada, se hace el proceso inverso a como lo reservaste, ej:
Código
  1. for(i=0; i<m; i++)
  2.   free(a[i]);
  3. free(a);
y asi para las demas matrices.... Saludos


Título: Re: ¿Cómo dimensionar un doble apuntador?
Publicado por: ERIK546 en 2 Julio 2012, 08:02 am
Hola! una pregunta, empezas los indices de las matrices en 1 por que te parece mas comodo??? o porque no sabes que empieza en cero??

El problema es que estas accediendo fuera de la memoria asignada por malloc. Supongamos que creas un arreglo dinamico de 5 elementos, y si vos haces i=1 y en la condicion del for pones i<=5; cuando ingresas datos se almacenan en las posiciones 1 2 3 4 5 del arreglo, PERO los arreglos empiezan desde el cero, posiciones: 0 1 2 3 4 (cinco posiciones), por lo tanto arr[5] no pertenece al arreglo.... y a esto se debe el error del programa(aplicado a las matrices)

Soluciones: si usas i=1, vas a teneer q reservar un elemento mas; ó usas i=0 y en la condicion i<n (lo cual es mas optima ya que no desperdicias un elemento)


Para liberar la memoria reservada, se hace el proceso inverso a como lo reservaste, ej:
Código
  1. for(i=0; i<m; i++)
  2.   free(a[i]);
  3. free(a);
y asi para las demas matrices.... Saludos
Muchísimas gracias durasno; efectivamente utilice los ciclos desde "i=1" debido a que me pareció más cómodo utilizarlos de esa forma para referirme a los espacio 1-1, etc. Y el problema residía en la dimensión de las filas, así como en la liberación de la memoria. Lo he corregido y le he agregado un ciclo que regresa la traza de la matriz resultante. Gracias a todos por su oportuna ayuda. Les dejo el código correspondiente:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6.    int **a;
  7.    int **b;
  8.    int **c;
  9.    int m,u,n,p,i,j,k,t;
  10.    printf("Programa que multiplica dos matrices m * u y n * p y regresa la traza de la matriz resultante\n");
  11.    printf("Introdue m\n");
  12.    scanf("%d",&m);
  13.    printf("Introduce u\n");
  14.    scanf("%d",&u);
  15.    printf("Introduce n\n");
  16.    scanf("%d",&n);
  17.    printf("Introduce p\n");
  18.    scanf("%d",&p);
  19.    a=(int**)malloc(sizeof(int*)*m);
  20.    b=(int**)malloc(sizeof(int*)*n);
  21.    c=(int**)malloc(sizeof(int*)*m);
  22.  
  23.    if(u==n){
  24.             for(i=0;i<m;i++){
  25.                               a[i]=(int*)malloc(sizeof(int)*u);
  26.                               }
  27.             for(i=0;i<n;i++){
  28.                               b[i]=(int*)malloc(sizeof(int)*p);
  29.                               }
  30.             for(i=0;i<m;i++){
  31.                               c[i]=(int*)malloc(sizeof(int)*p);
  32.                               }
  33.  
  34.             for(i=0;i<m;i++){
  35.                      for(j=0;j<u;j++){
  36.                                        printf("Introduce los valores %d-%d de la primera matriz\n",i+1,j+1);
  37.                                        scanf("%d",&a[i][j]);
  38.                                       }
  39.                      }
  40.  
  41.             for(i=0;i<n;i++){
  42.                               for(j=0;j<p;j++){
  43.                                                 printf("Introduce los valores %d-%d de la segunda matriz\n",i+1,j+1);
  44.                                                 scanf("%d",&b[i][j]);
  45.                                                 }
  46.                               }
  47.  
  48.                               for(i=0;i<m;i++){
  49.                                                 for(j=0;j<p;j++){
  50.                                                                   c[i][j]=0;
  51.                                                                   for(k=0;k<n;k++){
  52.                                                                                     c[i][j]+=a[i][k]*b[k][j];
  53.                                                                                     }
  54.                                                                   }
  55.                                                 }
  56.             printf("La matriz resultante es:\n");
  57.                        for(i=0;i<m;i++){
  58.                                          printf("\n");
  59.                                          for(j=0;j<p;j++){
  60.                                                            printf("%d   ",c[i][j]);
  61.                                                            }
  62.                                          }
  63.                        }
  64.             if(m==p){
  65.                      t=0;
  66.                      for(i=0;i<m;i++){
  67.                                       for(j=0;j<p;j++){
  68.                                                        if(i==j){
  69.                                                                 t+=c[i][j];
  70.                                                                 }
  71.                                                        }
  72.                                       }
  73.             printf("\nLa traza es: %d\n",t);
  74.                          }
  75.  
  76.             for(i=0;i<m;i++){
  77.                               free(a[i]);
  78.                               free(a);
  79.                               }
  80.             for(i=0;i<n;i++){
  81.                              free(b[i]);
  82.                              free(b);
  83.                              }
  84.             for(i=0;i<m;i++){
  85.                              free(c[i]);
  86.                              free(c);
  87.                              }
  88.  
  89.  
  90.  
  91.  
  92.  
  93.    system("PAUSE");
  94.    return 0;
  95. }
  96.