Estructuras anidadas, funciones y punteros

Iniciado por NathanD, 17 Marzo 2013, 15:25 PM

0 Miembros y 1 Visitante están viendo este tema.

NathanD

Buenas a todos, tengo unas cuantas dudas y espero poder resolverlas con vosotros.

Tengo que coger un ejercicio de administración de hoteles, hecho anteriormente, y hacerlo, pero esta vez usando punteros.

Por ejemplo, las primeras líneas del .c con main, donde declaro la estructura y la inicializo:


HOTELES hotel[NUM_HOTELES];          //3 hoteles

/***************/
HOTELES_inicializarHoteles(hotel); //Inicializamos el número de clientes de cada hotel a 0
 

Dicha función está definida así:


void HOTELES_inicializarHoteles(HOTELES hotel[])
{
int i;

for(i=0; i<NUM_HOTELES; i++)
{
hotel[i].numero_clientes = 0;
}
}


Como se trata de reescribir el programa usando punteros, me he limitado a cambiar el parámetro:

void HOTELES_inicializarHoteles(HOTELES *hotel)

Pero no consigo hacer nada. Me da error tanto si intento acceder a la posición del hotel con aritmética de punteros

*(hotel + i).numero_clientes = 0;

como accediendo a la estructura con el operador "->"

hotel[i]->numero_clientes = 0;

(Y haciendo ambas cosas juntas también de da error, claro).

En cambio, si en el parámetro de la función defino hotel como indirección doble, sí que debo emplear el operador "->". Pero bueno, que tampoco tengo del todo claro por qué hay que hacerlo así, lo he hecho un poco al tuntún. Además, así da error en ejecución...

Mi otra duda es si también debería modificar las estructuras anidadas, es decir, si en el primer ejercicio tengo una estructura dentro de otra de forma "simple", si ahora tengo que anidarlas usando punteros.

El tema de los punteros lo tengo claro, cómo y cuándo usar los operadores, direcciones de memoria, etc. Pero ahora con las estructuras no lo tengo nada claro.

Gracias de antemano, perdón por el tocho y saludos.

avesudra

#1
Sería de gran ayuda que postearas los errores que te dá el compilador. A mí así me funciona perfectamente:
#include <stdio.h>
#include <stdlib.h>
#define NUM_HOTELES 3

/// DEFINICIÓN DE ESTRUCTURAS
struct HOTEL
{
   int numero_clientes;
};

typedef struct HOTEL HOTELES;

/// DECLARACIÓN DE FUNCIONES
void HOTELES_inicializarHoteles(HOTELES *hotel);

int main (int argc, char *argv [])
{
   HOTELES hotel[NUM_HOTELES];          //3 hoteles

   HOTELES_inicializarHoteles(hotel); //Inicializamos el número de clientes de cada hotel a 0
   
   return 0;
}
/// DEFINICIÓN DE FUNCIONES
void HOTELES_inicializarHoteles(HOTELES *hotel)
{
   int i;
   for(i=0; i<NUM_HOTELES; i++)
   {
       hotel[i].numero_clientes = 0;
   }
}

Quizás te hayas confundido al declarar las estructuras puesto que se declaran así:
[struct] <identificador> <objeto_estructura>
Fuente: http://c.conclase.net/curso/?cap=011
Y tu la has declarado sin el struct:
HOTELES hotel[NUM_HOTELES];
Eso sí, si has puesto esto en el código no sé de que es el problema:
typedef struct HOTEL HOTELES;

¡Un saludo!
Regístrate en

NathanD

Hola avesudra, gracias por responder.

Así lo he hecho funcionar, modificando el parámetro de la función, solamente poniendo * en lugar de []. Pero verás, como se trata de hacer el ejercicios con punteros, asumo que debe de haber más cambios, no algo tan simple como cambiar los parámetros. Como, por ejemplo, acceder a los valores con la notación de punteros en lugar de con la de los arrays, o usando el operador -> en lugar de ., para acceder a las estructuras.

Si no me he expresado con claridad sólo tienes que preguntarme :)

Muchas gracias

avesudra

#3
---------------------------------------------------------------------------------------------------------------------------------------
El problema es que si desreferencias el puntero a la estructura te quedas con el valor del primer elemento de la estructura(supongo que puede ser el número de clientes o no sé, por eso no puedes acceder a nada, la primera dirección de memoria de una estructura creo que normalmente es su primer elemento, dependiendo de como se organize la memoria...)(que conste que no lo tengo claro):
*(hotel + i).numero_clientes = 0;
---------------------------------------------------------------------------------------------------------------------------------------
Retirando lo dicho, es un problema de sintaxis, pues así si sale:
(*(hotel + i)).numero_clientes = 0;
Pues así no está mal, lo que pasa es que obviamente tienes que apuntar el puntero a la estructura, que la creo con calloc:
#include <stdio.h>
#include <stdlib.h>
#define NUM_HOTELES 3

/// DEFINICIÓN DE ESTRUCTURAS
struct HOTEL
{
   int numero_clientes;
};

typedef struct HOTEL HOTELES;

/// DECLARACIÓN DE FUNCIONES
void HOTELES_inicializarHoteles(HOTELES *hotel);

int main (int argc, char *argv [])
{
   HOTELES *hotel;          
   hotel = calloc(NUM_HOTELES,sizeof(HOTELES));//3 hoteles
   HOTELES_inicializarHoteles(hotel); //Inicializamos el número de clientes de cada hotel a 0
   return 0;
}
/// DEFINICIÓN DE FUNCIONES
void HOTELES_inicializarHoteles(HOTELES *hotel)
{
   int i;

   for(i=0; i<NUM_HOTELES; i++)
   {
       (hotel+i)->numero_clientes = 0;
   }
}
Regístrate en

rir3760

Cita de: NathanD en 17 Marzo 2013, 15:25 PMComo se trata de reescribir el programa usando punteros, me he limitado a cambiar el parámetro:
void HOTELES_inicializarHoteles(HOTELES *hotel)
El problema: todo parámetro declarado como un array en realidad se procesa como un puntero. Puedes hacer ese cambio pero solo es cosmético.

El error en esta sentencia:
*(hotel + i).numero_clientes = 0;
Se genera porque el operador "." tiene mayor prioridad que "*" y la expresion se evalúa así:
*((hotel + i).numero_clientes) = 0;
Para conseguir el efecto deseado se deben utilizar paréntesis (mejor, por sencillo, utilizar "[]").

Y como ya te comentaron es mas fácil ayudarte si publicas el código fuente del programa así como los mensajes de error que se generan.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

NathanD

Muchas gracias a los dos :D Ya veo que era un error sintáctico, pensaba que había probado todas las formas...  ;D

Me ha surgido otra duda (siento ser tan pesado). ¿Cuál es la diferencia entre

(*(hotel + i)).numero_clientes = 0;

y


(hotel+i)->numero_clientes = 0;

? Ambas opciones me las da como válidas en la misma función, independientemente de haber usado calloc o no (¿y la diferencia entre inicializar con calloc y estáticamente como un array?).

avesudra

Es que con el operador "->" lo que haces es acceder a un miembro ( variable ) de un puntero, y con el "." simplemente al miembro cuando no hay punteros de por medio... De ahí que cuando desreferencias con el "*" debas usar el "." . La diferencia de usar memoria dinámica ( calloc, malloc, realloc ... ) y memoria estática ( declaraciones de arrays etc ) la puedes leer aquí:

http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Manejo_din%C3%A1mico_de_memoria

¡Saludos!
Regístrate en

85

#7
Cita de: rir3760 en 17 Marzo 2013, 16:58 PM
El problema: todo parámetro declarado como un array en realidad se procesa como un puntero. Puedes hacer ese cambio pero solo es cosmético.

El error en esta sentencia:
*(hotel + i).numero_clientes = 0;
Se genera porque el operador "." tiene mayor prioridad que "*" y la expresion se evalúa así:
*((hotel + i).numero_clientes) = 0;
Para conseguir el efecto deseado se deben utilizar paréntesis (mejor, por sencillo, utilizar "[]").

Y como ya te comentaron es mas fácil ayudarte si publicas el código fuente del programa así como los mensajes de error que se generan.

Un saludo


haber haber haber, veamos

Código (cpp) [Seleccionar]


//
// Yo no fui
//
//
//
//

/////////////////////////////////////////////////////////////////////////////////////////////////

#include<windows.h>// SYSTEM
#include<stdio.h>

/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

struct Sasafras{

int mandan;
};

struct Quete{

struct Sasafras quete;
};

struct Cador{

struct Quete tazo;
};

struct ElchoCador{

int x, y, z;
struct Cador elcho;
};

/////////////////////////////////////////////////////////////////////////////////////////////////

void Iniciar1(struct ElchoCador* reg);
void Iniciar2(struct ElchoCador* reg);

/////////////////////////////////////////////////////////////////////////////////////////////////

int main(){

struct Cador elcho;
memset(&elcho,0,sizeof elcho);
printf("Valor: %d\n", elcho.tazo.quete.mandan);

__try
      {
//if(IsDebuggerPresent())
               DebugBreak();
      }
       __except(GetExceptionCode() == EXCEPTION_BREAKPOINT ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
      {

system("pause");
               // No debugger is attached, so return FALSE
               // and continue.
               // return FALSE;
       }

struct ElchoCador regs[20];
Iniciar1(regs);
Iniciar2(regs);
for(int j=0; j<20;j++){
printf("%d %d %d\n",regs[j].x,regs[j].y,regs[j].z);
}

while(getchar()!='\n');
return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////

void Iniciar1(struct ElchoCador* regs){

for(int i=0; i<20;i++){

if(i%2==0)
{
(*(regs+i)).x = (*(regs+i)).y = (*(regs+i)).z = 2;
}
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////

void Iniciar2(struct ElchoCador* regs){

for(int i=0; i<20;i++){

if(i%2!=0)
{
//regs[i].x = regs[i].y = regs[i].z = 10;
(regs+i)->x = (regs+i)->y = (regs+i)->z = 10;
}
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////



Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/

rir3760

Cita de: 85 en 18 Marzo 2013, 03:30 AM
haber haber haber, veamos

...
No te entendi. ¿Por favor puedes explicar a que te refieres con eso?

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

85

a lo de acceder a los campos de la estructura con esas 2 funciones que se llaman Iniciar1 i Iniciar2  ::)

Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/