#include <stdio.h>
int
main (void)
{
int n, t, i;
int a[10];
printf ("Introduce dos numeros separados por un espacio ?");
scanf ("%d %d", &n, &t);
printf ("Has introducido %d y %d\n", n, t);
printf ("Introduce 10 numeros separados por espacios?\n");
for (i = 0; i < 10; scanf ("%d", &a[i++]));
printf ("Has introducido: ");
for (i = 0; i < 10; i++) printf ("%d ", a[i]);
printf ("\n");
return 0;
}La forma más sencilla y directa de leer datos del usuario en C es
utilizando la función de la librería estándar scanf. Esta
función utiliza format strings (o cadenas de formato) idénticas
a printf para leer información del usuario y convertirla
automáticamente al formato que nos interese, en este ejemplo en
enteros.
La función scanf requiere el uso del operador
&. Este operador en C nos permite acceder al puntero a
la variable que indicamos, es decir, a la posición de memoria en la que
se encuentra. Su nombre es Address-of, o
Dirección de. Sin entrar en más detalles, en C, debemos
utilizar este operador para los parámetros de salida de las funciones….
cada vez que necesitamos modificar el valor de una variable dentro de
una función.
C solo permite llamar a las funciones por valor. En este modo, se hace una copia de los valores de los parámetros, los cuales se pasan a la función para que haga su trabajo. Sin embargo, puesto que estamos pasando una copia de los valores de los parámetros, cualquier cambio que hagamos en la función se aplicará sobre la copia y no afectará a la variable original.
Para conseguir esto, es necesario llamar a la función por referencia. En este caso en lugar de la copia del valor del parámetro, pasamos una referencia al mismo, de forma que podamos modificarlo dentro de la función. En C esto se consigue pasando el puntero a la variable, utilizando el operador
&. Estrictamente hablando, seguimos llamando a la función por valor, solo que ahora el valor es una referencia. Otros lenguajes, permiten diferenciar entre estas dos modalidades de forma más clara.
Como veremos en breve, uno de los problemas al leer información del
usuario es que la forma que tiene el usuario de indicar al ordenador que
ha terminado de escribir sus datos es pulsando la tecla
ENTER. Dependiendo de la forma de obtener esta entrada del
usuario, puede ser que el caracter \n (la tecla
ENTER) esté presente en el resultado y sea necesario
eliminarlo. Utilizando la función scanf no tenemos este
problema…. Otro gallo cantaría si hubiéramos utilizado
fgets.
Nuestro programa puede obtener fácilmente los datos de un fichero en lugar de desde la consola simplemente redirigiendo el fichero a la entrada estándar del programa.
$ cat <<EOM | ./input > 3 4 > 0 1 2 3 4 5 6 7 8 9 > EOM Introduce dos números separados por espacios? Has introducido 3 y 4 Introduce 10 números separados por espacios ? 0 1 2 3 4 5 6 7 8 9
Si bien, el uso de scanf es muy útil para ejemplos
sencillos, en el mundo real, esta función es bastante problemática por
cuestiones como el manejo de los retornos de carro que mencionamos
anteriormente. En estas situaciones es mejor leer la cadena
completamente y parsearla de forma específica para detectar errores.
En nuestro sencillo ejemplo, si pulsamos enter tras introducir 3 o 4
valores, el programa funcionará igual pero no mostraría un error.
Posteriores scanf en el programa se confundirían y leerían
datos incorrectos.
Una forma más correcta sería leer todo el texto en un buffer, y luego parsear los datos según nuestras necesidades. Por ejemplo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main (void)
{
int i;
int a[10];
char buf[1024], *aux, *end;
printf ("Introduce 10 numeros separados por espacios?\n");
fgets (buf, 1024, stdin);
aux = strtok(buf, " ");
for (i = 0; i < 10; i++) {
if (!aux) {printf ("ERROR\n"); return -1;}
a[i] = strtold (aux, &end);
if (a[i] == 0 && end == aux) {printf ("ERROR1\n"); return -1;}
aux = strtok(NULL, " ");
}
printf ("Has introducido: ");
for (i = 0; i < 10; i++) printf ("%d ", a[i]);
printf ("\n");
return 0;
}Este programa lee una línea completa de datos y la parsea utilizando
strtok que nos permite extraer tokens de una cadena de
caracteres usando el delimitador que queramos, en este caso el espacio.
El bucle convierte cada token en un entero usando strtold
que nos permite detectar errores en caso de que el número introducido no
sea correcto (un texto por ejemplo). El programa también termina con un
error si leemos menos de 10 valores. En ese caso la llamada
strtok retornará NULL puesto que no hay
suficientes tokens en la línea.
En general, es mejor escribir código específico para leer y manejar
los posibles errores en nuestros programas C que usar la función
estándar scanf.
SUMARIO
- Podemos leer datos en nuestros programas usando la función
scanf. scanfrequire que pasemos los valores por referenica (punteros a los datos), para poder modificar las variables internamente.- Si necesitas controlar la validez de los datos entrados por el usuario,
scanfno es una buena opción y es mejor implementar tu propio código para leer y parsear los datos
■
