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

[SOLUCIONADO] Problema en el bucle while

Estas en el tema de Problema en el bucle while en el foro de C/C++ en Foros del Web. Hola amigos, tengo una duda en este ejercicio: Se trata de implementar una función que devuelva la media de tres números, sean cuales sean (en ...
  #1 (permalink)  
Antiguo 13/07/2013, 06:13
 
Fecha de Ingreso: julio-2013
Ubicación: Vic
Mensajes: 26
Antigüedad: 10 años, 9 meses
Puntos: 0
Exclamación Problema en el bucle while

Hola amigos, tengo una duda en este ejercicio:
Se trata de implementar una función que devuelva la media de tres números, sean cuales sean (en coma flotante o no). Probarla en un programa. El programa finaliza solo cuando el usuario lo solicita.


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

double media(double a, double b, double c);

int main()
{
	double a, b, c, d;
	char s_n=' ';
	while(s_n!='n'){
		printf("Inserte 3 numeros:\n");
		scanf("%lf %lf %lf",&a, &b, &c);
		d = media(a, b, c);
		printf("%.2lf\n",d);
		printf("Volver a empezar? (s/n)\n");
		scanf("%c",&s_n);
	}
	getch();
	return 0;
}

double media (double a, double b, double c)
{
	double med = (a + b + c) / 3;
	return med;
}
El problema esta en que no me deja si triar si / no al final del bucle, me salta automáticamente al principio del bucle.

Un saludo.
  #2 (permalink)  
Antiguo 13/07/2013, 06:51
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Problema en el bucle while

Es un tema que ha salido varias veces en este foro; cuando entras por teclado con scanf la funcion lee el formato que le digas hasta encontrar un salto de linea (un enter); la lectura de stdin se comporta como una cola f.i.f.o.: caracter que lee caracter que saca sabiendo que el primer caracter que entra es el primero que sale. Por eso cuando lees %d se deja el salto de linea al final y en el siguiente scanf es el primero que encuentra y por tanto parece que salte el scanf. Se soluciona limpiando el stream de entrada

Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4.  
  5. double media(double a, double b, double c);
  6. void buida_bufer_teclat() {
  7.     char c;
  8.     do {
  9.         c = getchar();
  10.     } while (c != '\n');
  11. }
  12.  
  13.  
  14. int main() {
  15.     double a, b, c, d;
  16.     char s_n = ' ';
  17.  
  18.     while(s_n != 'n') {
  19.         printf("Inserte 3 numeros:\n");
  20.         scanf("%lf %lf %lf",&a, &b, &c);
  21.         buida_bufer_teclat();
  22.  
  23.         d = media(a, b, c);
  24.         printf("%.2lf\n",d);
  25.         printf("Volver a empezar? (s/n)\n");
  26.         scanf("%c", &s_n);
  27.         buida_bufer_teclat();
  28.     }
  29.  
  30.     return 0;
  31. }
  32.  
  33. double media (double a, double b, double c)
  34. {
  35.     double med = (a + b + c) / 3;
  36.     return med;
  37. }

De la funcion buida_bufer_teclat() puedes encontrar mil versiones por ahi, todas hacen lo mismo.


"...El problema esta en que no me deja si triar..."

En vez de 'triar' puedes poner 'optar' que se escribe igual y al menos significa algo :)

Saludos
vosk
  #3 (permalink)  
Antiguo 13/07/2013, 07:21
 
Fecha de Ingreso: julio-2013
Ubicación: Vic
Mensajes: 26
Antigüedad: 10 años, 9 meses
Puntos: 0
Respuesta: Problema en el bucle while

No entiendo que hace la funcion buida_bufer_teclat()


Muchas gracias por responder.

Saludos
  #4 (permalink)  
Antiguo 13/07/2013, 07:54
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Problema en el bucle while

Lee datos del stream de entrada hasta dar con un salto de linea; lo de 'leer' con el stdin significa copiar el caracter en un bufer y quitar de la cola, la finalidad de esta funcion no es saber lo que hay en la cola del stdin sino vaciarlo haya lo que haya, para que el siguiente 'scanf' o 'getchar' u otro no se encuentre con el salto de linea como primer caracter porque eso implica (segun la logica de la funcion scanf) que el usuario ha aceptado la entrada pinchando un enter, y como el anterior 's_n' es diferente de 'n' siempre repite. En este caso solo lee hasta dar con el primer salto de linea, puedes implementar para que lea hasta el EOF (eso vaciará completamente el stdin)

En el segundo scanf sabiendo que el primero te deja un salto de linea como primer elemento de lectura puedes forzar la lectura de un salto de linea seguido del caracter que te interesa

Código C:
Ver original
  1. scanf("\n%c", &s_n);

Dicho de otra forma, inicias la aplicacion y stdin está vacio. Pides tres numeros en formato senar + espacio + senar + espacio + senar, el usuario los entra (los entra correctamente, sin poner a prueba la aplicacion usando caracteres textuales en vez de numericos),
de forma que teclea el valor '2' y el stdin queda como [2], teclea un espacio y stdin queda como [2][SP], teclea 3 y stdin queda [2][SP][3], teclaea espacio, teclea un 4 y pincha enter; ahora mismo en stdin hay (**)

[2][SP][3][SP][4][CR] //SP es espacio, CR es carriage return alias enter

La funcion scanf va leyendo mientras haya algo en la cola, es decir que cuando tecleas el primer '2' ya está funcionando el scanf hasta completar el formato o hasta dar con el salto de linea (lo que antes ocurra detiene el proceso). Va copiando los datos a los buffers proporcionados y va quitando de stdin lo que copia

stdin = [2][SP][3][SP][4][CR]

Primero copia el 2 en &a, luego lee SP pero no lo copia porque no le proporcionas bufer de destino (podrias darle un %c despues del %lf y saltarte los espacios), ahora en stdin queda [3][SP][4][CR], sigue leyendo ahora copia 3 en &b, salta el SP, copia 4 en &c y finaliza porque ha completado el formato que le pediste, de forma que al final stdin = [CR]

(**)(en verdad en el momento que tecleas '2', scanf la copia a &a y se elimina de la cola y cuando vas a teclear el primer espacio el '2' ya no está y la cola está vacía, es decir que nunca hay una cola [2][SP][3][SP][4][CR], pero lo pongo asi como vision atemporal o como quieras decirlo, son todos los caracteres en el orden en que aparecen en la cola del stdin)

Despues de eso determinas la media, la muestras y preguntas si quiere repetir. Llamas a scanf y sabiendo que stdin aun tiene el ultimo [CR] que no leyó, sabiendo tambien que scanf lee mientras haya algo en la cola, y sabiendo que scanf finaliza cuando completa el formato o cuando encuentra CR (lo que antes ocurra), en el scanf para entrar 's/n' no guardas en 's_n' el caracter 's' o 'n' sino el '\n' [CR] que quedó como ultimo caracter el la cola del stdin ok?

Con 'buida_bufer_teclat()' lees y quietas de la cola ese \n que te hace saltar el scanf cuando buscas un caracter.

Saludos
vosk
  #5 (permalink)  
Antiguo 14/07/2013, 12:33
 
Fecha de Ingreso: julio-2013
Ubicación: Vic
Mensajes: 26
Antigüedad: 10 años, 9 meses
Puntos: 0
Respuesta: Problema en el bucle while

Muchas gracias, me ha servido mucho.

Un saludo

Etiquetas: bucle, int, numeros, programa
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 22:08.