Mostrando postagens com marcador scanf. Mostrar todas as postagens
Mostrando postagens com marcador scanf. Mostrar todas as postagens

segunda-feira, 25 de fevereiro de 2008

O scanf engana

Quando falei sobre a função scanf, chamei a atenção para a limpeza do buffer do teclado.
Naquele momento enfatizei que limpar o buffer do teclado evitaria algumas dores de cabeça.
Execute o código abaixo e verifique o seu funcionamento.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char chr1, chr2;
007:    
008:    printf("Digite o primeiro caractere: ");
009:    scanf("%c", &chr1
010:    printf("Digite o segundo caractere: ");
011:    scanf("%c", &chr2);
012:    printf("Primeiro caractere %c\nSegundo caractere: %c\n", chr1, chr2);
013:    system("PAUSE");
014:    return 0;
015:  }


Não fique nervoso tentando digitar o segundo caractere. Esse problema é bastante comum nos códigos de programadores pouco experientes. Tente limpar o buffer do teclado, utilizando a instrução fflush(stdin) antes de cada scanf. Você verá que agora o segundo caractere é lido.
Por que isso ocorre? Imagine o buffer do teclado como um arquivo seqüencial, onde o scanf retira os dados.
Para o exemplo anterior, na linha 9, o scanf espera que você digite um byte (estamos lendo variáveis do tipo char). O que você faz? Digita o caractere e em seguida o enter. Supondo que você digitou o caractere V, o buffer do teclado fica:


V\n


O \n representa o enter.
Após a execução da linha 9, o caractere V é armazenado na variável chr1, deixando o \n no buffer do teclado. Adivinhe que receberá o \n? Correto, a variável chr2. Por esse motivo ela não é lida!
Quando você usa a instrução fflush(stdin), e limpa o buffer do teclado, o \n sai do buffer, deixando ele limpo para a próxima leitura.

sexta-feira, 22 de fevereiro de 2008

lendo dados - a função scanf

Agora que você sabe como funciona o operador de endereço &, posso apresentar a você a função scanf (leia-se scanEFE).
Essa função, como a printf, está localizada na biblioteca stdio.h e serve como entrada de dados em seu programa. Tudo aquilo que você digita no teclado será lido por essa função.
É claro que para o scanf você deverá informar duas coisas:
  1. Em qual formato o dado será lido?
  2. Onde ele será armazenado?

Para informar o formato do dado para o scanf é necessário recorrer a tabela abaixo:
CódigoFormatação
%cLê um caractere
%dLê um inteiro positivo ou negativo (base decimal)
%iLê um inteiro positivo ou negativo (base decimal)
%eLê um número de ponto flutuante em notação científica
%fLê um número de ponto flutuante
%gLê um número de ponto flutuante podendo ser expressa em notação científica
%oLê um número em octal
%sLê uma cadeia de caracteres (string)
%uLê um inteiro sem sinal
%xLê um número hexadecimal
%nRecebe um valor inteiro correspondente ao número de caracteres lidos até então
%[]Busca por um conjunto de caracteres

A resposta genérica para a segunda pergunta é a memória. Devemos especificar para o scanf qual o endereço de memória ele deve guardar o dado inserido. Para essa operação utiliza-se o operador de endereço &.
A forma geral do scanf é:


scanf("código de formatação", lista de endereços);


Para ler duas variáveis, sexo e anoNascimento podemos fazer como no programa abaixo.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char sexo;
007:    int anoNascimento;
008:    printf("Digite o sexo\n[F] - Feminino\n[M] - Masculino\n");
009:    scanf("%c",&sexo);
010:    printf("Digite o ano de nascimento: ");
011:    scanf("%d",&anoNascimento);
012:    system("PAUSE");
013:    return 0;
014:  }


Note que nas linhas 9 e 11 o código de formatação indica somente o tipo de dado a ser lido.
O scanf permite ler mais de uma variável na mesma instrução. Adaptando o programa acima para ler em apenas uma instrução fica da seguinte forma:


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char sexo;
007:    int anoNascimento;
008:    printf("Digite o sexo\n[F] - Feminino\n[M] - Masculino\nEm seguida digite o ano de nascimento.");
009:    scanf("%c%d",&sexo, &anoNascimento);
010:    system("PAUSE");
011:    return 0;
012:  }


Particularmente não gosto dessa segunda opção porque não permite a limpeza do buffer do teclado entre uma leitura e outra. A limpeza é importante pois garante que nenhuma sujeira presente no buffer contaminará suas variáveis.
Para fazer a limpeza do buffer basta inserir a instrução


fflush(stdin);


antes de cada scanf.
Veja o primeiro programa escrito de uma forma mais segura.


001:  #include <stdio.h>
002:  #include <stdlib.h>
003:
004:  int main(int argc, char *argv[])
005:  {
006:    char sexo;
007:    int anoNascimento;
008:    printf("Digite o sexo\n[F] - Feminino\n[M] - Masculino\n");
009:    fflush(stdin);
010:    scanf("%c",&sexo);
011:    printf("Digite o ano de nascimento: ");
012:    fflush(stdin);
013:    scanf("%d",&anoNascimento);
014:    system("PAUSE");
015:    return 0;
016:  }


Agora sim, ler dados ficou ainda mais fácil!