Ir ao conteúdo
  • Cadastre-se

C A condição do if está sendo ignorada


GesséFerreira

Posts recomendados

Boa tarde!

 

Estou a algum tempo tentando polir esse código. No caso em questão, preciso que o programa receba como entrada o código e o valor dos produtos. O problema é que eu criei uma condição para que o programa informe se o código foi digitado incorretamente, porém, independente da entrada, a condição é ignorada e o printf sempre é executado. Outro problema é a repetição da mensagem inicial (anexo na imagem). Não estou conseguindo identificar o que causa isso e minhas tentativas de corrigir não funcionaram, e agora está parecendo uma gambiarra. Obs: tenho que usar obrigatoriamente o do while. Obrigado.

#include <stdio.h>

int main(){
    float valor = 0;
    float dinheiro = 0;
    float cheque = 0;
    float total = 0;
    char cod = ' ';
    int cont = 1;

    printf("MENU \n");
    printf("Codigo D = Compras em dinheiro. \n");
    printf("Codigo C = Compras em cheque. \n");
    printf("Codigo S = Sair \n\n");

    do{
        printf("Codigo: ");
        scanf("%c", &cod);
        if(cod == 's' || cod == 'S'){
            total = dinheiro + cheque;
            printf("Total de compras em Dinheiro: %.2f\n", dinheiro);
            printf("Total de compras em Cheque: %.2f\n", cheque);
            printf("Total de compras: %.2f\n\n", total);

            return 0;

        }else if(cod == 'd' || cod == 'D'){
            printf("Valor: ");
            scanf("%f", &valor);
            dinheiro = dinheiro + valor;
            cod = ' ';
        }else if(cod == 'c' || cod == 'C'){
            printf("Valor: ");
            scanf("%f", &valor);
            cheque = cheque + valor;
            cod = ' ';
        }else if(cod != 'd' && cod != 'D' && cod != 'c' && cod != 'C' && cod != ' '){
            printf("Codigo ou valor invalido, digite novamente.\n");
            cod = ' ';
        }

    }while(1);


return 0;
}

 

executavel.jpg

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

@GesséFerreira    o comando if está sim funcionando bem ,  mas o que acontece é que como muda o tipo pego pelo scanf , na próxima leitura o scanf não lê nada e passa direto para mostrar que a variável cod está com um valor desconhecido , então muitos  dizem que o comando fflush não deve ser usado para limpar o buffer de entrada do teclado , mas aqui no codeblocks está funcionando e serve para resolver esse caso , e então seu código com algumas modificações poderia ser assim  :

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(){
    float valor = 0,dinheiro = 0;
    float cheque = 0,total = 0;
    char cod;
    int cont = 1;
    do{
        system("cls");
        printf("        MENU De Ofertas\n");
        printf("Codigo D = Compras em dinheiro. \n");
        printf("Codigo C = Compras em cheque. \n");
        printf("Codigo S = Sair \n\n");
        printf("Codigo: ");
        fflush(stdin);
        scanf("%c", &cod);
        if(toupper( cod ) == 'S' ){
            total = dinheiro + cheque;
            printf("Total de compras em Dinheiro: %.2f\n", dinheiro);
            printf("Total de compras em Cheque: %.2f\n", cheque);
            printf("Total de compras: %.2f\n\n", total);
            break;
        }
        else{
            if(toupper( cod ) == 'D' ){
                printf("Valor: ");
                fflush(stdin);
                scanf("%f", &valor);
                dinheiro = dinheiro + valor;
            }
            else{
                if(toupper( cod ) == 'C' ){
                    printf("Valor: ");
                    fflush(stdin);
                    scanf("%f", &valor);
                    cheque = cheque + valor;

                }
                else{
                    if(toupper( cod ) != 'D' && toupper( cod ) != 'C' ){
                        printf("Codigo -> %c , ou valor invalido, digite novamente.\n",cod);
                    }
                }
            }
        }
    }while(1);
    printf("    Esperai !   ");
    int w,j,i;
    for( w=50; w>=0; w--)
    {
      for( i=0; i<3000; i++ )
        for( j=0; j<40000; j++ );
      printf("  %2d\b\b\b\b",w);
    }
    printf("\n\n\n");
    return 32768;
}

 

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

Não entendi seu programa.

 

  • Está ao final no último else testando de novo os possíveis valores de cod que já testou antes. Para que?
  • E porque todos esses else? só fica mais difícil de ler. Cada opção é definitiva: vai tratar a opção e sair ou continuar no loop lendo o próximo valor de cod. São dois casos e dois comandos: return para sair e continue para ler o próximo cod. Porque usou só o return e deixou esses else todos?
  • Porque não mostra o valor de cod que leu, a toda vez? Enquanto está testando é bom se acostumar a fazer isso.
  • Porque quando o código está em branco tem um tratamento especial, que é só deixar de mostrar a mensagem?

Depois de ler com scanf() você precisa consumir o que quer que seja que o cara digitou e que possa não ter sido usado. scanf() é para ler entrada formatada. Teclado não é assim: o usuário tem uma certa liberdade...

Use um simples loop e consuma o que quer que tiver lá.

Entenda que ao digitar o valor ao tratar cod D por exemplo o usuário pode escrever
"120.00 todo o dinheiro que eu tinha! "
e só depois teclar ENTER. E isso vai claro atrapalhar um pouco a sua lógica :) Depois de ler o que queria leia o resto.

E Entenda que scanf() pode não ler nada. Por isso ela retorna um int dizendo quantos valores leu. Só que você não está testando e aí nunca vai saber. SEMPRE teste o retorno de scanf()

 

 

 

.

adicionado 7 minutos depois
4 minutos atrás, devair1010 disse:

então muitos  dizem que o comando fflush não deve ser usado para limpar o buffer de entrada do teclado , mas aqui no codeblocks está funcionando...

 

É, não deve. fflush() não está definido para arquivos de entrada. Code::Blocks não tem efeito sobre isso. Seu compilador é que está fazendo isso --- flush() numa situação que contraria a documentação --- porque no Windows a Microsoft adotou esse comportamento e está programado assim no código de fflush() na biblioteca padrão.

 

Você pode apenas ler o que está lá. Entenda que o usuário pode ter teclado mais coisas, mas no mínimo tem um ENTER, então um simples fgets() funcionaria em Windows E Linux e outras plataformas.

 

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

 

18 horas atrás, devair1010 disse:

então muitos  dizem que o comando fflush não deve ser usado para limpar o buffer de entrada do teclado , mas aqui no codeblocks está funcionando ...

 

Usar fflush ainda não é o problema, o problema é o que nos leva a usar fflush. Eu diria, simplesmente escreva programas em C; 'A portabilidade é um objetivo ilusório'.

"

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

@devair1010 Se você estiver em uma entrevista de emprego ou com seu orientador na universidade e o entrevistador pedir para você falar sobre fflush() e buffers e streams em C no Windows você pode dizer:

  • (a) A gente precisa precisa apagar o lixo do teclado então tem que dar fflush() para limpar o buffer!. Todo mundo sabe isso! E funciona no Code::Blocks!
     
  • (b) fflush() não está definida para fluxos de entrada, mas a Microsoft implementou essa extensão que funciona apenas, claro, no Windows.
     
    • no Windows você pode chamar FlushConsoleInputBuffer() que com esse nome já se imagina o que faz
       
    • Por outro lado uma simples chamada a fgets( , ,stdin ) vai consumir os dados que eventualmente não foram consumidos por scanf()
       
    • scanf() nunca deveria ser usada para entrada de dados via teclado. Basta ver o nome. O propósito dela é scan formatted input --- ler entrada formatada --- e o teclado não é nada formatado: o usuário tem dezenas de teclas e grande liberdade
       
    • se é preciso controlar perfeitamente a entrada, sem permitir que o cursor saia pela tecla afora por exemplo, é melhor separar o teclado da tela, como nos anos 80. Ler sem eco e só mostrar na tela e mover o cursor se for algo válido. Ou ao menos ler a linha toda usando fgets() ou letra a letra usando fgetc()
       
    • O que venha a ter no buffer do teclado não é lixo. Não se sabe o que foi parar lá e pode ter outra rotina no mesmo programa que vai consumir o que scanf() não leu. Não se pode imaginar que isso seja um problema de scanf() ou que uma função de biblioteca, e que foi escrita para outra coisa, tenha capacidade de identificar o que os valores digitados representam para o programa: será um gato andando sobre o teclado ou o cara digitou aquilo de propósito? 🤔

Conheça as ferramentas que usa e boa sorte nas entrevistas se por acaso passar por alguma. 

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

@devair1010  

 

fflush foi definida para fluxos de entrada também no linux, segundo manual: https://man7.org/linux/man-pages/man3/fflush.3.html não é para uso em terminais, o que bem mais específico.

 

Procurei aqui no fórum e em outros lugares, postagens sobre o tema, inclui as recentes também.

Selecionei aquela que melhor contribui sobre o assunto, não há igual.

 

Standard C and POSIX leave fflush(stdin) as undefined behaviour

https://stackoverflow.com/questions/2979209/using-fflushstdin#:~:text=ostream points to an output,"how bad" this is.

 

 
Citação

 

Resumo

 

A Microsoft documenta o comportamento de fflush(stdin). Aparentemente, funciona conforme documentado na plataforma Windows, usando o compilador nativo do Windows e bibliotecas de suporte de tempo de execução C.

 

Apesar da documentação em contrário, ele não funciona no Linux quando a entrada padrão é um terminal, mas parece seguir a especificação POSIX, que é formulada com muito mais cuidado. De acordo com o padrão C, o comportamento de fflush(stdin) é indefinido. POSIX adiciona o qualificador 'a menos que o arquivo de entrada seja pesquisável', o que um terminal não é. O comportamento não é igual ao da Microsoft.

 

Conseqüentemente, o código portátil não usa fflush(stdin). O código que está vinculado à plataforma da Microsoft pode usá-lo e funcionará.

 

 

Vale conferir na integra.

" o que nos leva a usar fflush" deixa de ser um mistério, mesmo porque nunca foi. 

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

1 hora atrás, mauro_b disse:

 o que nos leva a usar fflush" deixa de ser um mistério, mesmo porque nunca foi. 

 

Não há mistério. Só não há razão para usar em fluxos de entrada. Isso quando faz sentido porque tem casos que mesmo com  flush atuando dados já passaram para outras camadas do sistema e é tarde demais.

 

Cenários comuns onde se usa flush() no mundo real:

  • buffers de comunicação, que me geral tem uma capacidade fixa, como os 1500 bytes do TCP/IP na internet e na rede local. Quando você quer transmitir e não tem ainda o tamanho total o que você faz? flush() e ele é transmitido na mesma hora.
     
  • dispositivos como impressoras especiais, plotters, em que só pode ser preciso num dado momento imprimir uma parte e voltar para a origem. Hora do flush()
     
  • painéis LCD em que a linha tem um número fixo de letras e você sabe que não vai usar a linha toda ou está fazendo uma animação por exemplo, para simular movimento. O painel espera completar a linha e imprime automaticamente. Quer imprimir antes? uma letra só talvez? flush()
     
  • Na entrada não é seguro e se fosse estaria previsto desde sempre em toda implementação de stdio. E há tantas outras maneiras que nunca se sentiu falta. Ganhou uso em escolas e por preguiça apenas, provavelmente. A mesma preguiça que difundiu o uso de scanf() para leitura, mesmo entre alunos que ainda não sabem o que são ponteiros e endereços mas tem que aprender que em alguns casos tem que colocar um & na frente da variável e em outros não, ao invés de ler a linha e usar atoi(), atof() e outras para converter os argumentos de string para o tipo desejado. E nem entendem que o operador & extrai o endereço e que scanf() precisa disso porque não aloca memória

 

 

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

 

1 hora atrás, arfneto disse:

Não há mistério. Só não há razão para usar em fluxos de entrada.

 

Um assunto com + 10 anos, eu não defendo razões e nem motivos que te impeça de usar fflush, principalmente quando funciona para ti.

 
 
1 hora atrás, arfneto disse:

Na entrada não é seguro e se fosse estaria previsto desde sempre em toda implementação de stdio

 

É caso de se demostrar os possíveis erros que fflush vem causando na entrada padrão,

afinal esse é o cenário que se tem aqui, outros considerados ideias ficam para mais tarde, porque ao que me parece essa não é a questão.

 

Vaje bem se no windows funciona fora do Padrão C, mesmo com alegações de um uso irregular.

 

O ponto é uma questão de causa e efeito, eu acredito que essa foi a posição que conduziu essa discussão a princípio.

Já portabilidade, sabemos que não pesa muito na questão.

 

 

 

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

3 horas atrás, mauro_b disse:

Um assunto com + 10 anos, eu não defendo razões e nem motivos que te impeça de usar fflush, principalmente quando funciona para ti.

 

Tentei dizer que não adiante aponta motivos contra ffush(stdin). Uma discussão histórica que se repete há uma década, acaba retomando para o ambiente Windows na mesma proporção que tem uma correção gramatical, ou seja, é gramaticalmente incorreto se usar a norma tal, --- não há problema porque funciona, ---Porém não é seguro porque algo desconhecido faz anos vai acontecer só com você e tem mais, existe formas melhores de se fazer o mesmo, por último alguém sempre vai corrigi-lo.

 

 

Brincando um pouquinho

Chefe do Departamento: Fala sobre fflush(sdin) e scanf no Windows :

Eu: o motivo para não usar ffush(stdin) depois de scanf numa programação para windows é evitar aquela velha discussão de 10 anos

Eu:🤷‍♀️

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

9 horas atrás, mauro_b disse:

Brincando um pouquinho

Chefe do Departamento: Fala sobre fflush(sdin) e scanf no Windows :

Eu: o motivo para não usar ffush(stdin) depois de scanf numa programação para windows é evitar aquela velha discussão de 10 anos

 

Brincando mais um pouco

 

  • Se você tem um chefe de departamento é porque tem um emprego já e ainda. E talvez seu chefe não se importe, já que você ainda tem um emprego
     
  • Você então não é o chefe de departamento. E se você  é seu diretor pode ser um desses fanáticos que não aceita justificativas como essa
    --- não há problema porque funciona, ---

    e nem o vice-presidente. E você vai ter dificuldade em ser promovido
     
  • Seu próximo emprego pode esbarrar numa entrevista pra explicar as razões de usar isso ou aquilo, e essas normas chatas de gramática  e sintaxe que atrapalham no uso de coisas que funcionam

    Recomendo conhecer as opções e as ferramentas

 

  • Curtir 1
  • Obrigado 1
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...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!