Ir ao conteúdo
  • Cadastre-se

C Problema com Do-While e buffer de teclado.


Posts recomendados

Vou colocar uma parte do programa, a parte que estou em duvida mas tem mais código pra cima e pra baixo do que vou mostrar.

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>



    char cont;

    do{

    printf("Digite o voto: ");
    scanf("%i",&voto);
    fflush(stdin);
    switch (voto){
        case 1:
            tDV.c[0]+=1;
            break;
        case 2:
            tDV.c[1]+=1;
            break;
        case 3:
            tDV.c[2]+=1;
            break;
        case 4:
            tDV.c[3]+=1;
            break;
        case -1:
            tDV.nulos+=1;
            break;
        case 0:
            tDV.brancos+=1;
            break;
        default:
            printf("Escolha invalida!\nTente novamente!\n");
            goto tentenovamente;
    }
    
        i++;
        printf("Quer continuar? [S/N]");
        //scanf(" %c",&cont);
       // printf("\n%%c: %c\n",cont);
        getchar();
        cont=getchar();
        //printf("\n%%c: %c\n",cont);
    } while (cont=='S');

 

 

 

O que acontece é que eu não consigo fazer esse do-while funcionar, pelo o que eu pesquisei é um problema relacionado ao buffer de teclado que fica logo apos os comandos de leitura(ex: scanf, getchar() ), alias, coloquei o ffush(stdin) porque dizem que limpa o buffer, mas não deu certo mesmo assim. Quando chega la no getchar, ele le a variavel cont e imediatamente finaliza o programa em vez de continuar executando o longo codigo que tem abaixo.

 

obs: Não reparem nos comentarios dentro do codigo, são testes que fui fazendo com o programa.

 

 

Código completo:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


struct tiposDeVoto{
    int nulos;
    int brancos;
    int c[4];
}tDV={0,0,{0,0,0,0}};

struct porcVotos{
    float nulos;
    float brancos;
    float c[4];
}pV={0.0,0.0,{0.0,0.0,0.0,0.0}};

int main(){
    /*Em uma eleição para governador concorrem 4 candidatos (1, 2, 3 e 4). No dia da eleição cada
     um dos N eleitores votaram:
• 1, 2, 3 ou 4 para cada candidato.
• 0 (zero) para voto em branco.
• -1 para voto nulo.
Considere que:
• O candidato ganha a eleição se fizer 51% ou mais do total de votos.
• Se não houver ganhador, os dois melhores irão para o segundo turno.
Faça um programa em C que calcule e imprima:
• O candidato vencedor (se houver), seguido da porcentagem de votos obtida. Se não houver vencedor,
 imprima os candidatos que irão ao segundo turno com a respectiva porcentagem de votos obtida.
• A porcentagem obtida pelos demais candidatos.
• A porcentagem de votos em branco e nulos.*/
    tentenovamente:
    printf("----------------------------\n");
    printf("         Urna eleitoral       ");
    printf("\n 1- Tiago\n 2- Pedro\n 3- Alvaro\n 4- Chaves\n 0- Voto em branco\n -1- Voto nulo\n");
    printf("------------------------------\n");

    
    int voto=0,i=0;
    char cont;

    do{

    printf("Digite o voto: ");
    scanf("%i",&voto);
    fflush(stdin);
    switch (voto){
        case 1:
            tDV.c[0]+=1;
            break;
        case 2:
            tDV.c[1]+=1;
            break;
        case 3:
            tDV.c[2]+=1;
            break;
        case 4:
            tDV.c[3]+=1;
            break;
        case -1:
            tDV.nulos+=1;
            break;
        case 0:
            tDV.brancos+=1;
            break;
        default:
            printf("Escolha invalida!\nTente novamente!\n");
            goto tentenovamente;
    }
    
        i++;
        printf("Quer continuar? [S/N]");
        //scanf(" %c",&cont);
       // printf("\n%%c: %c\n",cont);
        getchar();
        cont=getchar();
        //printf("\n%%c: %c\n",cont);
    } while (cont=='S');

    int totalDeVotos=i+1;
    pV.brancos=tDV.brancos/totalDeVotos;
    pV.nulos=tDV.nulos/totalDeVotos;
    for (int k=0;k<4;k++)
        pV.c[k]=(float)tDV.c[k]/totalDeVotos;
        int vencedor=0;

    if(pV.c[0]>0.51 && pV.c[0]>pV.c[1] && pV.c[0]>pV.c[2] && pV.c[0]>pV.c[3]){
        vencedor=1;
        printf("Tiago e o vencedor da eleicao com %0.2f %% dos votos",(pV.c[0]*100));
    }
    if(pV.c[1]>0.51 && pV.c[1]>pV.c[0] && pV.c[1]>pV.c[2] && pV.c[1]>pV.c[3]){
        vencedor=1;
        printf("Pedro e o vencedor da eleicao com %0.2f %% dos votos",(pV.c[1]*100));
    }
    if(pV.c[2]>0.51 && pV.c[2]>pV.c[0] && pV.c[2]>pV.c[1] && pV.c[2]>pV.c[3]){
        vencedor=1;
        printf("Alvaro e o vencedor da eleicao com %0.2f %% dos votos",(pV.c[2]*100));
    }
    if(pV.c[3]>0.51 && pV.c[3]>pV.c[0] && pV.c[3]>pV.c[2] && pV.c[3]>pV.c[1]){
        vencedor=1;
        printf("Chaves e o vencedor da eleicao com %0.2f %% dos votos",(pV.c[3]*100));
    }
    


    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

Postei uns programas e uma discussão ontem sobre isso. Pode te ajudar a entender o que acontece porque tem exemplos com os códigos lidos. O link está no fim do texto

 

Note que:

  • scanf() retorna um valor: USE. É o número de ítens lidos.
  • se vai ler strings com espaços, fgets() é o mais prático
  • Se vai usar scanf() LEIA o manual ou ao menos a tabela de especificadores como a que está em https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htm. Ao menos se acostume com 

    A declaração
    int scanf(const char *format, ...)

    E veja o que retorna, esse int. 

    E o formato geral da máscara

     [=%[*][tamanho][modificadores]tipo]
  • fflush(stdin) não funciona. A Microsoft parece ter contrariado os padrões e implementado algo, mas o oficial é que fflush() só existe para buffers de saída.
     
  • Uma maneira bem ingênua de escrever fflush() e que funciona é simplesmente ler até encontar o fim de arquivo ou um '\n' o tal newline:
    void    flush()
    {   int ch = 0;
        do { ch = getc(stdin); } while ((ch != '\n') && (ch != EOF));
    };	// flush()
    Pode usar algo assim em seu programa depois de ler algo com ftegc(), getc(), scanf() sei lá... Pode até declarar um parâmetro FILE* para poder escrever como todo mundo faz e saber que funciona mesmo no Mac ou no Linux:
    void    flush(FILE* f)
    {
        int ch = 0;
        do { ch = getc(f); } while ((ch != '\n') && (ch != EOF));
    };	// flush()
    Assim você pode escrever fflush(stdin) e vai funcionar, mesmo quando a entrada padrão estiver redireciona. Isso quer dizer quando estiver lendo de um arquivo como
             type entrada.txt > programa.exe
    para seu programa programa.exe ler de entrada.txt ao invés de ler do teclado...
     


Veja os programas em 

 

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@arfneto Em especifico o meu programa a parte do do while nao tava dando por que? 

adicionado 0 minutos depois

@herbertbahia Então, essa biblioteca <conio.h> nao funciona, pesquisei na net e vi falando que ela nao é nativa da linguagem C. E tambem nao achei como importar bibliotecas, se é que isso é possivel...

Link para o comentário
Compartilhar em outros sites

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
	
    printf("----------------------------\n");
    printf("         Urna eleitoral       ");
    printf("\n 1- Tiago\n 2- Pedro\n 3- Alvaro\n 4- Chaves\n 0- Voto em branco\n -1- Voto nulo\n");
    printf("------------------------------\n");
    int i=0;
    char cont;
    do{
    printf("Digite o voto: ");
    scanf ("%d",&i);
    switch (i){
        case 1:
             printf("\nvotou Tiago");
            break;
        case 2:
        	printf("\nvotou Pedro");
            break;
        case 3:
        	printf("\nvotou Alvaro");
            break;
        case 4:
        	printf("\nvotoo Chaves");
            break;
        case -1:
        	printf("\nvotou nulo");
            break;
        case 0:
        	printf("\nvotou branco");
            break;
        default:
            printf("\nEscolha invalida!\nTente novamente!\n");
            break;
    }

    printf("\nQuer continuar? [S/N]");
    scanf(" %c",&cont);
    } while (cont=='S'||cont=='s');

printf ("voce nao continuou");
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

30 minutos atrás, JaoProgramador disse:

Achei essa funcao do flush mt complexa, acho que nao consigo entender isso ainda... Preciso de mais base...@arfneto

 

void    flush(FILE* f)
{
    int ch = 0;
    do { ch = getc(f); } while ((ch != '\n') && (ch != EOF));
};	// flush()

Você leu mesmo o que eu escrevi? Viu o programa exemplo de ontem com scanf() getchar() fgets() e o resto que expliquei?

 

Sobre a versão de flush()

 

Basta você acreditar que flush()  funciona e colocar esse código no seu programa, antes de main(). É só uma função... Troque o fflush(stdin) por flush(stdin) e pronto.

 

A função tem apenas 5 linhas. Se achou complexa podia ter perguntado algo objeitivo eu acho.

 

Essa "função" apenas chama getc() para ler uma letra, em loop while, até ler o newline ou o fim de arquivo. O que achou complexo? podia ter explicado sua dúvida...

 

Comentando 3 das 5 linhas: 


void    flush(FILE* f)
{
    int ch = 0; // a letra
    do
    { 
        ch = getc(f); // le a letra
    } while ((ch != '\n') && (ch != EOF)); // ate o fim da linha
};	// flush()

E é só isso: ler até o fim da linha

 

28 minutos atrás, herbertbahia disse:

para usar getch use a bilbioteca  #include <conio.h>

 

conio é uma biblioteca dos anos 80 derivada do compilador de uma empresa chamada Borland daquela época, e que vinha em dois disquetes. Eu comprei.

Não entendo o que tem lá que pode mesmo ser útil em 2020. Por certo não seria getch(). Ou perdi algo?

 

29 minutos atrás, JaoProgramador disse:

Em especifico o meu programa a parte do do while nao tava dando por que

 

Você leu o programa que mostrei ontem? 

Entendeu as notas que te escrevi hoje?

 

scanf() retorna um parâmetro. USE. scanf() consome a entrada só até satisfazer o que tentou ler. E as vezes é mais ou menos do que você imaginava. Essa rotina não foi escrita para isso. Mas serve.


Se quer ler uma letra para o voto leia com getc() que retorna exatamente a letra e depois use flush() para descartar o resto da linha. Se o cara teclar em seu programa algo como "coisa" e ENTER por exemplo vai pular a mensagem de escolha inválida... Faça o simples, minha sugestão. E leia aquilo que falei sobre scanf() é só uma folha. 

 

E me diga o que não entendeu na função de 5 linhas que te mostrei para que eu possa tentar te explicar. Sua dúvida pode ser a de outros.

adicionado 2 minutos depois
35 minutos atrás, JaoProgramador disse:

E tambem nao achei como importar bibliotecas, se é que isso é possivel...

 

importar o código executável de uma biblioteca você precisa conseguir de algum lugar a versão já compilada para sua plataforma, algo como um arquivo .DLL ou .OBJ ou .lib pro seu sistema.

 

ou conseguir o código fonte, o programa na linguagem em que foi escrito e compilar em seu sistema. E salvar o arquivo .lib ou DLL gerado porque você não vai ficar compilando isso para o resto da vida certo?

 

O que precisa de conio, dos anos 80, em 2020?

adicionado 42 minutos depois


fflush(stdin) e um pouco de história


Acho que eu ou alguém devia escrever isso afinal parece que não faz parte das aulas ou nos livros mais...
 

Desde os programas em linguagem FORTRAN do final dos '50 os programas acessavam arquivos por números. Sim, existiam programas em 1958 por exemplo! E alguns desses números eram pré-definidos e apontavam para certas coisas.


No final dos 70 a linguagem C fazia a mesma coisa. E ainda faz. 
 

Um programa em C tem acesso SEMPRE a 3 arquivos --- streams ou fluxos é o nome hoje em dia ---  e eles tem um número cada um. No Unix, no Windows, todo lugar.


E um nome. Os arquivos são 0, 1 e 2 e os nomes são stdin, stdout e stderr. Então quando você fala em limpar o buffer de entrada está falando de stdin, de 0. 

    getc(stdin) é a mesma coisa que getc(0)


flush() foi criado para limpar o buffer de um arquivo desse tipo, mas um arquivo de saída.

Porque isso? Há muitas razões. Vou deixar 2 exemplos:

  • se você tem um programa rodando funções em paralelo escrevendo coisas num mesmo lugar, como vários printf(), você pode precisar de fflush(stdout) para garantir que imprima o que você quer de imediato para diminuir a chance de misturar com a saída de outra função.
  • Se você tem um periférico tipo um painel LCD e tem uma lógica que escreve nele, pode usar fflush() para forçar a descarregar o buffer e mostrar o que já está lá para ser impresso.

O que acontece é que os sistemas usam áreas intermediárias de armazenamento --- os tais buffers -- e tem uma lógica deles para descarregar os dados. Isso por questão de pura eficiência.
 

É a mesma coisa na entrada: o sistema imagina que alguém vai ler tudo que está lá no buffer de teclado. Isso inclui espaço, ENTER e o que tiver. E como tem rotinas lendo elas podem pegar o troco do que sobrou de outras e não foi consumido ainda, como o ENTER de uma leitura de teclado, que em C é um arquivo como outro qualquer.
 

Sobre fflush(stdin) veja uma discussão em https://www.geeksforgeeks.org/use-fflushstdin-c/ onde alguém até cita o parágrafo do padrão onde diz que fflush() para entrada tem comportamento indefinido

C-stdin-undef.png.9bfc84d2739406bd95a6d2ba4cd60595.png

 

E uns exemplos em C e C++ em
 

https://www.geeksforgeeks.org/clearing-the-input-buffer-in-cc/

 

 

Link para o comentário
Compartilhar em outros sites

@JaoProgramador A forma como você estruturou seu programa está um pouco complexa. Eu partiria de algo assim:

typedef struct candidato {
    int numero;
    char nome[50];
    int voto;
} Candidato;

void cadastrar(Candidato *candidatos, int quantidade);

void exibirResultado(Candidato *candidatos, int quantidade, Candidato *vencedor);

Candidato *getVencedor(Candidato *candidatos, int quantidade);

void sequenciaVotacao(Candidato *candidatos, int quantidade);

int main() {
    const int quantidade = 6;

    Candidato *candidatos = malloc(quantidade * sizeof(Candidato));
    Candidato *vencedor = &candidatos[0];

    cadastrar(candidatos, quantidade);
    sequenciaVotacao(candidatos, quantidade);

    vencedor = getVencedor(candidatos, quantidade);
    exibirResultado(candidatos, quantidade, vencedor);

    return EXIT_SUCCESS;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@arfneto Muito obrigado pela sua vontade de ajudar. você é 10. Você não tem ideia de como esse assunto de buffer de entrada e saida me pegou de surpresa, porque imagina só, se poe no meu lugar: Eu tava criando esse codigo que eu citei, e tava estudando sobre ponteiro para incrementar esse programa, e DE REPENTE, a variavel nao consegue ser lida. O negocio foi estão inesperado, que pra eu saber o que PERGUNTAR no forum demorou 2 dias, literalmente. Eu nao tinha palavras pra isso. Porque na minha cabeça, nao existia isso de dar erro na hora de ler, era como se essas funções nativas, fossem perfeitas. Entao pra mim ta sendo difícil entender isso tudo, eu leio o que você me fala, leio umas paginas do assunto, mas parece que ainda tem uma neblina que me impede de entender. Vou continuar tentando entender isso.

adicionado 0 minutos depois

@AdrianoSiqueira Aqui pra mim apareceu só as funções prototipadas, nao apareceu o codigo da funcao...

adicionado 4 minutos depois

@arfneto Outra coisa... Eu sinto uma falta de um material de aprendizado, como apostila, ou um curso em video, tanto faz a plataforma... Sinto uma falta de um material de aprendizado completo, detalhista, sabe? Porque as videos aulas que vejo no youtube sao mt superficiais. Se tiver algum livro ou um site que você acha mt bom pra aprender me passa por favor.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

1 hora atrás, JaoProgramador disse:

Porque na minha cabeça, nao existia isso de dar erro na hora de ler, era como se essas funções nativas, fossem perfeitas

 

Elas são perfeitas, ou quase isso. Acontece que você não está usando de acordo. Como eu disse, scanf() por exemplo sequer foi escrita para isso e você estava lendo do jeito errado. 

 

Você leu os exemplos que eu mostrei? lá tem até o código do programa que dá erro e depois dá certo e a discussão passp a passo.

 

Se você não entendeu poste a linha do que você não entendeu, algo objetivo. Assim será mais produtivo para você.

 

O livro clássico de C é sempre o "livro branco" de Kernighan e Ritchie. https://www.amazon.com.br/Programming-Language-Brian-W-Kernighan/dp/0131103628 Online eu acho que o material em https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htmé muito bom. Tem um erro aqui ou ali, mas cobre tudo e com exemplos...

 

Sua escola não assina uma biblioteca online? É muito comum hoje em dia. 

 

1 hora atrás, JaoProgramador disse:

mas parece que ainda tem uma neblina que me impede de entender. Vou continuar tentando entender isso

 

Pergunte algo objetivo. Algo assim nebuloso. Vamos ver se dá pra ajudar.

 

Entendeu o que eu expliquei sobre flush()? Todas as linhas?

Link para o comentário
Compartilhar em outros sites

Outras versões da função flush:

void flush(){
    /*Descarta todos os caracteres se houver algum até 
      encontrar o caractare nova linha ´\n´, então só
      sobra o ´\n´ na entrada: */
    scanf("%*[^\n]"); 
    /*E então descarta o caractere nova linha ´\n´:*/
    scanf("%*c");  
}

Ou essa (basicamente igual a do @arfneto ) :

void flush(){
    int c;
    /*Lê todos os caracteres até encontrar '\n' ou EOF:*/
    while( (c = getchar()) != '\n' && c != EOF );
}

 

E essa é a minha recomendação para documentação online sobre scanf:

https://en.cppreference.com/w/c/io/fscanf

 

Link para o comentário
Compartilhar em outros sites

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

	struct tiposDeVoto{
    	int tiago=0;
    	int pedro=0;
    	int alvaro=0;
    	int chaves=0;
    	int nulos=0;
    	int brancos=0;
    };

int main(){
	
	struct tiposDeVoto tipo, *p;
	p = &tipo;
	int i=0;
	char cont;
	
	printf("----------------------------\n");
    printf("         Urna eleitoral       ");
    printf("\n 1 - Tiago\n 2 - Pedro\n 3 - Alvaro\n 4 - Chaves\n 0 - Voto em branco\n -1- Voto nulo\n");
    printf("------------------------------\n");
    
    do{
    printf("Digite o voto: ");
    scanf ("%d",&i);
    switch (i){
        case 1:
             printf("\nvotou Tiago");
             p->tiago+=1;
            break;
        case 2:
        	printf("\nvotou Pedro");
        	p->pedro+=1;
            break;
        case 3:
        	printf("\nvotou Alvaro");
        	p->alvaro+=1;
            break;
        case 4:
        	printf("\nvotoo Chaves");
        	p->chaves+=1;
            break;
        case -1:
        	printf("\nvotou nulo");
        	p->nulos+=1;
            break;
        case 0:
        	printf("\nvotou branco");
        	p->brancos+=1;
            break;
        default:
            printf("\nEscolha invalida!\nTente novamente!\n");
            break;
    }
    printf("\nQuer continuar? [S/N]");
    scanf(" %c",&cont);
    } while (cont=='S'||cont=='s');
	float total = (p->tiago+p->pedro+p->alvaro+p->chaves+p->nulos+p->brancos);
	float maior1,maior2;
	float ppedro,ptiago,palvaro,pchaves,pnulos,pbrancos;
	char primeiro[20],segundo[20];
	 ppedro = (p->pedro*100)/total;
	if (ppedro>=51)
		printf("\nPedro Ganhou com %.2f%%",ppedro);
		
	 ptiago = (p->tiago*100)/total;
	if (ptiago>=51)
		printf("\nTiago Ganhou com %.2f%%",ptiago);
		
	 palvaro = (p->alvaro*100)/total;
	if (palvaro>=51)
		printf("\nAlvaro Ganhou com %.2f%%",palvaro);
		
	 pchaves = (p->chaves*100)/total;
	if (pchaves>=51)
		printf("\nChaves Ganhou com %.2f%%",pchaves);
		
	 pnulos = (p->nulos*100)/total;
	if (pnulos>=51)
		printf("\nQuem diria %.2f%% de votos nulos",pnulos);
	 pbrancos = (p->brancos*100)/total;
	if (pbrancos>=51)
		printf("\nQuem diria %.2f%% de votos brancos",pbrancos);
		printf("\nResultado da Eleicao: \n");
		printf("\nporcentagem pedro: %.2f%%",ppedro);
		printf("\nporcentagem tiago: %.2f%%",ptiago);
		printf("\nporcentagem alvaro: %.2f%%",palvaro);
		printf("\nporcentagem chaves: %.2f%%",pchaves);
		printf("\nporcentagem nulos: %.2f%%",pnulos);
		printf("\nporcentagem brancos: %.2f%%",pbrancos);
		
	if(ppedro>maior1&&ppedro!=0){
			strcpy(primeiro,"pedro");
			maior1 = ppedro;
		}
		if(ppedro<maior1&&ppedro>maior2&&ppedro!=0){
			strcpy(segundo,"pedro");
			maior2 = ppedro;
		}
		if(ptiago>maior1&&ptiago!=0){
			strcpy(primeiro,"tiago");
			maior1 = ptiago;
		}
		if(ptiago<maior1&&ptiago>maior2&&ptiago!=0){
			strcpy(segundo,"tiago");
			maior2 = ptiago;
		}
		if(palvaro>maior1&&palvaro!=0){
			strcpy(primeiro,"alvaro");
			maior1 = palvaro;
		}
		if(palvaro<maior1&&palvaro>maior2&&palvaro!=0){
			strcpy(segundo,"alvaro");
			maior2 = palvaro;
		}
		if(pchaves>maior1&&pchaves!=0){
			strcpy(primeiro,"chaves");
			maior1 = pchaves;
		}
		if(pchaves<maior1&&pchaves>maior2&&pchaves!=0){
			strcpy(segundo,"chaves");
			maior2 = pchaves;
		}
		if(ppedro<51&&ptiago<51&&palvaro<51&&pchaves<51)
printf("\n\nVamos ter Segundo Turno Entre %s %.2f%% e %s %.2f%% !",primeiro,maior1,segundo,maior2);
	
	

}

 

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!