[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: gets() en Lenguaje C.



El sáb, 12-01-2002 a las 20:17, Jose Luis Alarcon escribió:
>   Por favor, si hay por aqui alguien que
> conozca el C, le pido encarecidamente que
> eche un vistazo al programa que adjunto (es
> muy cortito) y averigue por que diablos
> falla la orden gets().

Amoaver...he estado siguiendo el thread desde el armario, pero ya no
puedo más:

Vamos con el código que pones:


1- Primero y fundamental:
....
char respuesta='s';

printf("¿Quieres Introducir un nuevo Dato?: ");
    scanf("%s", &respuesta);
    if (respuesta == 's')
....

hay al menos tres errores en cuatro lineas:
1- scanf aquí te recoge un (char *), y tu lo almacenas en un (char). Lo
raro es que no te dé un core dump. porque AL MENOS, vas a recibir DOS
caracteres ( pulsando return obtienes la secuencia { '\n','\0' }. Bueno,
miento. rectifico: scanf no retorna el '\n' si no se lo pides
expresamente, pero en cualquier caso devuelve un string, no un char
2- si pulsas return la variable se modifica. Lo normal es que return sea
una secuencia de aceptación con lo que el if se debe modificar... (? que
tal un switch con todas las opciones?( yes/Yes/Y/y/Si/si/No/no ..... )
3- dado que scanf devuelve un string, lo lógico es comparar con un
string, no con un char... el if se hace con strcasecmp, no comparando
caracteres. Como alternativa puedes comparar con el primer caracter del
string... previa conversión a char

2- Sobre gets()

El manual lo dice muy clarito: NO USAR gets() a menos que estés borracho
o estés haciendo el programa para alguien a quien odias ( creo que el
info lo dice más o menos así )

lo que hay que hacer es cambiar gets(buffer) por
fgets(buffer,size,stdin). Problema: gets elimina el retorno de carro,
mientras que fgets lo mantiene. 
El substituto correcto de gets(buffer) es:

if (fgets(buffer,sizeof(buffer),stdin) ) {
	if ( buffer[strlen(buffer)-1] == '\n' )
 		buffer[strlen(buffer)-1]='\0';
	fflush(stdin);
}

- la primera linea coge el string. fgets coge como maximo size-1
caracteres, y añade un '\0' al final
- la segunda linea elimina el retorno de carro, si lo hubiera
- la tercera linea vacia el buffer de entrada, dejandolo limpio para
nuevos datos

Por otro lado, hay un error de concepto en el orden de ejecución: el
programa se mete en un bucle infinito que tienes que abortar con
control-c... ¿Seguro que lo has copiado de un libro? Pues yo que tu
demandaba al editor :)

Por último no haces la más mínima comprobación de lo que te meten. !!Al
menos comprueba que no recibes un EOF!!. Recuerda que en UNIX la entrada
standard no tiene por qué ser el teclado....

El programa correcto es pues el que mando en el adjunto. Hay todavía un
par de errores gordos de concepto en cuanto a seguridad ( el usar
system() sin ajustar el entorno, por ejemplo ), pero por lo menos hace
lo que se le pide. observa que en lugar de dos fputs(), los agrupo con
un fprintf(). Mucho más eficiente... además garantizo todas las posibles
salidas del programa cerrando todo correctamente

Pues eso. Saludos
PS: RTFM !!!

-- 
        Juan Antonio          \|||/
                             / _ _ \
                             \ o o /
=========================o00o===U===o00o======================================
Juan Antonio Martinez               Universidad Politecnica de Madrid
email: jantonio@dit.upm.es          E.T.S.I Telecomunicacion
http://www.dit.upm.es/~jantonio     Ciudad Universitaria s/n
Tel:   34-1-3367366 ext 416         Laboratorio de Programación. Desp
A-127-2
Fax:   34-1-3367333                 28040 Madrid, Spain
==============================================================================
¿Y que haríais si Dios os Dijera: "Os ordeno que, por encima de todo, 
seáis felices el resto de vuestra vida"?  - Richard Bach
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>


FILE *canal;

char *coge_string(FILE *file) {
	static char buffer[2048];
	if (fgets(buffer,sizeof(buffer),file) ) {
		if ( buffer[strlen(buffer)-1] == '\n' ) 			buffer[strlen(buffer)-1]='\0';
		fflush(stdin);
	}
	return (char *) &buffer[0];
}

int main(int argc, char *argv[] ){
	int flag=1;
	char *dato;
	system("clear"); /* se puede hacer de otra forma, pero bueno */
	if ( ! (canal=fopen("datos.txt","a+")) ){
		fprintf(stderr,"Error abriendo fichero");
		exit(1);
	}
	while(1) {
	fprintf(stdout,"Quieres introducir un nuevo dato? ");
	if ( ! (dato=coge_string(stdin)) ) { fclose(canal); exit(0); }
	if (!strlen(dato) ) strcpy(dato,"y"); /* default */
	switch (*dato) {
		case 'N': case 'n': fclose(canal); exit(0);
		case 'Y': case 'y': case 'S': case 's':
			fprintf(stdout,"Introduce dato: ");
			if ( dato=coge_string(stdin))
				fprintf(canal,"%s\n",dato);
			break;
		default: fprintf(stderr,"Entrada incorrecta\n");
			break;
	    } /* switch */
	} /* while */
	/* nunca debería llegar aquí, pero por si acaso */
	fclose(canal);
	exit(0);
}

Attachment: pgpEVgiT95kH_.pgp
Description: PGP signature


Reply to: