Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Locura_23 en 21 Agosto 2021, 21:33 pm



Título: Error de printeo con puntero triple
Publicado por: Locura_23 en 21 Agosto 2021, 21:33 pm
Hola genios. Bueno resulta que estoy practicando el manejo de punteros y arreglos, pero estoy teniendo problemas: no se muestran los valores desde main. Alguien puede notar algo? Si nadie se quiere molestar lo entiendo porque puede parecer complejo... gracias saludos.

Código
  1. //la funcion crearArreglo maneja la creacion del arreglo, primero guarda
  2. //la memoria necesaria y luego le copia los valores.
  3. //crearArreglo recibe un puntero a entero y la dimension.
  4. //Luego le pasa el puntero a puntero
  5. //a otra funcion asignarMemoria. Luego le pasa el puntero a puntero
  6. //a copiarValores, donde se asignan numeros random.
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <time.h>
  10.  
  11. void crearArreglo(int**punteroApuntero, int dim);
  12. void asignarMemoria(int***punteroTriple, int dim );
  13. void copiarValores(int ***punteroTriple, int dim);
  14.  
  15. int main()
  16. {
  17.    int *pArreglo = NULL;
  18.    int dim = 0; //dimension
  19.  
  20.    printf("\nIngrese la dimension del arreglo: ");
  21.    scanf("%d",&dim);
  22.  
  23.    srand(time(NULL)); //para obtener valores random en copiarValores()
  24.    crearArreglo(&pArreglo,dim); //se le pasa el puntero a puntero y la dimension
  25.  
  26.    printf("\nPrimer elemento desde main: %d\n",*pArreglo); //printea un valor erroneo
  27.  
  28.    return 0;
  29.  
  30. }// fin main
  31.  
  32. void crearArreglo(int **punteroApuntero, int dim)
  33. {
  34.    asignarMemoria(&punteroApuntero, dim);
  35.  
  36.    copiarValores(&punteroApuntero, dim);
  37.  
  38. }// fin funcion crearArreglo
  39.  
  40. void asignarMemoria(int ***punteroTriple, int dim)
  41. {
  42.    (**punteroTriple) = (int *) malloc ( dim * sizeof(int) );
  43.  
  44.    if( (**punteroTriple) == NULL )
  45.    {
  46.        printf("\nError en asignacion de memoria.\n");
  47.        exit(EXIT_FAILURE);
  48.    }//fin if
  49.    else
  50.    {
  51.        printf("\nAsignacion de memoria exitosa.\n");
  52.  
  53.    } // fin else
  54.  
  55. } // fin funcion asignarMemoria
  56.  
  57. void copiarValores(int ***punteroTriple, int dim)
  58. {
  59.    int i = 0;
  60.  
  61.    while( i < dim )
  62.    {
  63.        (***punteroTriple) = rand() % 10;
  64.        printf("Elemento %d : %d\n",i,***punteroTriple);
  65.        system("pause");
  66.        (**punteroTriple)++; //dudas aca
  67.        i++;
  68.    }// fin while
  69.  
  70. } // fin funcion copiarValores
  71.  


Título: Re: Error de printeo con puntero triple
Publicado por: MAFUS en 22 Agosto 2021, 13:05 pm
No tiene sentido usar puntero triple. Lo que te importa es la dirección de memoria que contendrá pArreglo y cambiarlo en otra función. Como sabes un argumento de una función es una copia de un dato y para modificar el valor de una variable se pasa el puntero a esa variable (así el puntero es la copia y lo que hay dentro se modifica), por eso se pasa un puntero a puntero.

Como crearArreglo va a crear un array dinámico que debe ser devuelto (a a introducir en pArreglo un valor), esta función debe recibir la dirección de pArreglo (que es copia, pero su dato sí se puede modificar).

Ídem para asignarMemoria. No debe ser un puntero triple porque es realmente la encargada de crear el array e introducir esa dirección de memoria en pArreglo. La dirección de pArreglo ya la has pasado en el argumento punteroApuntero de crearArreglo y es lo que te interesa, así que se lo das sin más.

Totalmente diferente es el trabajo en copiarValores. Allí sólo te interesa rellenar el array, no debes modificar su dirección de memoria y por tanto debes pasarle la dirección del propio array. Vas a modificar su contenido.

Sería algo así:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. void crearArreglo(int **punteroApuntero, int dim);
  6. void asignarMemoria(int **punteroApuntero, int dim );
  7. void copiarValores(int *puntero, int dim);
  8.  
  9. int main()
  10. {
  11.    int *pArreglo = NULL;
  12.    int dim = 0; //dimension
  13.  
  14.    printf("\nIngrese la dimension del arreglo: ");
  15.    scanf("%d",&dim);
  16.  
  17.    srand(time(NULL)); //para obtener valores random en copiarValores()
  18.    crearArreglo(&pArreglo,dim); //se le pasa el puntero a puntero y la dimension
  19.  
  20.    printf("\nPrimer elemento desde main: %d\n",*pArreglo);
  21.  
  22.    free(pArreglo); // recuerda que siempre que adquieres memorias a mano debes liberarla a mano.
  23.  
  24.    return 0;
  25.  
  26. }// fin main
  27.  
  28. void crearArreglo(int **punteroApuntero, int dim)
  29. {
  30.    asignarMemoria(punteroApuntero, dim);
  31.  
  32.    copiarValores(*punteroApuntero, dim);
  33.  
  34. }// fin funcion crearArreglo
  35.  
  36. void asignarMemoria(int **punteroApuntero, int dim)
  37. {
  38.    (*punteroApuntero) = (int *) malloc ( dim * sizeof(int) );
  39.  
  40.    if( (*punteroApuntero) == NULL )
  41.    {
  42.        printf("\nError en asignacion de memoria.\n");
  43.        exit(EXIT_FAILURE);
  44.    }//fin if
  45.    else
  46.    {
  47.        printf("\nAsignacion de memoria exitosa.\n");
  48.  
  49.    } // fin else
  50.  
  51. } // fin funcion asignarMemoria
  52.  
  53. void copiarValores(int *puntero, int dim)
  54. {
  55.    for(int i=0; i<dim; ++i)
  56.    {
  57.        puntero[i] = rand() % 10;
  58.        printf("Elemento %d : %d\n",i,puntero[i]);
  59.        system("pause");
  60.    }// te lo cambio por un for. Es más conciso en este caso
  61.  
  62. } // fin funcion copiarValores


Título: Re: Error de printeo con puntero triple
Publicado por: Locura_23 en 22 Agosto 2021, 18:57 pm
Ohh ya veo, con que era eso... Osea en asignarMemoria estaba ampliando el bloque de memoria del puntero al puntero de pArreglo. En vez de ampliar el bloque de memoria del puntero a la direccion de pArreglo. Y luego con ese error, en copiarValores asignaba valores en la memoria reservada en el lugar erroneo.
En resumen no estaba guardando nada en pArreglo sino en otra direccion de memoria... Por eso me mostraba siempre cero en main, pues mostraba el equivalente a NULL...

En verdad me ayudaste mucho, muchas gracias por tu tiempo Mafus