Necesito ayuda en "Structs" en C, tengo un error muy gordo

Iniciado por DarkSorcerer, 13 Enero 2014, 23:38 PM

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

DarkSorcerer

Saludos comunidad, tengo un error muy gordo acerca de los structs en C, resulta que quiero crear personas usando structs en vez de crear una clase (paradojicamente, empecé al revés, es decir, de C++ a C)

La cosa es que cree una estructura que representa a una persona, tiene un nombre, apellido paterno, apellido materno, edad y rut (numero de identificación), la cosa es que en el main quiero crearlos y através de una función es la que imprime por pantalla los valores de cada persona para ahorrar lineas de código, pero no me funciona, me vi obligado a hacerlo en el main y también me sale error, les pongo mi código para que me puedan ayudar porfavor. Estoy usando DevC++. En el fondo del post se encuentra una captura del error.

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

struct persona{

    char nombre[20];
    char apellidoP[20];
    char apellidoM[20];
    char rut[10];
    int edad;       
       
}

void desplegarValores(struct persona p){
     
    printf("Nombre: %s\n",p.nombre);
    printf("Apellido paterno: %s\n",p.apellidoP);
    printf("Apellido materno: %s\n",p.apellidoM);
    printf("Rut: %s\n",p.rut);
    printf("Edad: %i\n\n",p.edad);     
     
}

int main(){
   
    struct persona persona1;
    struct persona persona2;
    struct persona persona3;
   
    persona1.nombre = "Rodrigo";
    persona1.apellidoP = "Saavedra";
    persona1.apellidoM = "Pizarro";
    persona1.rut = "ASDF-1";
    persona1.edad = 23;
   
    persona2.nombre = "Jorge";
    persona2.apellidoP = "Muñoz";
    persona2.apellidoM = "Cardenas";
    persona2.rut = "QWERT-1";
    persona2.edad = 27;
   
    persona3.nombre = "Francisco";
    persona3.apellidoP = "Sanchez";
    persona3.apellidoM = "Villagra";
    persona3.rut = "ZXCV-3";
    persona3.edad = 56;
   
    desplegarValores(persona1);
    desplegarValores(persona2);
    desplegarValores(persona3);
   
    printf("Nombre: %s\n",persona1.nombre);
    printf("Apellido paterno: %s\n",persona1.apellidoP);
    printf("Apellido materno: %s\n",persona1.apellidoM);
    printf("Rut: %s\n",persona1.rut);
    printf("Edad: %i\n\n",persona1.edad);
   
    printf("Nombre: %s\n",persona2.nombre);
    printf("Apellido paterno: %s\n",persona2.apellidoP);
    printf("Apellido materno: %s\n",persona2.apellidoM);
    printf("Rut: %s\n",persona2.rut);
    printf("Edad: %i\n\n",persona2.edad);
   
    printf("Nombre: %s\n",persona3.nombre);
    printf("Apellido paterno: %s\n",persona3.apellidoP);
    printf("Apellido materno: %s\n",persona3.apellidoM);
    printf("Rut: %s\n",persona3.rut);
    printf("Edad: %i\n\n",persona3.edad);
   
    system("PAUSE");
    return 0;   
   
}



xiruko

#1
A ver, primer error es que te falta un ';' al final de la declaración del struct:

struct persona
{
   char nombre[20];
   char apellidoP[20];
   char apellidoM[20];
   char rut[10];
   int edad;        
};


Segundo, en C, una vez pasada la declaración de las variables, no se pueden asignar las cadenas de esta manera:

persona1.nombre = "Rodrigo";
persona1.apellidoP = "Saavedra";


En lugar de eso, deberías hacerte alguna función para copiar carácter a carácter o usar, por ejemplo, la función strncpy() de la librería 'string.h'. Quedaría algo así:

#include <string.h>

char nombre1[] = "Rodrigo";  // aqui si que se puede porque es en el momento de la declaracion
strncpy(persona1.nombre, nombre1, strlen(nombre1));  // en tiempo de ejecucion hay que hacerlo asi


También puedes inicializar las variables del tipo de tu estructura al momento de declararlas:

struct persona persona1 = {"Rodrigo", "Saavedra", "Pizarro", "ASDF-1", 23};

edito: mirando el código, sería una buena práctica que pasaras un puntero de tu estructura a la función 'desplegarValores' en lugar de la estructura en sí, ya que así evitarías que se hiciera una copia local de ella. Si además no quieres que en la función se modifique el valor de tu estructura, podrías pasarla con el parámetro 'const'. Te quedaría algo así:

void desplegarValores(const struct persona *p)
{
   printf("Nombre: %s\n",p->nombre);
   printf("Apellido paterno: %s\n",p->apellidoP);
   printf("Apellido materno: %s\n",p->apellidoM);
   printf("Rut: %s\n",p->rut);
   printf("Edad: %i\n\n",p->edad);    
}


Y en la función 'main' deberías llamarla así:

desplegarValores(&persona1);

Un saludo.


xiruko


DarkSorcerer

#4
Ahora tengo otra duda, error logico, el programa me compila pero no como lo esperaba.

Lo que hice fue ir mas allá de mi programa anterior, quise hacer un programa con menú incluido, se trata de una registradora de personas en un arreglo de structs, cada struct representa a una persona, pero cuando quiero desplegar por pantalla, sus datos aparecen como si no hubiera sido registrado, además otro error que tengo es que en una parte del programa cuando pregunta el nombre, se salta a la siguiente instrucción y no permite que se registre el nombre, en mi código lo verán, repetí 2 veces la línea de código problema. Otro problema menor es que no me funciona el comando "clrscr" para limpiar la pantalla,

Ahora, pondré mi código y al fondo del post coloqué un link para que puedan ver mi captura de lo que se ve en consola.

#include <stdio.h>
#include <stdbool.h>
#include <windows.h>

struct persona personas[10];
int cant = 0;
bool flag = true;

struct persona{

   char nombre[30];
   char apellidoP[30];
   char apellidoM[30];
   char rut[20];
   int edad;    
     
};

void ingresarPersona(){
   
   printf("\n\nIngrese el nombre de la persona: ");
   gets(personas[cant].nombre); //Aqui es el error.
   gets(personas[cant].nombre);
   
   printf("\nIngrese el apellido paterno: ");
   gets(personas[cant].apellidoP);
   
   printf("\nIngrese el apellido materno: ");
   gets(personas[cant].apellidoM);
   
   printf("\nIngrese el RUT: ");
   gets(personas[cant].rut);
   
   printf("\nIngrese la edad: ");
   scanf("%i",&personas[cant].edad);    
   
   cant++;
   printf("\n\nRegistro realizado exitosamente.\n");
   
}

void desplegarDatos(){
   
   printf("\n\nDesplegando datos personales de los registrados:\n");
   
   int i;
   
   for(i=0; i<cant; i++){
   
       printf("\n\nNombre: %s",personas[cant].nombre);
       printf("\nApellido paterno: %s",personas[cant].apellidoP);
       printf("\nApellido materno: %s",personas[cant].apellidoM);
       printf("\nRut: %s",personas[cant].rut);
       printf("\nEdad: %i\n",personas[cant].edad);      
           
   }
     
}

void menuPrincipal(){
   
   printf("\n::::: MENU PRINCIPAL :::::\n");
   printf("\n1.- Ingresar nueva persona");
   printf("\n2.- Informacion de personas inscritas");
   printf("\n3.- Salir");
   printf("\n\nDigite su opcion: ");
   
   int opcion;
   scanf("%i",&opcion);
   
   
   switch(opcion){
                 
       case 1:
           
            ingresarPersona();
           
            break;
           
       case 2:
           
            desplegarDatos();
           
            break;
           
       case 3:
           
            flag = false;
                 
            break;
           
   }    
   
}

int main(){
   
   while(flag){
               
       //clrscr();
       menuPrincipal();
                   
               
   }
   
   system("PAUSE");
   return 0;    
   
}


http://www.subirimagenes.com/imagen-errorc-8777151.html

rir3760

Lo primero que debes hacer es cambiar colocar la declaración de la estructura antes de la declaración del array:
struct persona{

   char nombre[30];
   char apellidoP[30];
   char apellidoM[30];
   char rut[20];
   int edad;   

};

struct persona personas[10];


El porque se "salta" la lectura del nombre se debe a que estas intercalando llamadas a gets (no deberías, en su lugar fgets) y scanf, el tema se ha tratado en los foros y solo es cuestión de utilizar el motor de búsqueda.

Para solucionarlo debes eliminar el resto de la linea después de cada llamada a scanf (y antes de una llamada a fgets), por ejemplo la función "menuPrincipal" se debe cambiar a:
void menuPrincipal(void)
{
   int opcion;
   int ch;
   
   puts("::::: MENU PRINCIPAL :::::");
   puts("1.- Ingresar nueva persona");
   puts("2.- Informacion de personas inscritas");
   puts("3.- Salir");
   puts("Digite su opcion: ");

   scanf("%i", &opcion);
   /* Descartamos el resto de la linea */
   while ((ch = getchar()) != EOF && ch != '\n')
      ;
   
   switch(opcion){
   case 1:
      ingresarPersona();
      break;
   case 2:
      desplegarDatos();
      break;
   case 3:
      flag = false;
      break;
   }   
}

El cambio en la función "ingresarPersona" es similar.

El porque no se imprimen los datos correctamente se debe al bucle de la función "desplegarDatos":
void desplegarDatos(void)
{
   int i;
   
   puts("Desplegando datos personales de los registrados:");
   for(i = 0; i < cant; i++){
      printf("\n\nNombre: %s",personas[cant].nombre);
      printf("\nApellido paterno: %s",personas[cant].apellidoP);
      printf("\nApellido materno: %s",personas[cant].apellidoM);
      printf("\nRut: %s",personas[cant].rut);
      printf("\nEdad: %i\n",personas[cant].edad);
   }
}

En el cuerpo de este utilizas "personas[ cant ]" cuando debería ser "personas[ i ]".

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

DarkSorcerer

Cita de: rir3760 en 17 Enero 2014, 02:01 AM
Lo primero que debes hacer es cambiar colocar la declaración de la estructura antes de la declaración del array:
struct persona{

   char nombre[30];
   char apellidoP[30];
   char apellidoM[30];
   char rut[20];
   int edad;   

};

struct persona personas[10];


El porque se "salta" la lectura del nombre se debe a que estas intercalando llamadas a gets (no deberías, en su lugar fgets) y scanf, el tema se ha tratado en los foros y solo es cuestión de utilizar el motor de búsqueda.

Para solucionarlo debes eliminar el resto de la linea después de cada llamada a scanf (y antes de una llamada a fgets), por ejemplo la función "menuPrincipal" se debe cambiar a:
void menuPrincipal(void)
{
   int opcion;
   int ch;
   
   puts("::::: MENU PRINCIPAL :::::");
   puts("1.- Ingresar nueva persona");
   puts("2.- Informacion de personas inscritas");
   puts("3.- Salir");
   puts("Digite su opcion: ");

   scanf("%i", &opcion);
   /* Descartamos el resto de la linea */
   while ((ch = getchar()) != EOF && ch != '\n')
      ;
   
   switch(opcion){
   case 1:
      ingresarPersona();
      break;
   case 2:
      desplegarDatos();
      break;
   case 3:
      flag = false;
      break;
   }   
}

El cambio en la función "ingresarPersona" es similar.

El porque no se imprimen los datos correctamente se debe al bucle de la función "desplegarDatos":
void desplegarDatos(void)
{
   int i;
   
   puts("Desplegando datos personales de los registrados:");
   for(i = 0; i < cant; i++){
      printf("\n\nNombre: %s",personas[cant].nombre);
      printf("\nApellido paterno: %s",personas[cant].apellidoP);
      printf("\nApellido materno: %s",personas[cant].apellidoM);
      printf("\nRut: %s",personas[cant].rut);
      printf("\nEdad: %i\n",personas[cant].edad);
   }
}

En el cuerpo de este utilizas "personas[ cant ]" cuando debería ser "personas[ i ]".

Un saludo

Ya me dí cuenta de mi error, y me equivoqué por una tontería T.T,  por esto "personas[cant]" en vez de "personas", es que andaba apurado y tenía que irme a otra parte :O, pero de todas maneras gracias por informarme.

Al final usé la siguiente instruccion "fflush(stdin)" para que no se saltara la lectura del nombre, ¿ que opinas ?

rir3760

No se recomienda utilizar fflush(stdin), las razones se describen en el tema |Lo que no hay que hacer en C/C++. Nivel basico|.

Alternativas hay varias, puedes utilizar el motor de búsqueda para revisar los temas relacionados con el bufer de la entrada estándar.

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