Parser de Entrada de Dados com scanf

por Fabio A. Mazzarino

Todo mundo sabe que printf faz escrita de dados, e que scanf faz leitura de dados, mas nem todo mundo sabe usar scanf para fazer parser de entrada de dados. Nest post vamos ensinar a fazer parser de formatos básicos usando scanf.

Primeiro a sintaxe básica:

scanf(<FORMATO>, <VAR1>, <VAR2>,...); 

O formato é uma string, podendo ser um literal, que contém o formato a ser lido, e uma série de especificadores de formato. Cada especificador de formato irá gerar um conteúdo para sua respectiva variável (VAR1, VAR2…). E a quantidade de variáveis depende da quantidade de especificadores de formato.

O valor do retorno é a quantidade de variáveis aonde foi feito o parser corretamente.

Vamos agora a lista de especificadores de formato:

  • %c – um único caracter
  • %d – número inteiro na base 10
  • %i – número inteiro na base 10, 8 ou 16
  • %e, %f ou %g – número de ponto flutuante
  • %o – número na base 8
  • %s – string
  • %x – número hexadecimal
  • %p – ponteiro
  • %n – um inteiro igual ao número de caracteres lidos até o momento
  • %u – um número natural na base 10
  • %[] – um conjunto de caracteres
  • %% – um caracter %

Vamos começar bem básico, lendo 3 caracteres:

char c1, c2, c3;
scanf("%c%c%c", &c1, &c2, &c3);

O código acima vai aceitar caracteres digitados até que o usuário digite ENTER. Porém somente fará a leitura dos três primeiros caracteres. E o retorno será 3.

Para ler uma data no formato YYYY-MM-DD, basta usar o código abaixo:

unsigned year, month, mday;
scanf("%04d-%02d-%02d", &year, &month, &mday);

Para saber se o parser ocorreu com sucesso, basta conferir o valor retornado. No caso acima em caso de sucesso o valor deve ser três.

É possível, inclusive interpretar um arquivo .csv sem utilizar strtok:

scanf("%4d;%2d;%2d;%[^;];%[^;]", &year, &month, &mday, name, email);

Que irá recuperar dados numéricos e textuais dos cinco primeiros campos da linha .csv

Tudo o que foi expresso sobre scanf nesse post também vale para sscanf, para fazer parser de um buffer em memória, e para fscanf, para fazer parser a partir do conteúdo de um arquivo.