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.

  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