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

[SOLUCIONADO] Problema con estructuras y punteros en C

Estas en el tema de Problema con estructuras y punteros en C en el foro de C/C++ en Foros del Web. Hola, Tengo la siguiente estructura declarada en C: @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); Código C: Ver original typedef struct              {     ...
  #1 (permalink)  
Antiguo 26/05/2015, 06:03
 
Fecha de Ingreso: mayo-2015
Mensajes: 15
Antigüedad: 9 años, 6 meses
Puntos: 0
Problema con estructuras y punteros en C

Hola,

Tengo la siguiente estructura declarada en C:

Código C:
Ver original
  1. typedef struct             
  2. {
  3.     char *nombre;
  4.     char *apellido;
  5.     int edad;          
  6. } persona;
  7.  
  8. persona empleado;

Tengo también una función que escribe en cada uno de los miembros de la estructura (de tipo char) el valor que se le pasa por parámetro:

Código C:
Ver original
  1. int setEmpleadoValue(char *nombre, string &cadena)
  2. {
  3.     nombre=(char*)malloc(cadena.size());
  4.     strcpy(nombre,cadena.c_str());
  5.     printf("%s\n",nombre);
  6.     return 0;
  7. }

Desde otra función, lo que hago es llamar a la funcion setEmpleadoValue para asignarle el valor correspondiente a cada uno de los miembros de la estructura empleado definida previamente:

Código C:
Ver original
  1. int rellenarEmpleado ()
  2. {
  3.    string text;
  4.    obtenerTexto(text); //esta función asigna a texto el nombre del empleado en función de otros parametros
  5.    setEmpleadoValue(persona[i].nombre,text);
  6.    printf("%s\n", persona[i].nombre);

Al ejecutar el código printf(...) de la función setEmpleadoValue(), el nombre de la persona se imprime sin problemas. Pero al intentar ejecutar el código printf(...) de la función rellenarEmpleado(), me aparece un error en tiempo de ejecución.

Imagino que es algún problema con los punteros, pero no termino de ver cuál..

¿Podéis ayudarme? Espero haberme explicado correctamente.. Gracias de antemano
  #2 (permalink)  
Antiguo 26/05/2015, 08:00
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Problema con estructuras y punteros en C

Si yo te pongo este ejemplo:

Código C:
Ver original
  1. #include <stdio.h>
  2.  
  3. void func( int dato )
  4. {
  5.   dato = 5;
  6. }
  7.  
  8. int main( int, char**)
  9. {
  10.   int variable = 0;
  11.   func( variable );
  12.  
  13.   printf( "%d", variable );
  14.   return 0;
  15. }

¿Qué se imprimirá por pantalla?
  • Un número indeterminado
  • 5
  • 0

La respuesta correcta, espero que coincidas conmigo, es la tercera. El motivo es que "dato" es una copia local de "variable", por lo que cualquier cambio en "dato" no tendrá efecto en el valor de "variable".

Si trabajamos con punteros pasa algo parecido:

Código C:
Ver original
  1. #include <stdio.h>
  2.  
  3. void func( int* dato )
  4. {
  5.   dato = (int*)5; // Suponemos que '5' es una dirección de memoria válida
  6. }
  7.  
  8. int main( int, char**)
  9. {
  10.   int* variable = 0;
  11.   func( variable );
  12.  
  13.   printf( "%d", variable );
  14.   return 0;
  15. }

En este caso vemos que, efectivamente, el programa vuelve a devolver 0.

Espera, ¿no se supone que una de las gracias que tiene usar punteros es que podemos modificar los valores "a distancia"? Si, cierto, pero con un pequeño matiz:

"dato" es una variable local. Es un puntero, no lo niego, pero es una variable local. Al ser un puntero, si modificamos los valores almacenados en "dato" veremos que efectivamente también van a cambiar en "variable"... sin embargo, si cambiamos la dirección de memoria apuntada por "dato", estamos cambiando un valor local de "func", por lo que dicho cambio no se verá reflejado fuera de dicha función. No se si me explico.

Al final la cosa se soluciona añadiendo más punteros, tal y como se indica a continuación:
  • Para modificar una variable normal desde una función, necesitamos un puntero
  • Para modificar la posición de memoria a la que apunta un puntero desde una función, necesitamos un puntero doble
  • Para modificar la posición de memoria a la que apunta un puntero doble desde una función, necesitamos un puntero triple
  • ...

Es decir:

Código C:
Ver original
  1. #include <stdio.h>
  2.  
  3. void func( int** dato )
  4. {
  5.   *dato = (int*)5; // Suponemos que '5' es una dirección de memoria válida
  6. }
  7.  
  8. int main( int, char**)
  9. {
  10.   int* variable = 0;
  11.   func( &variable );
  12.  
  13.   printf( "%d", variable ); // Imprime 5, como pretendíamos
  14.   return 0;
  15. }

Un saludo
  #3 (permalink)  
Antiguo 27/05/2015, 01:44
 
Fecha de Ingreso: mayo-2015
Mensajes: 15
Antigüedad: 9 años, 6 meses
Puntos: 0
Respuesta: Problema con estructuras y punteros en C

Hola eferion,

Perfecto, muy buena la explicación y todo aclarado. Me ha servido de gran auda.

Muchas gracias
  #4 (permalink)  
Antiguo 27/05/2015, 06:07
 
Fecha de Ingreso: mayo-2015
Mensajes: 15
Antigüedad: 9 años, 6 meses
Puntos: 0
Respuesta: Problema con estructuras y punteros en C

Hola otra vez..

En el caso de utilizar estructuras anidadas y punteros, ¿cómo habría que pasar la variable por parámetro?

Siguiendo con el ejemplo de antes, suponemos que tenemos:

Código C:
Ver original
  1. typedef struct             
  2. {
  3.     char *dni;
  4.     int edad;
  5. } ninio;                   
  6.  
  7. typedef struct             
  8. {
  9.     char *nombre;
  10.     char *apellido;
  11.     int edad;          
  12.     ninio *hijos;
  13. } persona; 
  14.  
  15. persona empleado;

En este caso, a la hora de llamar a una función pasando como parametro el campo nombre de la estructura persona, lo haría tal y como me has explicado antes:

Código C:
Ver original
  1. void func(char **dato)
  2. {
  3.    ...
  4. }
  5.  
  6. int main ()
  7. {
  8.    persona *empleado;
  9.    func(&(empleado.nombre))
  10. }

Pero en el caso de llamar a la función pasándole como parámetro el campo dni de la estructura ninio (que a su vez está definida dentro de la estructura persona), ¿cómo tendría que hacerlo? He probado a hacerlo así pero me aparece un error en tiempo de ejecución:

Código C:
Ver original
  1. int main ()
  2. {
  3.    persona *empleado;
  4.    func(&(empleado.nombre.dni))
  5.  
  6. }

Gracias de nuevo!
  #5 (permalink)  
Antiguo 27/05/2015, 06:52
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Problema con estructuras y punteros en C

Dado que "empleado" es un puntero, para acceder a sus miembros tienes utilizar el operador '->' en vez del operador '.':
Código C:
Ver original
  1. int main ()
  2. {
  3.    persona *empleado;
  4.    func(&(empleado->nombre));
  5. }

Otra posibilidad si la anterior, que es la más habitual y natural, no te gusta:
Código C:
Ver original
  1. int main ()
  2. {
  3.    persona *empleado;
  4.    func(&(*empleado).nombre);
  5. }

Para el otro caso:

Código C:
Ver original
  1. int main ()
  2.     {
  3.        persona *empleado;
  4.        func(&(empleado.nombre.dni))
  5.      
  6.     }

Lamento decirte que "nombre" es de tipo "char*", es decir, no es una estructura y no tiene un miembro llamado "dni". Si revisas la definición de tu estructura, verás que "dni" se encuentra en la estructura "ninio", y el único campo de tipo "ninio" de la estructura "persona" se encuentra bajo el nombre "hijos", que además es un puntero.

Con todo esto la llamada quedaría así:

Código C:
Ver original
  1. int main ()
  2. {
  3.    persona *empleado;
  4.    int x;
  5.    func(&(empleado->hijos[x].dni));
  6. }

Donde x debería tener un valor válido entre 0 y el número de elementos del arreglo "hijos"
  #6 (permalink)  
Antiguo 28/05/2015, 01:26
 
Fecha de Ingreso: mayo-2015
Mensajes: 15
Antigüedad: 9 años, 6 meses
Puntos: 0
Respuesta: Problema con estructuras y punteros en C

Hola!!

Tienes toda la razón.. Al intentar simplificar mi código para poner el ejemplo, copié mal el mismo y puse persona.nombre en lugar de persona.hijos.

En cuanto a la solución al problema, de nuevo me ha sido de gran ayuda.

Muchas gracias!
  #7 (permalink)  
Antiguo 29/05/2015, 01:23
 
Fecha de Ingreso: mayo-2015
Mensajes: 15
Antigüedad: 9 años, 6 meses
Puntos: 0
Respuesta: Problema con estructuras y punteros en C

Hola de nuevo,

He intentado probar la solución que me comentabas ayer, utilizando el operador '->' para acceder a los miembros del puntero, pero al utilizar la siguiente llamada:

Código C:
Ver original
  1. func(&(empleado->nombre));

me aparece este error:

error C2232: '->persona::nombre': el operando izquierdo tiene el tipo 'struct'; utilice '.'

Por tanto, imagino que estoy definiendo mal el puntero empleado.

Escribo la definición completa de empleado, por si hay algo mal aquí:

Código C:
Ver original
  1. typedef struct             
  2. {
  3.     char *dni;
  4.     int edad;
  5. } ninio;       
  6.            
  7. typedef struct             
  8. {
  9.     char *nombre;
  10.     char *apellido;
  11.     int edad;          
  12.     ninio *hijos;
  13. } persona;
  14.  
  15. int main ()
  16. {
  17.    persona *empleado;
  18.    empleado=(persona*)malloc(num_empleados);   //num_empleados es un valor entero
  19.  
  20.    func(&(empleado->nombre));
  21. }

Etiquetas: char, puntero, struct
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 18:06.