Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: bpenword en 12 Mayo 2019, 15:57 pm



Título: problema con la sentencia if
Publicado por: bpenword en 12 Mayo 2019, 15:57 pm
es un simple programa que pregunta edad y sexo, pero al ejecutarse se salta la sentencia if.
Código:
#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;
}


Título: Re: problema con la sentencia if
Publicado por: K-YreX en 12 Mayo 2019, 16:36 pm
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:
Código
  1. getchar(); // alternativa 1: coge un caracter del buffer
  2. fgetc(stdin); // alternativa 2: mas de lo mismo
  3. // 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.


Título: Re: problema con la sentencia if
Publicado por: RayR en 12 Mayo 2019, 20:12 pm
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 (http://man7.org/linux/man-pages/man2/lseek.2.html#NOTES) dice sobre esa función:

Citar
On 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
  1. while((c = getchar()) != '\n')

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