Subsecções

23 Entrada e Saída Padrão

A forma com que um programa em C se comunica com o mundo externo é através de entrada e saída de dados: o usuário fornece dados via teclado e o programa imprime mensagens na tela. Todos os programas vistos até agora lêem suas entradas do teclado e produzem suas saídas na tela.

Em C toda entrada e saída é feita com fluxos (streams) de caracteres organizados em linhas. Cada linha consiste de zero ou mais caracteres e termina com o caracter de final de linha. Pode haver até 254 caracteres em uma linha (incluindo o caracter de final de linha). Quando um programa inicia, o sistema operacional automaticamente define quem é a entrada padrão (geralmente o teclado) e quem é a saída padrão (geralmente a tela).

As facilidades de entrada e saída não fazem parte da linguagem C . O que existe é uma biblioteca padrão de funções para manipular a transferência de dados entre programa e os dispositivos (devices) de saída e entrada padrão. Algumas destas funções são: scanf(), printf(), getchar(), puts(), gets(). Estas funções são declaradas no arquivo <stdio.h>. Existem funções úteis para conversão e teste de caracteres declaradas no arquivo <ctype.h>.

As funções de entrada e saída operam sobre streams (fluxos) de caracteres. Toda vez que uma função se entrada é chamada (por exemplo, getchar(), scanf()) ela verifica pela próxima entrada disponível na entrada padrão (por exemplo, texto digitado no teclado). Cada vez que uma função de saída é chamada, ela entrega o dado para a saída padrão (por exemplo, a tela).

As funções para leitura da entrada padrão e para escrita na saída padrão que têm sido usadas até agora são:

  1. Entrada e saída de caracteres:
    int getchar( void );
    int putchar( int );
    

  2. Entrada e saída de strings:
    char *gets(char *);
    int puts( char *);
    

  3. Entrada e saída formatada:
    int scanf(char *format, arg1, arg2, ... );
    int printf(char *format, arg1, arg2, ... );
    

23.1 Comandos de entrada e saída: getchar() e putchar()

Vamos discutir algumas funções de entrada de dados (diferente do scanf()). A entrada de texto é considerada como um fluxo de caratecteres. Um fluxo texto é uma sequência de caracteres dividida em linhas; cada linha consiste de zero ou mais caracteres seguido do caractere de nova linha (\n). Como programador, você não quer se preocupar em como as linhas são representadas fora do programa. Quem faz isso por você são funções de uma biblioteca padrão.

Suponha que você queira ler um único caractere, mas não quer usar o scanf(). Isso pode ser feito usando a função getchar(). A função putchar() aceita um argumento de entrada, cujo valor será impresso como caracter:

#include <stdio.h>

int main()
{
   char ch;

   printf("Digite algum caracter: ");

   ch = getchar();

   printf("\n A tecla pressionada eh %c.\n", ch);

}

O Resultado deste programa na tela é:

   Digite algum caracter: A
    A tecla pressionada eh A.

Outro exemplo:

#include <stdio.h>

int main()
{
   char ch;

   printf("Digite outro caracter: ");

   ch = getchar();

   putchar(ch);

}

O Resultado deste programa na tela é:

   Digite outro caracter: B
   B

23.2 Considerações sobre Leitura de Dados pelo Teclado

23.2.1 Lendo o teclado usando getchar()

getchar() é uma função da biblioteca padrão stdio. Cada vez que é chamada, esta função lê um caractere teclado; getchar começa a ler depois que a tecla \enteré digitada no final de uma sequência de caracteres (dizemos que a entrada para a função getchar() está no fluxo de entrada). A função getchar() retorna um valor, o caractere lido (mais precisamente, o código inteiro ASCII correspondente ao caractere).

Vejamos o que acontece quando um programa trivial é executado.

#include <stdio.h>

main(){

    int ch;

    ch = getchar();
}

getchar() obtém sua entrada do teclado. Portanto, quando o programa acima é executado, o programa espera que o usuário digite alguma coisa. Cada caractere digitado é mostrado no monitor. O usuário pode digitar diversos caracteres na mesma linha, inclusive backspace para corrigir caracteres já digitados. No momento que ele teclar \enter, o primeiro caractere da sequência digitada é o resultado da função getchar(). Portanto, na instrução do programa acima o caractere (ou melhor, o seu código ASCII) é atribuído a variável ch. Note que o usuário pode ter digitado diversos caracteres antes de teclar \enter, mas a função getchar() só começará a ler o que foi digitado depois que for teclado \enter. Além disso, com uma chamada da função getchar() só o primeiro caractere da sequência digitada é lida.

Você deve saber que o caractere de nova linha, \n, que tem o código ASCII 10, é automaticamente adicionado na sequência de caracteres de entrada quando o \enteré teclado. Isso não tem importância quando a função getchar() é chamada uma única vez, mas isto pode causar problemas quando ele é usado dentro de um laço.

No inicício de qualquer programa que usa getchar(), você deve incluir

#include <stdio.h>

Esta diretiva do pré-processador diz ao compilador para incluir informações sobre getchar() e EOF (mais sobre EOF mais tarde.).

Considere o seguinte programa:

   #include <stdio.h>

   int main(){
   
      int ch;
   
         printf( "Entre com uma letra: " );
         ch = getchar();
         if( ch < 'A' || ch > 'z' )
            printf( "Voce nao teclou uma letra!" );
         else
            printf( "Voce teclou %c, e seu codigo ASCII eh %d.\n", ch, ch );
   }

Um exemplo da execução do programa:

        Entre com uma letra: A
        Voce teclou A, e seu codigo ASCII eh 65.

No exemplo de execução acima o usuário teclou A e depois \enter.

Outro exemplo de execução do programa:

        Entre com uma letra: AbcD
        Voce teclou A, e seu codigo  ASCII eh 65.

Neste caso o usuário digitou quatro caracteres e depois teclou \enter. Embora quatro caracteres tenham sido digitados, somente uma chamada a função getchar() foi feita pelo programa, portanto só um caractere foi lido. O valor atribuído ao argumento da função é o código ASCII do primeiro caractere lido.

O tipo do resultado da função getchar() é int e não char. O valor retornado pela função é o código ASCII do caractere lido.

23.2.2 Marcando o final da entrada

Frequentemente quando você está digitando a entrada para o programa, você quer dizer ao programa que você terminou de digitar o que queria. Em ambiente Unix, digitando ^D (segure a tecla de Ctrl e pressione D) você diz ao programa que terminou a entrada do programa. Em ambiente MS-Windows, você faz isto digitando ^Z (segure a tecla de Ctrl e pressione Z).

Isto envia uma indicação para a função getchar(). Quando isso ocorre, o valor de ch depois de executar ch = getchar(); será um valor especial do tipo inteiro chamado EOF (que significa end of file - final do arquivo).

Considere o seguinte programa exemplo que conta o número de caracteres digitados (incluindo o caractere de ``próxima linha''):

  #include <stdio.h>

  int main()
  {

   int total = 0, ch;

   /* Le o proximo caractere em ch e para quando encontrar final do arquivo */
   while( (ch = getchar()) != EOF ) {
      total++;
   }
   printf( "\n%d caracteres digitados\n", total );
}

Só para esclarecer: você deve teclar \enterdepois de entrar com o comando ^D (ou ^Z no MS-Windows).

23.2.3 Para evitar problemas com a entrada...

(Observação: nesta seção, espaços em branco são relevantes e são mostrados como \verbspc)

Quando você executa um programa, cada caractere que você digita é lido e considerado como parte do fluxo de entrada. Por exemplo, quando você usa getchar(), você deve teclar \enterno final. Como mencionado anteriormente, o primeiro caractere digitado é lido pelo getchar(). Mas, o caractere de nova linha continua no fluxo de entrada (porque você teclou \enter).

De qualquer forma, se você executar um getchar() depois de um scanf() ou de um getchar() você lerá o caractere de nova linha deixado no fluxo de entrada.

Da mesma forma, quando você usa scanf() para ler informações, ele somente lê o que é necessário. Se voce usar scanf() para ler um número inteiro e digitar 42\verbspc\verbspc (seguido de \enter), o scanf() lê 42, mas deixa \verbspc\verbspc (e o caractere de nova linha do \enter) no fluxo de entrada.

Outro caso ``problemático'' é quando o scanf() é usado num laço. Se você digitar um valor do tipo errado, o scanf() lerá o valor errado e a execução do laço continuará na sentença após o scanf(). Na próxima iteração do laço o scanf() vai tentar ler novamente, mas o ``lixo'' deixado da iteração anterior ainda estará lá, e portanto a chamada corrente do scanf() também não dará certo. Este comportamento resultará num laço infinito (um laço que nunca termina), ou terminará e terá um resultado errado.

Há uma maneira simples de resolver este problema; toda vez que você usar getchar() (para ler um caracter só) ou scanf(), você deve ler todo o ``lixo'' restante até o caractere de nova linha. Colocando as seguinte linhas após chamadas a getchar() ou scanf() o problema é eliminado:

        /* Pula o restante da linha */
        while( getchar() != '\n' );

Note que isso não é necessário após todas as chamadas a getchar() ou scanf(). Só depois daquelas chamadas que precedem getchar() (ou scanf()), especialmente em um laço.

A função scanf() na realidade retorna um inteiro que é o número de itens (valores) lidos com sucesso. Você pode verificar se o scanf() funcionou testando se o valor retornado é igual ao número de especificadores de formato no primeiro argumento da função.

int main(){

   int total = 0, num;

   while( total < 20 ){
      printf( "Total = %d\n", total );

      printf( "Entre com um numero: " );
      if( scanf("%d", &num) < 1 )
          /* Ignora o resto da linha */
          while( getchar() != '\n' );
      else 
         total += num;
   }

   printf( "Final total = %d\n", total );
}

Armando Luiz Nicolini Delgado
2013-10-21