How to check if the entered option is among the valid options

Asked

Viewed 183 times

3

I’m doing Exercise 28 of the website’s Decision Structure list [Pythonbrasil] (https://wiki.python.org.br/EstruturaDeDecisao) but when I include the code for when the user chooses an invalid option to terminate the program all the options I choose (even the right ones) terminates the program.

Code with probable error:

if tipo_da_carne.lower() != "f" or tipo_da_carne.lower() != "a" or tipo_da_carne.lower() != "p":
    print()
    print("{}".format("="*64))
    print("{}Opção Invalida".format(" "*25))
    print("{}".format("="*64))
    print()
    sys.exit()

Complete Code:

import sys

print()
print("{}".format("="*64))
print("{}Seja bem vindo ao Supermercado Tabajara".format(" "*12))
print("{}".format("="*64))
print()

tipo_da_carne = str(input("Precione F para File Duplo, A para Alcatra ou P para Picanha: "))

if tipo_da_carne.lower() != "f" or tipo_da_carne.lower() != "a" or tipo_da_carne.lower() != "p":
    print()
    print("{}".format("="*64))
    print("{}Opção Invalida".format(" "*25))
    print("{}".format("="*64))
    print()
    sys.exit()

qtd_carne = float(input("Digite a quantidade que vai querer: "))
tipo_pagamento = str(input("Caso tenha o cartão tabajara precione C ou D para dinheiro: "))

print()
print("{}".format("="*64))
print("{}Nota Fiscal".format(" "*26))
print("{}".format("="*64))
print()

#File Duplo
if tipo_da_carne.lower() == "f":
    print("Tipo da carne: File Duplo")
    print("Quantidade: {}".format(round(qtd_carne, 2)))

    #Calcular desconto por Kg
    if qtd_carne <= 5:
        preço_file_duplo = qtd_carne * 4.90
    else:
        preço_file_duplo = qtd_carne * 5.80

    #Preço Bruto
    print("Preço total: R${}".format(round(preço_file_duplo, 2)))

    #Catão Tabajara
    if tipo_pagamento.lower() == "c":
        print("Tipo de pagamento: Catão Tabajara")
        valor_desconto = preço_file_duplo * 0.05
        valor_pagar = preço_file_duplo - valor_desconto
        print("Desconto: R${}".format(round(valor_desconto, 2)))
        print("Preço Final: R${}".format(round(valor_pagar, 2)))
    else:
        print("Tipo de pagamento: Dinheiro")
        print("Desconto: R$0.0")
        print("Preço Final: R${}".format(round(preço_file_duplo, 2)))

#Alcatra
if tipo_da_carne.lower() == "a":
    print("Tipo da carne: Alcatra")
    print("Quantidade: {}".format(round(qtd_carne, 2)))

    #Calcular desconto por Kg
    if qtd_carne <= 5:
        preço_alcatra = qtd_carne * 4.90
    else:
        preço_alcatra = qtd_carne * 5.80

    #Preço Bruto
    print("Preço total: R${}".format(round(preço_alcatra, 2)))

    #Catão Tabajara
    if tipo_pagamento.lower() == "c":
        print("Tipo de pagamento: Catão Tabajara")
        valor_desconto = preço_alcatra * 0.05
        valor_pagar = preço_alcatra - valor_desconto
        print("Desconto: R${}".format(round(valor_desconto, 2)))
        print("Preço Final: R${}".format(round(valor_pagar, 2)))
    else:
        print("Tipo de pagamento: Dinheiro")
        print("Desconto: R$0.0")
        print("Preço Final: R${}".format(round(preço_alcatra, 2)))

#Picanha
if tipo_da_carne.lower() == "p":
    print("Tipo da carne: Picanha")
    print("Quantidade: {}".format(round(qtd_carne, 2)))

    #Calcular desconto por Kg
    if qtd_carne <= 5:
        preço_picanha = qtd_carne * 4.90
    else:
        preço_picanha = qtd_carne * 5.80

    #Preço Bruto
    print("Preço total: R${}".format(round(preço_picanha, 2)))

    #Catão Tabajara
    if tipo_pagamento.lower() == "c":
        print("Tipo de pagamento: Catão Tabajara")
        valor_desconto = preço_picanha * 0.05
        valor_pagar = preço_picanha - valor_desconto
        print("Desconto: R${}".format(round(valor_desconto, 2)))
        print("Preço Final: R${}".format(round(valor_pagar, 2)))
    else:
        print("Tipo de pagamento: Dinheiro")
        print("Desconto: R$0.0")
        print("Preço Final: R${}".format(round(preço_picanha, 2)))

print()
print("{}".format("="*64))
print()

2 answers

3


As already said in another answer, the problem is using or when you should actually use and. Using or, will enter the if if any of the conditions are true (i.e., if you type in f, will be no different than f, but it will be different from a, which is already enough to enter the if). Already using and, only enters the if if they are all true (that is, if the option is different from a, f and p).

But actually you could do it more simply. To begin with, input already returns a string, so do str(input(...)) is redundant and unnecessary. Also, I saw that you use several times the method lower(), but since you will only use the lowercase version of the string, use it only once, right after the input. So you could just do it like this:

tipo_da_carne = input("Pressione F para File Duplo, A para Alcatra ou P para Picanha: ").lower()

if tipo_da_carne not in ('a', 'f', 'p'):
    # opção inválida...

The not in checks whether the tipo_da_carne is not among the desired options. If not, enter if (that is, the option is invalid).


There are still other improvements to be made, here are some suggestions below:

By entering the amount of meat, you can capture the ValueError (which occurs if a number is not entered). Something like this:

while True:
    try:
        qtd_carne = float(input("Digite a quantidade que vai querer: "))
        break
    except ValueError:
        print('digite um número válido')

That is, until a number is entered, it keeps asking you to type again. If you enter a valid number, the break comes out of while and continues running the rest of the program.

Note: if the quantity can only be an integer number, prefer to use int instead of float.

Message printing can be encapsulated in a function:

def print_msg(msg):
    print()
    print('=' * 64)
    print('{:^64}'.format(msg))
    print('=' * 64)
    print()

Look at the stretch {:^64}: it centralizes the message, so you don’t need to put a fixed amount of spaces before the text (see more on documentation on the formats accepted by format). This way, you’d only need to call:

print_msg("Seja bem vindo ao Supermercado Tabajara")

That the format "turns around" to center the message.

Another thing is that the stretch that prints the price and other information is very repetitive (even the price is the same), so it would simplify also. You could use dictionaries to map the letters a, f and p for the respective names of the meat, and another to map the means of payment.

The code would look like this:

def print_msg(msg):
    print()
    print('=' * 64)
    print('{:^64}'.format(msg))
    print('=' * 64)
    print()

carnes = {
    'a': 'Alcatra',
    'f': 'Filé Duplo',
    'p': 'Picanha'
}

meios_pagto = {
    'c': 'Cartão Tabajara',
    'd': 'Dinheiro'
}

print_msg("Seja bem vindo ao Supermercado Tabajara")
tipo_da_carne = input("Pressione F para File Duplo, A para Alcatra ou P para Picanha: ").lower()

if tipo_da_carne not in carnes: # se tipo não é uma das chaves do dicionário "carnes"
    print_msg('Opção inválida')
else:
    while True:
        try:
            qtd_carne = float(input("Digite a quantidade que vai querer: "))
            break
        except ValueError:
            print('digite um número válido')

    tipo_pagamento = input("Caso tenha o cartão tabajara precione C ou D para dinheiro: ").lower()
    if tipo_pagamento not in meios_pagto:
        print_msg('Meio de pagto inválido')
    else:
        print_msg('Nota Fiscal')
        print("Tipo da carne: {}".format(carnes[tipo_da_carne]))
        print("Quantidade: {:.2f}".format(qtd_carne))
        # Calcular desconto por Kg
        if qtd_carne <= 5:
            preco = qtd_carne * 4.90
        else:
            preco = qtd_carne * 5.80

        #Preço Bruto
        print("Preço total: R${:.2f}".format(preco))
        print("Tipo de pagamento: {}".format(meios_pagto[tipo_pagamento]))

        # Cartão Tabajara
        if tipo_pagamento == "c":
            valor_desconto = preco * 0.05
            print("Desconto: R${:.2f}".format(valor_desconto))
            preco -= valor_desconto # subtrai o desconto do preço
        else:
            print("Desconto: R$0.0")

        print("Preço Final: R${:.2f}".format(preco))

        print()
        print("=" * 64)
        print()

tipo_da_carne not in carnes checks if the meat type is not one of the dictionary keys carnes (which in this case are a, f and p). Also note that when printing the name of the meat, I used carnes[tipo_da_carne], which is the name corresponding to the entered option.

I also used a dictionary for the means of payment, to verify that the option entered is valid and later to print the respective name. Note also that I did not use sys.exit(): instead, I just put a block else in the first if.

At last I used {:.2f} to format the price and other rounded values to 2 decimal places.

And I also simplified the last one a little bit if, which prints different information according to the means of payment (the common parts - that is, what it performs independent of the means of payment, such as the printing of the name and the final price - I took the if/else).


If you are using Python >= 3.6, you can still change the format for f-strings.

So instead of print("Quantidade: {:.2f}".format(qtd_carne)), you can use print(f"Quantidade: {qtd_carne:.2f}"):

def print_msg(msg):
    print()
    print('=' * 64)
    print(f'{msg:^64}')
    print('=' * 64)
    print()

carnes = {
    'a': 'Alcatra',
    'f': 'Filé Duplo',
    'p': 'Picanha'
}

meios_pagto = {
    'c': 'Cartão Tabajara',
    'd': 'Dinheiro'
}

print_msg("Seja bem vindo ao Supermercado Tabajara")
tipo_da_carne = input("Pressione F para File Duplo, A para Alcatra ou P para Picanha: ").lower()

if tipo_da_carne not in carnes:
    print_msg('Opção inválida')
else:
    while True:
        try:
            qtd_carne = float(input("Digite a quantidade que vai querer: "))
            break
        except ValueError:
            print('digite um número válido')

    tipo_pagamento = input("Caso tenha o cartão tabajara precione C ou D para dinheiro: ").lower()
    if tipo_pagamento not in meios_pagto:
        print_msg('Meio de pagto inválido')
    else:
        print_msg('Nota Fiscal')
        print(f"Tipo da carne: {carnes[tipo_da_carne]}")
        print(f"Quantidade: {qtd_carne:.2f}")
        # Calcular desconto por Kg
        if qtd_carne <= 5:
            preco = qtd_carne * 4.90
        else:
            preco = qtd_carne * 5.80

        #Preço Bruto
        print(f"Preço total: R${preco:.2f}")
        print(f"Tipo de pagamento: {meios_pagto[tipo_pagamento]}")

        # Cartão Tabajara
        if tipo_pagamento == "c":
            valor_desconto = preco * 0.05
            print(f"Desconto: R${valor_desconto:.2f}")
            preco -= valor_desconto
        else:
            print("Desconto: R$0.0")

        print(f"Preço Final: R${preco:.2f}")

        print()
        print("=" * 64)
        print()
  • Sorry for the many error in the code I am new in programming and I’m starting to learn now, for sure your help to simplify the code will help me a lot to evolve in the area, Thank you !

  • @Lucasestevam No need to apologize, the important thing is to learn and not make the same mistakes again :-) Another thing: if one of the answers solved your problem, you can choose the one that best solved it and accept it, see here how and why to do it. It is not mandatory, but it is a good practice of the site, to indicate to future visitors that it solved the problem. And when I get 15 points, you can also vote in all the answers you found useful.

1

The problem lies in choosing your logical operator. Replace OR with AND:

if tipo_da_carne.lower() != "f" or tipo_da_carne.lower() != "a" or tipo_da_carne.lower() != "p":

Leaving:

if (tipo_da_carne.lower() != "f") and (tipo_da_carne.lower() != "a") and (tipo_da_carne.lower() != "p"):

When you type F for example, the first analysis generates FALSE, but the other OR conditions will return TRUE (F is not equal to A which returns TRUE), entering the IF and at the end, ending the program.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.