Poner contraseña

Iniciado por Risketo, 25 Julio 2012, 02:05 AM

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

Risketo

Buenas, estudiando c quería hacer un programa que pidiese contraseña y simplemente termine cuando se ponga la contraseña correcta.

#include <stdio.h>
#include <string.h>

int main()
{
char passwd[]="xD", texto[3]; 

do {
printf ("Introduce la contrasena: ");
fgets(texto,3,stdin);

if (strcmp(passwd, texto)==0){
printf ("Contrasena correcta");
}
else {
printf ("Contrasena incorrecta\n");
}
}
while (strcmp(passwd, texto)!=0);

return 0;
}



El código compila sin errores y funciona al poner la contraseña correcta, pero cuando pongo una incorrecta me devuelve lo siguiente:



Introduce la contraseña: sfsd
Contraseña incorrecta
Introduce la contraseña: Contraseña incorrecta
Introduce la contraseña: Contraseña incorrecta
Introduce la contraseña:



Y si introduzco la contraseña seguido de algo mas la da por valida, por ejemplo:



Introduce la contraseña: xDasf
Contraseña correcta


Muchas gracias de antemano.

Fire544

#1
A ver intenta limpiar con fflush en stdin antes de la entrada con fgets() y modifica la iteraccion while(strcmp(passwd, texto)==0) por while(texto[0]==0); Suerte !! :xD
"Si enseñas a pezcar a un niño lo ayudas para toda la vida, si pezcas para alimentarlo lo ayudas por un momento".

durasno

Hola! no es recomendado usar fflush para stdin ya que no esta definido.

Este problema ya fue discutido muchas veces asi que voy a ser lo mas claro posible. Cuando se ingresan caracteres por teclado, estos se almacenan en un "bufer" para que luego funciones como fgets, scanf, etc tomen los caracteres de ahi.
Aclaracion 1: el ENTER(\n) tambien es un caracter, osea que tambien se almacena en el bufer
Aclaracion 2: fgets lee hasta encontrar un ENTER o como maximo n-1 caracteres
Supongamos que se ingresa esta cadena: "xDabcde\n". En este caso vos indicaste a fgets que lea 3-1 caracteres, es decir los caracteres 'x' y 'D' se almacenan en el arreglo texto. Es por esto que si se ingresa cualquier cadena, siempre y cuando empiece con "xD", imprime "contraseña correcta" (Esto seria la respuesta a tu segunda duda)

Ahora supongamos que se ingresa otra cadena: "asdfzxc\n". ¿que sucede ahora? como antes los primeros dos caracteres('a' y 's') se almacenan en texto y se imprime "contraseña incorrecta". ¿pero por que despues no podes ingresar y vuelve a imprimir "contraseña incorrecta" varias veces? Esto se debe a que en el bufer aun queda el resto de la cadena: "dfzxc\n". Para solucionar esto hay que limpiar el bufer; despues de fgets agrega:
while(getchar()!='\n'); // getchar lee del bufer hasta encontrar un '\n', osea limpia el bufer


Saludos
Ahorrate una pregunta, lee el man

Risketo

#3
Muchas gracias me ha servido lo del fgets pero si pongo un while(getchar()!='\n'); se produce un buble infinito.


Edito: si modifico el fgets por fgets(texto,30,stdin); no tengo problema al poner una contraseña incorrecta, pero no sirve la correcta, la verdad es que no se que puede ser.

durasno

Veo que aun no entendiste bien(no es un tema facil al principio). Lo que hace el getchar() dentro del  while es ir leyendo del bufer caracter por caracter hasta encontrar un ENTER, osea limpia el bufer... ¿¿¿seguro te genera un bucle infinito??? es raro

#include <stdio.h>
#include <string.h>

int main()
{
char passwd[]="xD", texto[3]; 

do {
printf ("Introduce la contrasena: ");
fgets(texto,3,stdin);
                while(getchar()!='\n');

if (strcmp(passwd, texto)==0){
printf ("Contrasena correcta");
}
else {
printf ("Contrasena incorrecta\n");
}
}
while (strcmp(passwd, texto)!=0);
system("PAUSE");
return 0;
}


Creo q tampoco sabes bien el uso de fgets(), mira este link: http://c.conclase.net/librerias/?ansifun=fgets


Saludos
Ahorrate una pregunta, lee el man

Risketo

Me generaba un buble infinito porque cambié el fgets por fgets(texto,30,stdin).
Y respecto al fgets, como le ordeno que si lee por ejemplo xDasd lo de por incorrecto?

Gracias a todos por responder.

rir3760

Los problemas del programa original son dos: el primero es el tamaño del array para almacenar la linea introducida por el usuario y el segundo que no eliminas (si es el caso) el resto de la linea.

El primero se elimina simplemente ajustando el tamaño del segundo array para que pueda contener la contraseña mas un carácter adicional y el segundo revisando la linea introducida por el usuario (cortesía de la función "strchr"): si no se encuentra el carácter '\n' significa que hay que descartar caracteres (el resto de la linea).

En cuanto a tu segunda pregunta "fgets" solo lee la linea, si deseas una comparación debes utilizar la función "strcmp".

El programa con las correcciones es:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
   char contra[] = "xD";
   char linea[sizeof contra + 1];
   char *p;
   
   while (1){
      printf("Introduce la contrasena: ");
      fflush(stdout);
      if (fgets(linea, (int) sizeof linea, stdin) == NULL)
         return EXIT_FAILURE;
     
      if ((p = strchr(linea, '\n')) != NULL)
         *p = '\0';
     
      if (strcmp(contra, linea) == 0){
         puts("Contrasena correcta");
         break;
      }else if (p == NULL){
         int ch;
         
         while ((ch = getchar()) != EOF && ch != '\n')
            ;
      }
   }
   
   return EXIT_SUCCESS;
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Risketo

Vale, muchas gracias me voy a mirar como funcionan los punteros para entender el programa al 100%.