problema con la sentencia if

Iniciado por bpenword, 12 Mayo 2019, 15:57 PM

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

bpenword

es un simple programa que pregunta edad y sexo, pero al ejecutarse se salta la sentencia if.

#include<stdio.h>
#include<stdlib.h>
int main(){
int edad; char sexo;

printf("ingresa tu edad:"); scanf("%d",&edad);

printf("ingresa tu sexo:F para mujer y M para hombre\n"); scanf("%c",&sexo);


if ((sexo=='F')&&(edad>23)) printf("usted es mujer y tiene más de 23 años");

if((sexo=='M')&&(edad>23)) printf("usted es hombre y tiene más de 23");

printf("usted no entra en el programa:)");

return 0;
}

K-YreX

El problema no es que se salte la condición sino que no te deja introducir el valor de <sexo>. Esto es porque al introducir la edad, introduces un número y pulsas Enter entonces en el buffer de entrada se guarda (imaginemos que introduces 20) <20 Enter>. Luego el programa busca en el buffer de entrada el valor de edad y encuentra un 20, por lo que el programa hace <edad = 20> y en el buffer queda <Enter>. Después el programa te pregunta el sexo y como el buffer no está vacío recoge el Enter y hace <sexo = Enter> (entíendase la asigación).

Para solucionar esto debes limpiar el buffer de entrada. Normalmente te recomendarán que hagas <fflush(stdin)> para limpiarlo. Sin embargo, <fflush()> es una función que se diseñó para limpiar el buffer de salida (<fflush(stdout)>) y aunque parece que funciona para el de entrada, siempre se recomienda no usarlo ya que no está definido formalmente su comportamiento para <stdin> (en los manuales oficiales de C se expone que el comportamiento es "indeterminado")

Tienes algunas alternativas como pueden ser:

getchar(); // alternativa 1: coge un caracter del buffer
fgetc(stdin); // alternativa 2: mas de lo mismo
// Para cuando puedes tener mas de un Enter tienes una alternativa 3: en bucle


Te dejo aquí un enlace a un tema que se abrió hace un tiempo tratando de buscar alternativas a <fflush(stdin)>:
https://foro.elhacker.net/programacion_cc/iquestqueda_algo_en_el_buffer_de_entrada_stdin_solucionado-t489993.0.html
Te recomiendo que uses algunas de estas para evitar ese <fflush(stdin)> que tanto daño hace. En el fondo mejor será conocer y aplicar buenas prácticas de programación.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

RayR

Cuidado, que en ese link dan 2 soluciones para limpiar el buffer, pero una de ellas, la que usa fseek, es casi tan mala como fflush(stdin). La verdad es que esa opción también es bastante antigua, y su problema es que parte de una premisa incorrecta: que stdin es un archivo, lo cual es falso. Lo tratamos como un archivo, pero en general, cuando nos referimos a la terminal (línea de comandos) no lo es.

La cuestión es que, en algunos sistemas stdin permite hacer búsquedas (fseek) y en otros no. Esa solución puede funcionar en Windows, igual que fflush(stdin) (aunque no hay garantía de que siempre lo haga... igual que fflush(stdin)), pero va a fallar en otros sistemas operativos, como Linux (igual que... creo que el punto está claro). De hecho, hasta hay documentación que lo dice. En Linux y algunos otros sistemas tipo Unix, la implementación de fseek llama internamente a la función del sistema lseek. La documentación oficial dice sobre esa función:

CitarOn Linux, using lseek() on a terminal device fails with the error ESPIPE.

Es decir, que usar lseek (y por lo tanto, fseek) en una terminal falla con el error ESPIPE.

Así que para limpiar el buffer lo mejor son las alternativas que te propusieron (getchar,() fgetc(stdin)), o la primera que aparece en ese link:

Código (cpp) [Seleccionar]
while((c = getchar()) != '\n')

Eso sí, mejor usar '\n', como te lo puse, que 0xA, que es lo que ponen en el link.