--------------------------------------------------------------------------------------------------
La mayoría que recién esta empezando con C/C++ y viene al foro a sacarse dudas, cometen errores similares. Incluso muchos tienen conceptos erroneos sobre la utilidad o eficiencia de ciertas funciones, probablemente debido a el estudio de textos incorrectos o de libros anticuados.
Pero incluso a veces uno no puede escapar de ciertas cosas. Imaginen a alguien que recien entra en la universidad y el profesor le hace incluir conio para utilizar getch. Seguramente el alumno de por sentado que hacer eso esta perfecto, e incluso el profesor recompense con notas altas a los que programan tal cual se ha enseñado.
Por lo tanto, ciertas cosas son comprensibles y el unico consejo que se puede dar es que nunca den por sentado algo, es recomendable informarse antes para ver que es lo que se esta realizando, sobre todo en programación.
1) gets();
La falta de control en un programa es un factor bastante negativo, y también peligroso en caso de programas comerciales o masivos. Ese es el principal problema de gets, no tiene control interno.
¿Que signifca no tener control interno?
Significa que la funcion acarrea como consecuencia el mal comportamiento del programa, resultados inesperados y erroneos, vulnerabilidades entre otras tantas cosas.
Define una cadena de 10 caracteres, y gets va a aceptarte eso y muchisimo mas como entrada.
Veamos este codigo:
#include
int main()
{
char letra1[]="AAAAA";
char letra2[]="BBBBB";
char letra3[]="CCCCC";
printf("A: %s\nB: %s\nC: %s\n\n",letra1,letra2,letra3);
printf("Ingrese la letra D, 5 veces: ");
gets(letra2);
printf("\nA: %s\nB: %s\nC: %s\n\n",letra1,letra2,letra3);
getchar();
}
[input/output]
A: AAAAA
B: BBBBB
C: CCCCC
Ingrese la letra D, 5 veces: DDDDD
A: AAAAA
B: DDDDD
C: CCCCC
[/input/output]
Como vemos nada paso, y los elementos de letra2 se reemplazaron por el input ingresado como debería ser . Ahora en vez de 5 veces, ingresemos la letra 'D' mas veces de lo que el programa nos indica:
[input/output]
A: AAAAA
B: BBBBB
C: CCCCC
Ingrese la letra D, 5 veces: DDDDDDDDDDDDDDDDDDD
A: DDD
B: DDDDD
C: CCCCC
[/input/output]
Que paso con letra1? precisamente lo que no queremos que pase en nuestro programa. gets sobreescribio una zona de memoria que no debia sobreescribir, ya que el input debia ser ingresado en letra2, pero simplemente no le importo que el input sea muchisimo mas grande que el tamaño de la cadena. Razon mas que suficiente para no utilizarla.
Por lo tanto es recomendable utilizar fgets();
fgets(char *string, int length, FILE * stream);
Es decir:
fgets(letra2, 5, stdin);
Con fgets permites que sean ingresados lenght-1 caracteres.
Aunque no todo es color de rosas, y en caso de que se ingresen menos caracteres de los que has definido como tamaño, tendras que lidiar con un salto de linea '\n'. Obviamente es una nimiedad que puedes arreglarla de esta forma:
if (letra2[strlen(letra2)-1] == '\n')//string.h para strlen();
letra2[strlen(letra2)-1] = '\0';
Supongo que con esto queda claro que no tiene sentido utilizar gets();.
Links:
http://en.wikipedia.org/wiki/Fgets
http://www.gidnetwork.com/b-56.html
2) fflush(stdin);
fflush(stdin) es un invitado casi diario. Pocas veces pasa un dia sin que alguien lo recomiende o lo mencione como la solucion! a los malos comportamientos de las pausas en los programas.
STDIN, como su nombre lo indica, significa 'Standard input'. Es decir, el ingreso por teclado.
Acorde al Standard, fflush espera solamente un stream de salida (STDOUT: 'Standard Output) por lo que el comportamiento con streams de entrada como STDIN es indefinido. Por mas que en algunas plataformas funcione, o que en algunos compiladores funcione, no deberia ser utilizado.
Por el otro lado, para evitar esas pausas fastidiosas es necesario evitar las funciones que dejan basura por doquier (como scanf();) y utilizar funciones como la ya mencionada fgets();
http://foro.elhacker.net/programacion_cc/fflushstdin-t91101.0.html
http://foro.elhacker.net/programacion_cc/zanjar_de_una_vez_fflushstdin-t265125.0.html;msg1294511
http://foro.elhacker.net/programacion_cc/error_super_basico_en_c_quien_me_ayuda_soy_nuevo-t262118.0.html;msg1275898
http://foro.elhacker.net/programacion_cc/problema_con_el_compilador_gcc_de_ubuntu-t248582.0.html
3) system("PAUSE");
Otro invitado diario es la pausa utilizando system. Esto incluso me ha tocado en mi universidad. Que el profesor me haga realizar ejercicios exclusivamente utilizando system y la pausa tambien habia que realizarla exclusivamente utilizando system. En fin, seguramente muchos consideren que realizar esto no es un gran problema, y probablemente tengan razon en los codigos que uno realiza como tarea estudiantil. Pero es un habito malo, y como todo, hay que dejarlo algun dia. Claramente no puedes pasarte toda la vida llamando al sistema para hacer una pausa.
*No es portable, solo va a funcionar en sistemas que tengan el comando PAUSE.
*Es una funcion pesada. Llamar al sistema, suspender tu programa, buscar el comando PAUSE, etc etc etc etc.
Por el otro lado si se siguio la norma de no dejar basura en el buffer de entrada, se puede utilizar soluciones mas sencillas como getchar(); (o cin.get(); en C++).
4) conio.h
Librerias inutiles si las hay, pero por sobre todas las cosas NO standard. No existe problema para el cual sea exclusivamente necesario utilizar conio.h. Y visto que aca la mayoria de los que la incluyen lo hacen para utilizar getch(); supongo que con todo el parrafo anterior habran quedado claras las alternativas.
http://en.wikipedia.org/wiki/Conio.h
http://www.gidforums.com/t-7379.html
2 comentarios: