Diario de un programador día 73
Lectura desde el teclado.
En esta ocasión se verá como solicitar información
al usuario, guardarla en una variable y luego mostrarla en pantalla.
Para leer datos se utilizará en primera instancia
la función scanf, la cual se utilizará para leer datos numéricos, pero para leer
cadenas se utilizará la función fgets, que es más segura que scanf, aunque con scanf también se pueden leer cadenas, pero como dije, en este caso se utilizará fgets que es más seguro y será explicado más abajo.
scanf()
Para tratar de entender esta función, se empezará
con un pequeño ejemplo, el cual solicitará un número entero y luego lo mostrará
en pantalla:
#include <stdio.h>
int main(void){
int num1;
printf("Escribe un
numero: ");
scanf("%d", &num1);
printf("El numero ingresado
es: %d", num1);
return 0;
}
La función scanf() tiene dos argumentos, %d y
&num1. El primer argumento es la cadena de control de formato, que indica
el tipo de dato que debe ser escrito por el usuario, en este caso un entero. El
segundo argumento empieza con el signo ampersand (&), llamado el operador
de dirección, seguido de una variable.
El ampersand al ser combinado con una variable, le indica a scanf la dirección
de memoria en la cual está almacenada la variable (en este caso num1), para
luego almacenar el valor de esa variable en esa posición de memoria. No olvidar el ampersand, a pesar de que el programa compila y se ejecuta, dará error al momento de ingresar un número, ya que no podrá asignar la memoria en forma adecuada.
El poder
trabajar directamente con la memoria hace que el lenguaje C gane en rendimiento en comparación con otros lenguajes a
la hora de producir programas, lo que lo hace ideal cuando se desea trabajar a
nivel de hardware.
Aquí otro ejemplo para seguir avanzando:
#include <stdio.h>
int main(void){
int num1, num2;
printf("Escribe un
numero: ");
scanf("%d", &num1);
printf("Escribe otro numero:
");
scanf("%d", &num2);
printf("num1 = %d, num2 = %d\n", num1, num2);
return 0;
}
Este programa
solicita dos números y luego los muestra en pantalla.
Por último, una
operación entre ellos:
#include <stdio.h>
int main(void){
int num1, num2, num3;
printf("Escribe un
numero: ");
scanf("%d", &num1);
printf("Escribe otro numero:
");
scanf("%d",
&num2);
num3 = num1 + num2;
printf("%d + %d =
%d\n", num1, num2, num3);
return 0;
}
fgets()
Esta función, también permite leer desde el
teclado y es mucho más segura para leer cadenas que scanf, debido a que es muy
probable que se produzca un desbordamiento de memoria o que se sobre escriban
sectores de memoria que no se debería, etc.
Aquí un ejemplo de su uso:
#include <stdio.h>
int main(void){
char palabra[5];
printf("Ingresa una palabra:
");
fgets(palabra, 5, stdin);
printf("La palabra es
%s\n", palabra);
return 0;
}
fgets()
utiliza tres argumentos, el primero es el nombre de la variable, el segundo el
largo de la cadena -1 y por último el flujo de entrada, en este caso se utiliza
el teclado (stdin). Que el largo de la cadena sea -1 significa en este caso, al ser 5,
que solamente leerá 4 caracteres. Si el largo de la cadena supera el número de
caracteres permitidos, entonces la palabra quedará cortada. En caso de que el
largo de la cadena sea inferior, la cadena terminará con un salto de línea. Si no interesa que genere un salto automático de línea, entonces está bien, pero si por algún motivo no se desea que realice un salto al finalizar la frase, se puede hacer lo siguiente:
if (variable[strlen(variable)-1] == '\n')
variable[strlen(variable)-1] = '\0';
variable[strlen(variable)-1] = '\0';
Nota: Para ocupar strlen se debe incluir
la cabecera string.h
Ejemplo:
#include <stdio.h>
#include <string.h>
int main(void){
char palabra[10];
int num;
printf("Ingresa una
palabra: ");
fgets(palabra, 10, stdin);
if (palabra[strlen(palabra)-1] == '\n')
palabra[strlen(palabra)-1] = '\0';
printf("Ingresa un numero:
");
scanf("%d", &num);
printf("La palabra es %s. El
numero es %d\n", palabra,num);
return 0;
}
Este programa lo que hace es solicitar el ingreso de una palabra o frase y un numero, para luego mostrar ambos ingresos en una misma línea.
Si se
escribe una palabra con 9 caracteres o menos incluyendo espacios, entonces no habrá problemas con
el programa y no realizará el salto de línea al finalizar la frase, pero si se escribe una palabra con 10 caracteres o más, entonces
ocurrirá uno de los problemas más comunes que pasan con la función scanf(), lo
que hará será tomar el resto de los caracteres que quedaron en memoria y los
utilizará como si fuesen un ingreso normal, lo que dará a lugar a errores. Es
solo cosa de que intentes ingresar una palabra de 10 caracteres o más (en este
caso) y verás lo que hace.
A modo de ejemplo y para que vean que no miento XD, ejecutaré nuevamente el programa y cuando me solicite una palabra escribiré "hola mundo" y verán que pasa:
La frase "hola mundo" tiene 10 caracteres (9 letras y un espacio), entonces, al sobrepasar el límite, la última letra pasó a formar parte del buffer y fue utilizada para realizar el ingreso automático del número, generando el error que se muestra. El número que se muestra, podría ser cualquier cosa, como una dirección de memoria o algo más. En alguna oportunidad creo haber mencionado que en C se pueden producir errores inesperados. Y es que C no respeta nada, si C te pide un número y tu le entregas un caracter... te lo acepta, pero tu debes aceptar también los resultados. Esta situación lo hace algo peligroso, sobre todo si se trabaja en sistemas como linux, ya que C no te advierte nada. Si no estás pendiente de lo que haces, facilmente te puedes "cargar" tu disco duro sobreescribiendo la tabla de partición. Si tu dices "Quiero que escribas en tal lugar", C te dirá "ok, escribo en tal lugar". Así que ten cuidado, por ahí alguien dijo "Echar a perder un disco duro no es una posibilidad, es una probabilidad, así que haz respaldo de tus archivos de vez en cuando"
Volviendo a lo nuestro. Es por esto que hay que tener cuidado al
utilizar scanf en combinación con funciones que lean cadenas, (En realidad, es mejor no hacerlo). Otro de los
problemas con scanf que no mencioné es que tiene problemas para leer frases.
Esto es debido porque toda frase está separada por espacios.
La función
scanf dice que solo leera caracteres
hasta que encuentre un “Enter” o un “espacio” y al encontrar cualquiera de las dos situaciones, no seguira "leyendo" y todo lo que se haya escrito despues del espacio en blanco quedará en memoria (buffer) disponible para un proximo ingreso. Con fgets no hay problemas
en leer frases siempre y cuando el argumento del largo de la cadena lo permita.
En resumen.
Scanf()
para números y fgets() para cadenas. Hasta la próxima.
Gustavo J. Cerda Nilo
Enero 2016, última actualización Mayo 2016
No hay comentarios:
Publicar un comentario