Fazer um programa em C que peça dois caracteres ao usuário e os exiba.
Porém, há um problema ao se fazer isso, que e o que vai ser explicado nesse artigo de nossa apostila de C.
O problema de usar scanf, getchar, getc e fgetc para receber caracteres em C
"Ora, é só declarar duas variáveis char e usar a scanf duas vezes, uma para cada variável", é que você deve ter pensado para criar o tal programa.
Vamos fazer isso então, e ver o resultado:
#include <stdio.h> int main() { char letra1, letra2; printf("Insira um caractere: "); scanf("%c",&letra1); printf("Insira outro caractere: "); scanf("%c",&letra2); printf("Você digitou: '%c' e '%c'", letra1, letra2); }
Eu digitei 'C' (a melhor letra do alfabeto), dei enter, e antes de digitar a próxima letra o progarma terminou, exibindo a seguinte mensagem:
"Você digitou: 'C' e '
'"
Nossa! Estranho, não? Será que hackeamos a linguagem C e descobrimos uma falha?
Não ;)
Note que digitei 'C' e enter...mas enter também é uma tecla, e é representada por '\n', lembra?
Ou seja, o C entendeu que nossa segunda letra era o enter!
A solução para isso é bem simples.
Na função scanf, dê um espaço entre a aspa " e o símbolo %c.
Nosso código fica assim:
#include <stdio.h> int main() { char letra1, letra2; printf("Insira um caractere: "); scanf("%c",&letra1); printf("Insira outro caractere: "); scanf(" %c",&letra2); printf("Você digitou: '%c' e '%c'", letra1, letra2); }
Pronto! Agora funciona perfeitamente!
Pois esse simples espaço é um comando para o C desconsiderar o enter, tab ou espaço em branco.
Sim, precisa nem dar enter. Tente aí digitar uma letra, dar espaço (ou tab) e a outra.
Ok, mas só é possível fazer isso na scanf().
E na getchar(), getc() e fgetc()?
Limpando o buffer em C: fflush e __fpurge
Ainda no primeiro exemplo desse artigo ( o que dá problema ), digitamos a letra 'C', que é armazenada na variável 'letra1' e em seguida apertamos enter.
Esse caractere (enter), ficará armazenado no buffer do teclado (um memória temporária).
Em seguida, noss programa em C pede para que algo seja armazenado na variável 'letra2'.
Porém, antes do C receber um novo dado do usuário, ele checa se não tem mais alguma coisa armazenada no teclado (ele sempre faz isso...fez antes, para pegar a letra 'C'). E lá tem um caractere sim, o enter.
Então o programa pega esse caractere e o coloca na variável letra2, e é por isso que aparece uma quebra de linha em nosso programa.
Portanto, uma alternativa, caso não queria usar o espaço entre " e o %c na scanf, é limpar o buffer após cada scanf(), getchar(), getc() ou fgetc().
Para limpar o buffer em Windows, use: fflush(stdin)
Para limpar o buffer em Linux, use: __fpurge(stdin)
Veja como fica nosso programa original, funcionando do jeito que queríamos:
#include <stdio.h> int main() { char letra1, letra2; printf("Insira um caractere: "); scanf("%c", &letra1); fflush(stdin); __fpurge(stdin); printf("Insira outro caractere: "); scanf("%c", &letra2); printf("Você digitou: '%c' e '%c'", letra1, letra2); }
Fica ao seu dispor escolher como vai ser.
E se habitue com essas coisas, em C há várias maneiras de se fazer várias coisas. Muitas vezes, porém, a solução que usamos não é muito segura ou portável, mas é a mais simples.
Limpar o buffer, por exemplo, nem sempre é algo desejável, e para programação mais profissional e segura não é recomendado que se use fflush por exemplo.
Mas para quem está começando, não há problema algum ficar limpando o buffer após cada scanf, e o scanf (embora seja arriscado e não indicado em alguns casos) é o mais usado.
Por isso, usaremos bastante o scanf ao longo de nosso curso de C.
28 comentários:
Usar
getchar();
getchar();
}
no final dos programas, faz limpeza de buffer?
Não Vinicius, você entendeu errado!
Pra entender melhor, faça o teste usando as 3 funções uma após outra. Ao fazer isso, ao tentar ler o caractere na segunda função o programa vai simplesmente colocar o enter (\n) e já pula pra terceira.
A limpeza de buffer serve pra evitar este tipo de problema.
Logo após a leitura, usa o fflush (no windows) ou __fpurge (no linux) que resolve isso.
obs.: se for usuário linux, o fpurge é antecedido por 2 underline e não apenas 1.
T+
Oii.. Estou fazendo um programa muito simples para descobrir o numero que o computador "pensou" usando a função rand().. mas ele sempre "pensa" no numero 41.. neste caso o fflush() nao deu certo.. Como limpo o buffet neste caso??
e o comando setbuff(stdin,NULL);
mais recomendado ?
Olá!! Também pode resolver o problema simplesmente adicionando um espaço antes do %c. O código ficaria assim:
#include <stdio.h>
int main()
{
char letra1, letra2;
printf("Insira um caractere: ");
scanf(" %c",&letra1);
printf("Insira outro caractere: ");
scanf(" %c",&letra2);
printf("Você digitou: '%c' e '%c'", letra1, letra2);
}
Abraços.
No capítulo passado não se pediu pra usar a função scanf() e sim a função getc(stdin) então não tem como dar o espaço:
scanf(" %c",&letra2);
Com a função getc(stdin) eu achei outra solução:
int main(void)
{
char
letra1,
letra2;
printf("Insira um caractere: ");
letra1 = getc(stdin);
getchar(); //Esse getchar() sem atribuição lê o [Enter](que seria o \n) que antes era atribuido ao letra2
printf("Insira outro caractere: ");
letra2 = getc(stdin);
printf("Voce digitou: %c%c", letra1, letra2);
return 0;
}
Nas minhas aulas meu professor disse para usar esse fflush(stdin), mas eu nunca entendi o porquê! E agora, lendo essa explicação, tudo ficou claro e agora até saber explicar eu sei. Obrigado :)
Olá
Gostaria mais que se ensinasse a forma correta de proceder com esses comandos e não o atalho, mesmo simples. Pois a boca entorta com o uso do cachimbo.
obrigado.
Qual é a forma mais adequada de resolver o problema do buffer?
#include
int main()
{char letra1, letra2;
printf("Insira um caractere: " );
scanf("%c%c",&letra1,&letra2);
printf("Você digitou: '%c' e '%c' ", letra1, letra2);}
Esse é melhor!
#include
int main()
{char letra1, letra2;
printf("Insira um/dois caractere:");
scanf("%c %c",&letra1,&letra2);
printf("Você digitou:'%c' e '%c'", letra1, letra2);}
Olá...
Estou tendo dificuldade parecida com a primeira situação neste post.
#include
int main(){
char A[15], B[15], C[15], D[15], E[15];
int A1, B1, C1, D1, E1;
printf("\n\nDigite o nome do primeiro município:\n* ");
scanf("%15[^\n]", A);
printf("Temperatura média:\n* ");
scanf("%d", &A1);
printf("\n\nDigite o nome do segundo município:\n* ");
scanf("%15[^\n]", B);
printf("\nTemperatura média:\n* ");
scanf("%d", &B1);
Quando digito o primeiro nome e a temperatura, quando aperto enter ele já pula para segunda temperatura.
Eu coloquei o getchar(); depois da primeira temperatura e funcionou, mas não sei se é a coisa correta a fazer neste caso.
Comigo nenhum desses funcionou no Linux, então usei o comando setbuf(stdin, NULL); e resolvi. Acho que ele também funciona para Windows, pois setbuf parece ser um acrônimo para set buffer, ou seja, configurar o Buffer.
Anônimo que perguntou qual a maneira mais adequada de resolver o problema do Buffer, não existe. Simples assim. Você escolhe como vai fazer.
Deu certo para o que eu precisava.
Obrigado
Caramba, eu não estava conseguindo limpar o buffer.
Pensei que era _fpurge(stdin), com só uma underline, mas percebi agora que são duas __, demorei um pouco pra entender, só dava erro. haha
Valeu.
Excelente! Obrigada...
Quase sempre não comento, mas dessa vez ajudou bastante mesmo!
Vlw
No Linux, ao tentar compilar o programa, dá o seguinte erro:
winter@winter-desktop:~/C$ cc problemas_getc.c
problemas_getc.c: In function ‘main’:
problemas_getc.c:12:2: warning: implicit declaration of function ‘__fpurge’ [-Wimplicit-function-declaration]
__fpurge(stdin);
Para solucionar o problema, basta adicionar no cabeçalho do arquivo:
#include
E voilà! Funciona! :)
Fonte:
http://man7.org/linux/man-pages/man3/fpurge.3.html
Olá.
Estou com um "pequeno problema" se assim posso dizer
programo c no linux, e obviamente utilizando o compilador gcc,
toda vez que compilo o código onde utilizo o __fpurge dá um aviso de declaração implícita da função, porem funciona, só que me incomoda esse aviso, poderiam me dizer o porque? Ou não tem nenhum problema.
Show de bola \o/\o/\o/\o/\o/
Não é recomendado o uso de fflush(stdin), ele é usado para trabalhar com stdout.
Mais aconselhável para limpar buffer de entrar, na maioria dos caso e não todos, é o setbuf(stdin, NULL)
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1052863818&id=1043284351
Segundo o pessoal da softblue uma forma de limpar o buffer é criar um ponteiro de char no inicio do programa e cada vez que quizer limpar o buffer é só dar um scanf passando %c &c:
Exemplo:
int main()
{
char *c;
char letra1, letra2;
printf("Insira um caractere: ");
scanf("%c", &letra1);
// limpeza do buffer
scanf("%c",&c);
printf("Insira outro caractere: ");
// limpeza do buffer
scanf("%c", &letra2);
printf("Você digitou: '%c' e '%c'", letra1, letra2);
// é so colar "scanf("%c",&c);" para cada limpeza
scanf("%c",&c);
return 0;
}
scanf("%c",&c);
return 0;
}
Isso faz o terminal "segurar a tela" para leitura no final tb para quem usa visual express como eu.
Caso tenha alguem interessado em aprender c podemos criar um grupo de whats e aprender c juntos.
Tamy Caroline, sobre a função rand(), sei q a resposta está meio atrasada, mas o caso da função rand() sempre pensar, ao executar inicialmente um programa, o mesmo valor, se dá por causa da semente que se continua o mesmo. No caso, para o computador mudar a semente, é recomendado que vc utilize o tempo como semente:
#include "stdio.h"
#include "time.h"
#include "stdlib.h"
int main (){
srand(time(NULL)); //mudando a semente para o tempo do computador
//depois vc segue com a função rand normalmente e cada nova execução, ele gerará valores diferentes
[...]
}
O que o Fabio disse acima está correto. o comando fflush(stdin) não é recomendado para limpar o stdin.
Sugiro o uso do modo como ele fez p limpar o stdin e também deixo duas funções que são ótimas para limpar o stdin:
void limpa_linha() {
scanf("%*[^\n]");
scanf("%*c");
}
ou essa:
void fflush_stdin() {
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
}
Para usar essas funções, qualquer q seja, é só chamar ela depois de cada scanf e resolve o problema do stdin
para limpeza segura do buffer usem
while((c = getchar()) != '\n' && c != EOF){}; //sempre após scanf()
inicialize a variável
char c:
#include
#include
#include
#include
#include
#include
main (void)
{
setlocale(LC_ALL,"portuguese");
system ("color 3E");
char letra1, letra2;
printf("Insira um caractere: ");
letra1 = fgetc(stind);
fflush(stdin);
printf("Insira outro caractere: ");
letra2 = fgetc(stind);
printf("Você digitou: '%c' e '%c'", letra1, letra2);
}
Só não funcionou com o "fgetc(stind);"
Não entendi porque isso aconteceu. Fiquei a me perguntar se essa função pertence ao linux. utilizo o windows.
jean carlos conceição experimente "fgetc(stdin);" stind deve ser uma gralha.
Parabéns pelo criador desse curso. É muito bom mesmo, ensina coisas que nem na faculdade eu vi.
Postar um comentário