Saltar ao contido

C/scanf

En Galilibros, o Wikibooks en galego.
< C
C
← Volver a puts scanf Seguir con rewind


A función scanf() lee datos do ficheiro de entrada estándar, stdin, asociado ao teclado, os interpreta de acordo co formato especificado, e os almacena nos argumentos especificados. A función devolve un enteiro coa cantidade de datos lidos e asignados. A súa sintaxe básica é a seguinte:

scanf("Cadea co formato de entrada",lista de argumentos);

O primeiro argumento é unha cadea que contén o formato de entrada dos datos por parte do usuario, utilizando para tal fin marcadores de formato. O resto dos argumentos son as variables nas que se van cargar os datos interpretados pola función a partir da información introducida polo usuario. Os argumentos coas variables estarán na mesma orde que os seus correspondentes marcadores de formato, e as variables estarán precedidas por un & (paso por referencia). Vexamos un exemplo:

scanf("%d, %f",&numero_corredor, &puntuacion);

Onde temos que introducir primeiro o número do corredor (numero_corredor, de tipo enteiro en sistema decimal) e a súa puntuación (puntuacion, de tipo float), separados por unha coma e un espazo en branco.

Cómpre ter en conta que a función scanf, ao premer o usuario INTRO para indicar o final da lectura de datos, deixa ese último carácter (|n) no búfer de entrada por teclado e imprímeo ao mesmo tempo no programa, é dicir, despois da lectura de datos faise un salto de liña.

Limpar o lixo

[editar]

Aínda que pode soar algo estraño para quen o escoite por vez primeira, «scanf() deixa lixo, e hai que limpalo».

scanf() le unha serie de datos que o usuario introduce por teclado, e remata a lectura unha vez o usuario preme INTRO, é dicir, introduce un salto de liña (\n). O caso é que este salto de liña, que scanf() non necesita ler, queda no búfer de entrada por teclado (lixo), e a seguinte función que lea datos por teclado, coma o caso doutro scanf() ou similar, lerá dito dato coma se o usuario o acabase de introducir. E na meirande parte dos casos o desenvolvedor non quererá que isto aconteza.

Para evitalo existen diversas solucións, pero o problema da meirande parte delas é que depende moito do compilador e do sistema operativo con que se utilice. É por isto que a solución máis sinxela é unha función que se encargue de limpar o búfer de entrada por teclado:[1]

void Limpar(void) 
{ 
  // Declaración de variables
  int ch; 
 
  // Limpar
  while
  (
    (ch = fgetc(stdin)) != EOF
    &&
    ch != '\n'
  );
}

Así que, despois dun scanf() ou antes dunha función susceptible de ler o lixo do búfer de entrada, cómpre utilizar esta función.

Lectura de cadeas

[editar]

scanf() pode ler cadeas de caracteres. A sintaxe para esta tarefa difire lixeiramente da sintaxe que utiliza para ler caracteres ou valores numéricos:

scanf("%s",cadea);

Hai dous diferencias clave. A primeira e a máis obvia é o uso de %s, que indica que o dato a recibir vai ser unha cadea de caracteres. A segunda diferencia puido parecerlle a máis de un unha errata, pero o caso é que para ler cadeas fai falla omitir o símbolo & da variable que vai conter a cadea de caracteres lida por scanf().

Pero, se ben pode facelo, scanf() presenta unha serie de inconvenientes á hora de ler cadeas que o converten probablemente na peor función que poidamos usar para realizar este tipo de tarefas. Un dos inconvenientes máis salientables é o feito de que scanf() interpreta os espazos en branco coma separadores, polo que non nos permitiría introducir nunha variable unha cadea de caracteres que contivese espazos en branco.

Xeralmente, á hora de ler cadeas de texto, a función estándar de C escollida é gets().

Manexo de erros

[editar]

Cómpre lembrar que scanf() non «le un ou máis datos», senón que máis ben «intenta ler un ou máis datos». En todo momento hai que ter en conta a posibilidade de que o usuario introduza un valor que scanf() non sexa capaz de ler. Así que un programa ten que estar preparado para o que queira que introduza o usuario. Para iso abonda con coñecer as diferentes saídas que pode dar a función scanf() e mailo seu significado, e modificar o programa de xeito que actúe en función de dita saída, que haberá que asignar a unha variable numérica.

A función pode devolver un valor numérico entre -1 e o número de datos que esperaba recibir. Se non é capaz de procesar un dos datos introducidos, a función devolverá o número correspondente á posición ordinal de dito dato menos 1, é dicir, se por exemplo non procesa correctamente o segundo dato introducido, devolverá 1. En caso de que a función lea correctamente todos os datos introducidos, devolverá un número igual á cantidade de datos que tiña que ler. En caso de que a función lea o carácter ASCII 255, FdF, devolverá a constante EOF.

Sempre que a función falle ao procesar un dato introducido polo usuario, este dato quedará no búfer de entrada por teclado. Isto significa que o búfer quedará "manchado", e será necesario limpalo antes de que o programa volva utilizalo con outra función de entrada por teclado. Para facelo utilizaremos unha función que xa tivemos o pracer de coñecer: fflush(). Podemos situar dita función ben antes de calquera función de lectura por teclado, ou ben a continuación dela.

Un exemplo de manexo de erros con scanf() podería ser:

do{
  p=scanf("%d",&variable);
  fflush(stdin);
}while(p!=1);

Este ciclo pediralle ao usuario que introduza un valor para variable, e mentres o usuario non introduza un valor correcto, o ciclo repetirase. Se quitásemos a función fflush() e o usuario introducise un valor incorrecto, o ciclo entraría nun bucle sen fin.

Notas

[editar]
  1. Neste fío dun foro discútense as distintas alternativas para limpar o lixo que deixa a función scanf().


C
← Volver a puts scanf Seguir con rewind