SoloCodigo

Programación General => C/C++ => Mensaje iniciado por: Amphoth3ra en Jueves 9 de Junio de 2011, 01:13

Título: [C] fgets y línea innecesaria [Solucionado]
Publicado por: Amphoth3ra en Jueves 9 de Junio de 2011, 01:13
Estoy practicando un poco de fgets con cadenas y me he encontrado con algo bastante extraño, que consiste en que las cadenas que yo entrego de entrada, me salen correctas, pero me salen con una línea de más.

Les explico con código en mano. Esta aplicación pretende guardar en una estructura temporal cuatro datos
1) El nombre de un DVD
2) El género de un DVD
3) El número de discos de un DVD
4) La duración total del DVD en minutos

Código: C
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4.  
  5. struct dvd {
  6.  char name[255];
  7.  char genero[50];
  8.  int discs_number;
  9.  int length;
  10. };
  11.  
  12. int main()
  13. {
  14.     struct dvd temporal;
  15.  
  16.     char discs_number[2];
  17.     char length[4];
  18.  
  19.     printf("Nombre del DVDn");
  20.              fgets(temporal.name, 255, stdin);
  21.  
  22.     printf("%sn", temporal.name); 
  23.  
  24.     printf("Género del DVDn");
  25.             fgets(temporal.genero, 50, stdin);
  26.  
  27.     printf("%sn", temporal.genero);
  28.  
  29.     printf("Número de discos del DVDn");
  30.              fgets(discs_number, 2, stdin);
  31.  
  32.     temporal.discs_number = atoi(discs_number);
  33.  
  34.     printf("%dn", temporal.discs_number);
  35.  
  36.     printf("Duración del DVDn");
  37.        
  38.     while(getchar() != 'n');
  39.             fgets(length, 4, stdin);
  40.  
  41.     temporal.length = atoi(length);
  42.    
  43.     printf("%dn", temporal.length);
  44.  
  45.    
  46.  
  47.     return(0);
  48. }
  49.  

Cuando ejecuto el programa, si introducen el nombre del DVD, la cadena que se me regresa es correcta cuando yo haga el printf, pero automáticamente se me salta una línea. Lo mismo pasa con el género del DVD.

Los campos de número de discos y de duración del DVD funcionan correctamente.

Pruébenlo con estos datos:
Nombre: Batman
Género: Acción
Número de discos: 1
Duración; 126

¿Que puede estar pasando? (por cierto, mi código está compilado con GCC)

Saludos!
Título: Re: fgets y línea innecesaria
Publicado por: su - en Sábado 11 de Junio de 2011, 05:45
fgets toma todo el contenido de la linea, incluyendo el fin de linea (el "n" cunado presionas enter).
Título: Re: fgets y línea innecesaria
Publicado por: Amphoth3ra en Sábado 11 de Junio de 2011, 13:52
De esto deduzco que el fgets no me servirá si lo que quiero es poner todos los datos de la estructura en una sola línea, ya que para los campos 1 y 2 me toma el fin de la línea.

Me explico, lo que yo quiero es que los datos de la estructura se puedan imprimir así:
Batman Acción 1 126

Pero en realidad ahora se imprimen así:
Batman
Acción
1 126


¿Existe otra manera de que yo pueda guardar el string sin el salto de línea?

Saludos!
Título: Re: fgets y línea innecesaria
Publicado por: ProfesorX en Domingo 12 de Junio de 2011, 03:18
Cita de: "Amphoth3ra"
¿Existe otra manera de que yo pueda guardar el string sin el salto de línea?

Bueno, podrias usar la funcion strchr() para buscar el caracter de salto de linea, y reemplazarlo con el caracter de fin de cadena. De esa manera te evitarias ese problema. A continuacion te dejo el codigo de como hacerlo:

Código: C++
  1.  
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5.  
  6. struct dvd {
  7.     char name[255];
  8.     char genero[50];
  9.     int discs_number;
  10.     int length;
  11. };
  12.  
  13. int main()
  14. {
  15.     struct dvd temporal;
  16.     char discs_number[2];
  17.     char length[4];
  18.     char *pch;
  19.  
  20.     printf("Nombre del DVDn");
  21.     fgets(temporal.name, 255, stdin);
  22.     // Buscas la posicion del caracter nueva linea (10) en la cadena
  23.     pch = strchr(temporal.name, 10);
  24.     // Si la encontro, reemplazas nueva linea con nulo, que es el fin
  25.     // de cadena ('')
  26.     if (pch != NULL)
  27.     {
  28.         *pch = '';
  29.     }
  30.  
  31.     printf("%sn", temporal.name);
  32.  
  33.     printf("Género del DVDn");
  34.     fgets(temporal.genero, 50, stdin);
  35.     pch = strchr(temporal.genero, 10);
  36.     if (pch != NULL)
  37.     {
  38.         *pch = '';
  39.     }
  40.  
  41.     printf("%sn", temporal.genero);
  42.  
  43.     printf("Número de discos del DVDn");
  44.     fgets(discs_number, 2, stdin);
  45.  
  46.     temporal.discs_number = atoi(discs_number);
  47.  
  48.     printf("%dn", temporal.discs_number);
  49.  
  50.     printf("Duración del DVDn");
  51.  
  52.     while(getchar() != 'n');
  53.     fgets(length, 4, stdin);
  54.  
  55.     temporal.length = atoi(length);
  56.  
  57.     printf("%dn", temporal.length);
  58.  
  59.     printf("%s %s %d %d", temporal.name, temporal.genero, temporal.discs_number, temporal.length);
  60.     return(0);
  61. }
  62.  
  63.  

Ojala se adapte a lo que necesitas.

Saludos :)
Título: Re: fgets y línea innecesaria
Publicado por: Amphoth3ra en Domingo 12 de Junio de 2011, 13:46
Funcionó perfecto men, era justo lo que necesitaba, muchas gracias =)

Saludos!
Título: Re: [C] fgets y línea innecesaria [Solucionado]
Publicado por: su - en Domingo 12 de Junio de 2011, 19:02
Cuidado con la solucion de ProfesorX ya que en Windows el fin de linea esta dado por los caracteres 13 y 10 ("rn"), asi que tocaria hacerlo 2 veces, una para hallar "r" y la otra para "n".

Mejor usa sscanf para quitar el fin de linea o fscanf para leer sin este.
Código: C
  1. int main(void){
  2.     char linea[50];
  3.     fscanf(stdin, "%s", linea);
  4.     printf("Leido: %sn", linea);
  5.     return 0;
  6. }
  7.  

Tambien podes hacer tu propia funcion donde lees de stdin caracter por caracter hasta hallar el caracter 13 o 10.