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

proplema con paso de punteros de structuras a funciones

Estas en el tema de proplema con paso de punteros de structuras a funciones en el foro de C/C++ en Foros del Web. Hola a todos, estoy intentando hacer un programa q realice las siguientes tareas. Mantener una lista de personas, poder introducir, modificar o borrar personas y ...
  #1 (permalink)  
Antiguo 13/03/2010, 08:45
 
Fecha de Ingreso: octubre-2008
Mensajes: 118
Antigüedad: 15 años, 6 meses
Puntos: 2
proplema con paso de punteros de structuras a funciones

Hola a todos, estoy intentando hacer un programa q realice las siguientes tareas.
Mantener una lista de personas, poder introducir, modificar o borrar personas y guardarlas en un archivo binario.
El problema q tengo es q me declaro un puntero q apunta a la primera persona de la lista y otro a la ultima y cuando paso este puntero a la funcion tiene un valor distinto al q esta en el main y no entiendo muy bien xk. El archivo main es el siguiente (resumiendo un poco):
Código:
#include <stdio.h>
#include <stdlib.h>
struct personas {
    char *nombre;
    int edad;
    struct personas *siguiente;
};


int main(int argc, char** argv) {

    int opcion=10;
    // declaro los punteros de tipo personas q aun no apuntan a ningun sitio
    struct personas *primera;
    struct personas *ultima;
    int nPersonas=0;

        scanf("%d",&opcion);
        fflush(stdin);

        switch(opcion){
            case 3: {
                primera=insertar(primera, ultima, &nPersonas);
                break;
            }
            case 4: {
                mostrar(primera, &nPersonas);
                break;
            }
            case 0: {
                puts("Hasta la proxima");
                break;
            }
            default: {
                puts("No es una opcion valida");
            }
        }
     }


    return (EXIT_SUCCESS);
}

este es el archivo de las funciones:

Código:
struct personas {
    char *nombre;
    int edad;
    struct personas *siguiente;
};
// le paso el apuntador a la primera persona, a la ultima y el numero de personas
void insertar(struct personas *primera, struct personas *ultima, int *nPersonas){

    char *nombre;
    int edad=0;
    struct personas *persona;

// asignamos el espacio de memoria al apuntador persona de tipo personas
    if ((persona=malloc(sizeof(struct personas)))==NULL){
        puts("Error al asignar la memoria");
    } else {
// pedimos los datos y los guardamos en la estructura
        puts("Dime el nombre de la persona: ");
        gets(&nombre);
        fflush(stdin);
        puts("Dime la edad: ");
        scanf("%d",&edad);
        fflush(stdin);
        strcpy(persona->nombre,&nombre);
        persona->edad=edad;
        persona->siguiente=NULL;
        if ((*nPersonas)==0){
// si es la primera persona q insertamos el puntero primera y ultima apuntan a esta persona
            ultima=persona;
            primera=persona;
        } else {
// si ya tenemos mas personas la ultima apuntara a esta y esta sera la ultima
            ultima->siguiente=persona;
        }
        (*nPersonas)++;
        puts("Insercion correcta");
    }

}

void mostrar(struct personas *primera, int *nPersonas){

    struct personas *perActual=primera;
    int cont=0;
    for (cont=0;cont<(*nPersonas);cont++){
        printf("Nombre: %s\nEdad: %d\n",perActual->nombre,perActual->edad);
        if (perActual->siguiente!=NULL){
            perActual=perActual->siguiente;
        }
    }

}
como veis dentro de la funcion insertar cambio el valor de primera y ultima pero cuando sale de la funcion, en el main, estos dos punteros siguen teniendo el mismo valor q antes.
Que estoy haciendo mal?

Gracias,
Dani.
  #2 (permalink)  
Antiguo 15/03/2010, 11:25
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: proplema con paso de punteros de structuras a funciones

En C todos los parametros se pasan por valor, por tanto no puedes modificar directamente nada al interior de una funcion.

Por ejemplo:

Código C:
Ver original
  1. void f( int valor )
  2. {
  3.    valor = 0;
  4. }
y en el main ..

Código C:
Ver original
  1. int i = 3;
  2.  
  3. // i vale 3
  4.  
  5. f(i);    // f no cambia a i, cambia a una copia de i
  6.  
  7. // i sigue valiendo 3

Lo mismo pasa con los punteros. Estas pasando punteros y quieres modificarlos, lo que en C no se puede.
Para lograrlo, pasa la direccion de memoria de ellos y recibelos en un puntero a puntero, y luego modificas lo apuntado, asi:

Código C:
Ver original
  1. void f( int ** p )
  2. {
  3.   *p = malloc( ... );
  4. }
  5.  
  6. main()
  7. {
  8.    int *puntero;
  9.  
  10.    f( &puntero );
  11.  
  12. }
  #3 (permalink)  
Antiguo 15/03/2010, 13:08
 
Fecha de Ingreso: octubre-2008
Mensajes: 118
Antigüedad: 15 años, 6 meses
Puntos: 2
Respuesta: proplema con paso de punteros de structuras a funciones

muchas gracias x tu respuesta CalgaryCorpus, ya he corregido esos errores. Ahora no entiendo xk me salta el programa cuando intento mostrar la lista.

El codigo es el siguiente:

Código:
mostrar(primera, &nPersonas);

void mostrar(struct personas *primera, int *nPersonas){

    struct personas *perActual=primera;
    int cont=0;
    for (cont=0;cont<(*nPersonas);cont++){
        printf("Nombre: %s\nEdad: %d\n",perActual->nombre, perActual->edad);
        if (perActual->siguiente!=NULL){
            perActual=perActual->siguiente;
        }
    }

}
El problema esta en el printf que lo q intento mostrar no debe de ser lo correcto pero no entiendo xk ni como solucionarlo
  #4 (permalink)  
Antiguo 15/03/2010, 21:00
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: proplema con paso de punteros de structuras a funciones

Cita:
Iniciado por nosek159 Ver Mensaje
muchas gracias x tu respuesta CalgaryCorpus, ya he corregido esos errores. Ahora no entiendo xk me salta el programa cuando intento mostrar la lista.
No se a que te refieres que tu programa te "salte". A que te refieres?

Una duda que tengo al mirar el código de "mostrar": Para que pasas el nro. de personas a la función mostrar? Si la lista esta bien construida y quieres mostrar toda la lista, basta el primer parámetro. Luego, en el ciclo, en vez de llevar un contador, usar el puntero perActual, y lo avanzas al siguiente cada vez. Solo das vuelta en el ciclo si perActual es no NULL, y por tanto siempre lo que escribes es valido.

Pienso que tu programa intenta escribir mas alla del ultimo elemento, debido a que usas este contador que puede estar desactualizado respecto a lo que la lista efectivamente tiene, o bien la lista esta mal construida.

Pon atencion a que tu puntero al ultimo elemento no se actualiza nunca, excepto cuando la lista esta vacia. Después de eso, el puntero al "ultimo" siempre es el puntero al primero que se ingresó.
  #5 (permalink)  
Antiguo 16/03/2010, 16:52
 
Fecha de Ingreso: octubre-2008
Mensajes: 118
Antigüedad: 15 años, 6 meses
Puntos: 2
Respuesta: proplema con paso de punteros de structuras a funciones

con q me salta me refiero a q me da error y tengo q cerrarlo.

Tengo el siguiente codigo:

Main
Código:
    int opcion=10;
    struct personas *primera;
    struct personas *ultima;
    int nPersonas=0;

        scanf("%d",&opcion);
        fflush(stdin);

        switch(opcion){
            case 3: {
                primera=insertar(&primera, &ultima, &nPersonas);
                break;
            }
            case 4: {
                mostrar(primera);
                break;
            }
            default: {
                puts("No es una opcion valida");
            }
        }
funciones:

Código:
void insertar(struct personas **primera, struct personas **ultima, int *nPersonas){

    struct personas *persona;


    if ((persona=malloc(sizeof(struct personas)))==NULL){
        puts("Error al asignar la memoria");
    } else {
        puts("Dime el nombre de la persona: ");
        gets(persona->nombre);
        fflush(stdin);
        puts("Dime la edad: ");
        scanf("%d",&persona->edad);
        fflush(stdin);
        persona->siguiente=NULL;
        if ((*nPersonas)==0){
            *ultima=persona;
            *primera=persona;
        } else {
            (**ultima).siguiente=persona;
            *ultima=persona;
        }
        (*nPersonas)++;
        printf("Nombre: %s\nEdad: %d",(**ultima).nombre,(**ultima).edad);
        puts("Insercion correcta");
    }
}

void mostrar(struct personas *primera){

    struct personas *perActual=primera;
        printf("Nombre: %s\nEdad: %d\n",perActual->nombre, perActual->edad);

}
he eliminado el bucle de mostrar pero aun asi me salta error al intentar mostrar pero no veo el xk.

Tmp nose xk **ahora la segunda vez q intento insertar una persona me salta error, si antes lo probe y funcionaba, peta justo en el if pero no hace ni el if ni el else :S. Nose, no lo entiendo si lo veo bien
  #6 (permalink)  
Antiguo 16/03/2010, 19:10
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: proplema con paso de punteros de structuras a funciones

En la estructura personas, tienes espacio para un entero (la edad) y un puntero. Aun no has pedido memoria para guardar el nombre.

Tienes que pedir memoria para guardar el string con el nombre y guardar la direccion de memoria en el puntero que tiene esa estructura.

De otra manera, cuando escribes en el campo nombre, estas sobreescribiendo una zona de memoria desconocida y tu programa, como dices tu, "salta".

Puedes mantener el ciclo en mostrar, si quieres mostrar la lista completa, basta que controles que el puntero no sea NULL y avanzarlo al siguiente en cada vuelta.
  #7 (permalink)  
Antiguo 18/03/2010, 11:52
 
Fecha de Ingreso: octubre-2008
Mensajes: 118
Antigüedad: 15 años, 6 meses
Puntos: 2
Respuesta: proplema con paso de punteros de structuras a funciones

Cita:
Iniciado por CalgaryCorpus Ver Mensaje
En la estructura personas, tienes espacio para un entero (la edad) y un puntero. Aun no has pedido memoria para guardar el nombre.

Tienes que pedir memoria para guardar el string con el nombre y guardar la direccion de memoria en el puntero que tiene esa estructura.

De otra manera, cuando escribes en el campo nombre, estas sobreescribiendo una zona de memoria desconocida y tu programa, como dices tu, "salta".

Puedes mantener el ciclo en mostrar, si quieres mostrar la lista completa, basta que controles que el puntero no sea NULL y avanzarlo al siguiente en cada vuelta.

Muxas gracias x tu respuesta, realmente no estaba teniendo en cuenta q tenia un puntero y no una cadena de caracteres. He modificado la estructura de forma que:

Código:
struct personas {
    char nombre[15];
    int edad;
    struct personas *siguiente;
};
ahora ya me funciona perfectamente la inserccion de personas pero me sigue dando problemas a la hora de mostrar, tengo este codigo:

Código:
void insertar(struct personas **primera, struct personas **ultima, int *nPersonas){

    struct personas *persona;


    if ((persona=malloc(sizeof(struct personas)))==NULL){
        puts("Error al asignar la memoria");
    } else {
        puts("Dime el nombre de la persona: ");
        gets(persona->nombre);
        fflush(stdin);
        puts("Dime la edad: ");
        scanf("%d",&persona->edad);
        fflush(stdin);
        persona->siguiente=NULL;
        if ((*nPersonas)==0){
            *ultima=persona;
            *primera=persona;
        } else {
            (**ultima).siguiente=persona;
            *ultima=persona;
        }
        (*nPersonas)++;
        printf("Nombre: %s\nEdad: %d\n",(**ultima).nombre,(**ultima).edad);
        puts("Insercion correcta");
    }
}

void mostrar(struct personas *primera, int *nPersonas){

    struct personas *perActual=primera;
    if ((*nPersonas!=0)){
        printf("Nombre: %s\nEdad: %d\n",perActual->nombre, perActual->edad);
    } else {
        puts("No hay personas insertadas");
    }
}
he probado a poner simplemente: printf("Nombre: %s\nEdad: %d\n",primera->nombre, primera->edad); y me sigue "saltando" error.
No entiendo xk me da error si le estoy pasando el puntero q esta apuntando a la estructura de la primera persona y luego la estoy mostrando :S


De nuevo muchas gracias x tu tiempo y la ayuda q me estas dando.
  #8 (permalink)  
Antiguo 18/03/2010, 12:17
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: proplema con paso de punteros de structuras a funciones

Copia el main que invoca a esas funciones, si es que ha cambiado
  #9 (permalink)  
Antiguo 19/03/2010, 05:01
 
Fecha de Ingreso: octubre-2008
Mensajes: 118
Antigüedad: 15 años, 6 meses
Puntos: 2
Respuesta: proplema con paso de punteros de structuras a funciones

Código:
int main(int argc, char** argv) {

    int opcion=10;
    struct personas *primera;
    struct personas *ultima;
    int nPersonas=0;

        scanf("%d",&opcion);
        fflush(stdin);

        switch(opcion){
            case 3: {
                primera=insertar(&primera, &ultima, &nPersonas);
                break;
            }
            case 4: {
                mostrar(primera, &nPersonas);
                break;
            }
            case 0: {
                puts("Hasta la proxima");
                break;
            }
            default: {
                puts("No es una opcion valida");
            }
        }


    return (EXIT_SUCCESS);
}
  #10 (permalink)  
Antiguo 19/03/2010, 07:21
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: proplema con paso de punteros de structuras a funciones

Veo al menos 2 problemas:
1. El main invoca a una funcion ( insertar) que ha sido definida con retorno void, no se como el compilador acepta que su resultado se lo asignes a una variable. Si yo fuera compilador te reclamaría que eso no tiene sentido hacerlo y no dejaría que el programa compilara y no generaria el ejecutable. Tal vez uno de tus problemas es que en realidad tu programa NO esta compilando, y tu estas ejecutando una version anterior del ejecutable todas las veces?

2. El main realiza 1 operacion y se sale, o insertas o muestras, pero en la misma ejecución, no haces las 2 cosas, entonces me pregunto como haces para mostrar lo que insertaste en 1 sola ejecucion?. Lo estas ejecutando mas de 1 vez? Si es asi, la segunda vez los datos de la primera vez ya no estarán en la lista. Estas seguro que estas mostrando el codigo que efectivamente tienes? Como estas haciendo para probar?
  #11 (permalink)  
Antiguo 20/03/2010, 06:49
 
Fecha de Ingreso: octubre-2008
Mensajes: 118
Antigüedad: 15 años, 6 meses
Puntos: 2
Respuesta: proplema con paso de punteros de structuras a funciones

Cita:
Iniciado por CalgaryCorpus Ver Mensaje
Veo al menos 2 problemas:
1. El main invoca a una funcion ( insertar) que ha sido definida con retorno void, no se como el compilador acepta que su resultado se lo asignes a una variable. Si yo fuera compilador te reclamaría que eso no tiene sentido hacerlo y no dejaría que el programa compilara y no generaria el ejecutable. Tal vez uno de tus problemas es que en realidad tu programa NO esta compilando, y tu estas ejecutando una version anterior del ejecutable todas las veces?

2. El main realiza 1 operacion y se sale, o insertas o muestras, pero en la misma ejecución, no haces las 2 cosas, entonces me pregunto como haces para mostrar lo que insertaste en 1 sola ejecucion?. Lo estas ejecutando mas de 1 vez? Si es asi, la segunda vez los datos de la primera vez ya no estarán en la lista. Estas seguro que estas mostrando el codigo que efectivamente tienes? Como estas haciendo para probar?
lo de la funcion insertar es xk antes si devolvia un valor y se me olvido quitar la variable :S q raro q no diga nada el compilador y lo 2º lo tengo metido dentro de un bucle solo que borre algunas cosas del main al copiarlo aqui.

Ya me funciona... El problema estaba en la llamada a la funcion insertar q como tu dices devuelve void y lo intentaba guardar en una variable.
Vaya un error tontisimo y todo x no fijarme lo q deberia pero bueno asi aprendere a revisarlo TODO TODO antes de mirar nada mas.

Muchas gracias x tu ayuda y la dedicacion q le has puesto a resolver mi problema. Te estoy muy agradecido, ahora entiendo un poco mejor los punteros de C.

De nuevo gracias,
Dani
  #12 (permalink)  
Antiguo 20/03/2010, 08:33
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: proplema con paso de punteros de structuras a funciones

Podrias publicar como quedo el programa finalmente? Seria de utilidad a los siguientes lectores de este foro.
  #13 (permalink)  
Antiguo 20/03/2010, 18:45
 
Fecha de Ingreso: octubre-2008
Mensajes: 118
Antigüedad: 15 años, 6 meses
Puntos: 2
Respuesta: proplema con paso de punteros de structuras a funciones

Cita:
Iniciado por CalgaryCorpus Ver Mensaje
Podrias publicar como quedo el programa finalmente? Seria de utilidad a los siguientes lectores de este foro.
por supuesto, aqui esta el codigo:

Main:

Código:
#include <stdio.h>
#include <stdlib.h>
struct personas {
    char nombre[15];
    int edad;
    struct personas *siguiente;
};


void main() {

    int opcion=10;
    struct personas *primera = NULL; //puntero q apuntara a la primera persona
    struct personas *ultima = NULL; // puntero q apuntara a la ultima persona
    int nPersonas=0; // numero de personas introducidas

     while (opcion!=0){
        puts("3. Insertar");
        puts("4. Mostrar");
        puts("0. Salir");
        puts("Haga su eleccion");
        scanf("%d",&opcion);
        fflush(stdin);

        switch(opcion){
            case 3: {
                insertar(&primera, &ultima, &nPersonas);
                break;
            }
            case 4: {
                mostrar(primera);
                break;
            }
            case 0: {
                puts("Hasta la proxima");
                break;
            }
            default: {
                puts("No es una opcion valida");
            }
        }
     }

}

funciones:

Código:
#include <stdio.h>
#include <stdlib.h>

struct personas {
    char nombre[15];
    int edad;
    struct personas *siguiente;
};

// insertar personas
void insertar(struct personas **primera, struct personas **ultima, int *nPersonas){

    struct personas *persona=NULL; //puntero que apuntara a la persona q estamos creando

// asignamos el espacio de memoria necesario para la persona
    if ((persona=malloc(sizeof(struct personas)))==NULL){
        puts("Error al asignar la memoria");
    } else {
        // pedimos los datos de la persona
        puts("Dime el nombre de la persona: ");
        gets(persona->nombre);
        fflush(stdin);
        puts("Dime la edad: ");
        scanf("%d",&persona->edad);
        fflush(stdin);
        persona->siguiente=NULL;
        // ponemos siguiente a null ya que la persona actual sera la ultima
        if (*primera==NULL){
            // si primera es null no tenemos personas y la primera y ultima seran la actual
            *ultima=persona;
            *primera=persona;
        } else {
            // si ya tenemos personas el puntero siguiente de la ultima persona apuntara
            // a la actual y la ultima sera esta
            (**ultima).siguiente=persona;
            *ultima=persona;
        }
        (*nPersonas)++;
        puts("Insercion correcta");
    }
}


// mostrar las personas de la lista
void mostrar(struct personas *primera){

    if ((primera==NULL)){
        puts("No hay personas insertadas");
    } else {
        struct personas *perActual=primera;
        // asignamos la primera persona al puntero y mos tramos sus datos
        do {
            printf("Nombre: %s\nEdad: %d\n",perActual->nombre, perActual->edad);
            // buscamos la siguiente persona y apuntamos a ella
            perActual=perActual->siguiente;
        } while(perActual!=NULL);
        
    }
}

Saludos,
Dani.

Etiquetas: funciones, 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 13:41.