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

Problema usando el gets con estructuras y ciclos

Estas en el tema de Problema usando el gets con estructuras y ciclos en el foro de C/C++ en Foros del Web. Hola, hace poco pedí ayuda con el mismo programa, pero el problema era otro, espero que esto no sea alguna clase de spam o doble ...
  #1 (permalink)  
Antiguo 05/07/2010, 09:54
Avatar de Mercality  
Fecha de Ingreso: junio-2010
Mensajes: 19
Antigüedad: 13 años, 10 meses
Puntos: 0
Problema usando el gets con estructuras y ciclos

Hola, hace poco pedí ayuda con el mismo programa, pero el problema era otro, espero que esto no sea alguna clase de spam o doble post. Es mas que todo una duda, ya que he hecho que el programa corra bien.

Acá el codigo:
Código C:
Ver original
  1. #include <stdio.h>
  2. #include <string.h>
  3.        struct fecha {
  4.               int dia;
  5.               int mes;
  6.               int anio;
  7.               };
  8.        struct sexo {
  9.               int op;
  10.               char masculino[15];
  11.               char femenino[15];
  12.               char sexoa[20];
  13.               };
  14.        struct especialidad {
  15.           int opc;
  16.           char inf[20];
  17.           char adm[20];
  18.           char agr[20];
  19.           char esp[20];
  20.           };
  21.        struct alumno {
  22.           long cedula;
  23.           char nombre[40];
  24.           char apellido[40];
  25.           char direccion[100];
  26.           long telefono;
  27.           struct fecha fecha_nac;
  28.           struct sexo sex;
  29.           struct especialidad espe;
  30.           int prom;
  31.           char ciudadn[50];
  32.           char estadon[50];
  33.           };
  34.        struct alumno alumnos[100];
  35.  
  36.      int  main() {
  37.           int i,n;
  38.           system("CLS");
  39.           printf("Introduzca el numero de alumnos a almacenar:");
  40.           scanf("%d",&n);
  41.           for (i=0; i<n; i++) {
  42.           printf("\nDatos del alumno #%d\n", i+1);
  43.           printf("Cedula: ");
  44.           scanf("%ld",&alumnos[i].cedula);
  45.           printf("Nombre: ");
  46.           gets(alumnos[i].nombre);
  47.           printf("Apellido: ");
  48.           gets(alumnos[i].apellido);
  49.           printf("Direccion: ");
  50.           gets(alumnos[i].direccion);
  51.           printf("Telefono: ");
  52.           scanf("%ld",&alumnos[i].telefono);
  53.           printf("Sexo:\n");
  54.           printf("1.)Masculino\n2.)Femenino\n");
  55.           scanf("%d",&alumnos[i].sex.op);
  56.           switch (alumnos[i].sex.op)
  57.            {
  58.           case 1:
  59.                {
  60.                strcpy(alumnos[i].sex.sexoa,"Masculino");
  61.                break;
  62.                }
  63.           case 2:
  64.                {
  65.                strcpy(alumnos[i].sex.sexoa,"Femenino");
  66.                break;
  67.                }
  68.           }
  69.           printf("Fecha de nacimiento:\n");
  70.           printf("Dia: ");
  71.           scanf("%d",&alumnos[i].fecha_nac.dia);
  72.           printf("Mes: ");
  73.           scanf("%d",&alumnos[i].fecha_nac.mes);
  74.           printf("Anio: ");
  75.           scanf("%d",&alumnos[i].fecha_nac.anio);
  76.           printf("Especialidad:\n");
  77.           printf("1.)Informatica\n2.)Administracion\n3.)Agroalimentaria\n");
  78.           scanf("%d",&alumnos[i].espe.opc);
  79.           switch (alumnos[i].espe.opc)
  80.            {
  81.           case 1:
  82.                {
  83.                strcpy(alumnos[i].espe.esp,"Informatica");
  84.                break;
  85.                }
  86.           case 2:
  87.                {
  88.                strcpy(alumnos[i].espe.esp,"Administracion");
  89.                break;
  90.                }
  91.           case 3:
  92.                {
  93.              strcpy(alumnos[i].espe.esp,"Agro");
  94.                break;
  95.                }
  96.           }
  97.           printf("Promedio: ");
  98.           scanf("%d",&alumnos[i].prom);
  99.           printf("Ciudad de nacimiento: ");
  100.           gets(alumnos[i].ciudadn);
  101.           printf("Estado de nacimiento: \n");
  102.           gets(alumnos[i].estadon);
  103.        }
  104.           printf("\n\n\t******Datos Almacenados******\n\n");
  105.  
  106.             for (i=0; i<n; i++) {
  107.               printf("Cedula: %ld\nNombre: %s\nApellido: %s\n",alumnos[i].cedula,alumnos[i].nombre,alumnos[i].apellido);
  108.                       printf("Direccion: %s\nTelefono: %ld\n",alumnos[i].direccion,alumnos[i].telefono);
  109.                       printf("Sexo: %s\n",alumnos[i].sex.sexoa);
  110.                       printf("Fecha de nacimiento: %d/%d/%d\n",alumnos[i].fecha_nac.dia,alumnos[i].fecha_nac.mes,alumnos[i].fecha_nac.anio);
  111.                       printf("Especialidad: %s\nPromedio: %d\n",alumnos[i].espe.esp,alumnos[i].prom);
  112.                       printf("Ciudad de nacimiento: %s\nEstado de nacimiento: %s\n\n",alumnos[i].ciudadn,alumnos[i].estadon);
  113.                       }
  114.                       system("PAUSE");
  115.                      
  116. }

Ok, con este codigo se me presenta un problema. Luego de leer la cedula, como que se salta el paso de lectura del nombre, osea no se detiene en nombre para que ingrese el texto, salta de una vez a apellido y este si lo lee, luego direccion tambien lo lee. Entonces cuando llega a Ciudad de nacimiento pasa lo mismo que con nombre, salta hacía estado de nacimiento el cual si lee.

Acá una imagen



Mis duas son: Por que se salta nombre pero no se salta ni apellido ni direccion? Entonces por que luego se salta Ciudad de nacimiento y luego no salta Estado de nacimiento?

Se me ha ocurrido algo y agrege otro gets a nombre y ciudad y me quedo así
Código C:
Ver original
  1. printf("Nombre: ");
  2.           gets(alumnos[i].nombre);
  3.           gets(alumnos[i].nombre);
  4.           printf("Apellido: ");
  5.           gets(alumnos[i].apellido);

Y mas abajo...
Código C:
Ver original
  1. printf("Ciudad de nacimiento: ");
  2.           gets(alumnos[i].ciudadn);
  3.           gets(alumnos[i].ciudadn);
  4.           printf("Estado de nacimiento: \n");
  5.           gets(alumnos[i].estadon);

Y funciona correctamente


A que se debe que funcione así? Por que debo agregar un segundo gets?
Esto no pasa en otros códigos que tengo con el gets, cabe mencionar que no uso ni estructuras ni ciclos.
  #2 (permalink)  
Antiguo 05/07/2010, 18:24
 
Fecha de Ingreso: junio-2010
Mensajes: 22
Antigüedad: 13 años, 10 meses
Puntos: 1
Respuesta: Problema usando el gets con estructuras y ciclos

El problema es con los "buffers" que se llenan al momento de leer informacion.

scanf lee informacion formateada de un buffer (para eso del %d y de mas) que se va llenando del stdin, cada que se llama a scanf, hace un flush (vaciado) al buffer para evitar que contenga información que no corresponda.

gets lee un string desde stdin, pero como no es formateado, lee lo que encuentra, no lo carga a un buffer y problablemente se encuentra con informacion que dejo el scanf, tal vez un null al comienzo, para anular el buffer. Y la segunda vez que lo llamas a gets ya no lo tiene (el anterior lo consumio) y espera a que introduscas los datos.

Lo que haga scanf depende del runtime, el SO, la libreria, etc, ademas de mas factores, curso de SO necesario, jejeje.

El problema es que las funciones com scanf y gets se bloquean, esperan a que escribas, hasta que encuentran el null, \n o el eof, pero si esta alguno de estos en lo que acaba de leer de stdin lo carga y por eso no se bloquea. Similar a lo que pasa cuando introduces un tipo de dato no incorrecto (numero en lugar de letra).

En realidad es algo complicado de tratar, el mismo manual de fscan es algo raro

Cita:
The scanf() function reads input from the standard input stream stdin, fscanf() reads input from the stream pointer stream, and scanf() reads its input from the character string pointed to by str.
Lo que te recomiendo es tratar de tener los buffers en limpio, con "flush"es, o usar funciones sin buffer, o usar funciones de la misma familia, asi aseguras el mismo trato de los datos.

Y como en el otro tema, gcc chilla si usas gets.

Cita:
test.cpp:(.text+0xa6): warning: the `gets' function is dangerous and should not be used.
  #3 (permalink)  
Antiguo 05/07/2010, 19:45
Avatar de Mercality  
Fecha de Ingreso: junio-2010
Mensajes: 19
Antigüedad: 13 años, 10 meses
Puntos: 0
Respuesta: Problema usando el gets con estructuras y ciclos

En el otro tema me recomendaste hacer algo de este tipo

fgets(struct[i].char,40,stdin);

Y que así no tendría problemas, pero es igual que si usara gets, entonces igual debo hacerle un flush al stdin luego de haber usado un scanf antes de un get?

Etiquetas: ciclos, estructuras
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 21:56.