FANDOM


Este artigo faz parte do FAQ para a linguagem C. Para o índice do FAQ, confira C/Faq. Para a linguagem em si, confira C.

Antes de acrescentar dúvidas a este FAQ, confira a Política de FAQ!

Como "pausar" o programa?Editar

Use a função getchar(), da <stdio.h>. Esta função aguarda pela tecla Enter. Ou então use system("pause"). Esta segunda solução precisa do header <stdlib.h> e é dependente de sistema (depende do DOS ou do Windows) por isso é preferível usar a primeira solução na maioria dos casos.

Eu coloquei o getchar()! Por que não funcionou?Editar

Se não funcionou significa que o getchar() pegou algum valor que ficou perdido no buffer, isso acontece quando você digita mais informação do que o programa desejava ler. Assim, os caracteres excedentes ficam esperando no buffer para serem consumidos pela próxima leitura. Para corrigir isto, use uma função para ler todos os caracteres do buffer até o fim da linha (já que a entrada sempre é terminada com um Enter). Note que a função scanf é caracterizada por deixar o '\n' no buffer se você não consumi-lo explicitamente, e a função fgets é caracterizada por ler até o '\n' e retirá-lo do buffer (portanto tornando desnecessário limpar o buffer).

Em C:

#include <stdio.h>

void limpaBuffer()
{
    int c;
    while((c = getchar()) != '\n' && c != EOF){
        /* vazio mesmo */
    }
}

Em C++, pode ser igual ao C, ou assim:

#include <iostream>
#include <limits>	

void limpaBuffer()
{
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Ou ainda:

    std::cin.sync();

Com o buffer limpo o getchar() irá funcionar perfeitamente.

E o que é "buffer"?Editar

Quando uma função de leitura é chamada, os caracteres digitados não são enviados diretamente para o seu programa, eles são primeiro armazenados numa memória temporária (buffer). É por isso que uma só chamada a getchar permite ao usuário digitar uma linha inteira e também usar backspace. Somente depois de pressionar Enter, o programa receberá o caractere digitado. Então as chamadas subseqüentes a getchar receberão os outros caracteres que foram armazenados no buffer, até que ele fique vazio (até o Enter). Nesse momento, se uma função de leitura for chamada, o programa novamente parará pra esperar o usuário digitar algo.

A explicação acima se refere à entrada interativa (o usuário digitando no teclado). Quando a entrada é feita através de um arquivo, também se usa um buffer internamente, mas por questões apenas de eficiência (evitar acessar o disco para leituras muito pequenas) e não há a questão de "esperar pelo Enter".

Por que um fgets logo após um scanf não funciona?Editar

Pelo mesmo problema explicado acima: caracteres excedentes no buffer.

Veja como funciona a chamada scanf("%d", &a):

a) O primeiro passo que o scanf executa para ler um %d é ignorar espaços encontrados. Isso é válido para todos os especificadores de formato, exceto %c e %[. Também é possível fazer esses especificadores ignorarem espaços colocando um caracter de espaço antes do %, por exemplo: " %c" ou "\n%c".

b) Ler caracteres que podem formar um número, isto é, os dígitos de 0 a 9 (porque %d indica um número decimal), possivelmente com sinal negativo

c) Quando um caracter que não faz parte de um número aparecer (isso inclui a quebra de linha: o '\n'), terminar a leitura e retornar esse caracter à entrada. É possível ler um caracter com c = getchar() e depois "desfazer" a leitura com ungetc(c, stdin), e é isso que o scanf faz.

d) Armazenar o número lido. Se essa é a única coisa que deve ser lida, a função scanf termina, retornando 1, pois foi lido 1 "item". Se o scanf não pôde fazer a leitura do %d (por exemplo, o 1º. caracter encontrado era uma letra), ele retorna 0. Poderia também retornar EOF se o arquivo tiver acabado antes de qualquer leitura.

Conforme explicado no item "c", a quebra de linha, por não fazer parte do número, é deixada para a próxima leitura. Se o scanf for chamado novamente, ela será ignorada pelo passo "a". Mas se for chamada a função fgets, ela encontrará uma linha vazia e retornará imediatamente

Por que a função scanf funciona diferente da função fgets?Editar

Elas têm propósitos diferentes. O scanf serve para extrair campos de informação, normalmente separados por espaços ou mudanças de linha, indiferentemente. Já o fgets serve pra ler linhas inteiras, exatamente como elas estão na entrada (digitada ou extraída de uma arquivo). Por isso o fgets lê até o caractere '\n', remove esse caractere da entrada e o inclui na string retornada ao seu programa. O caso da função gets, ligeiramente diferente de fgets, não será discutido porque você não deve usar essa função (ela é muito propensa a erros).

O conteúdo da comunidade está disponível sob CC-BY-SA salvo indicação em contrário.