Operator problem not in the condition of a while loop

Asked

Viewed 107 times

2

I made a program to train txt manipulation:

def escreve():
    BancodeDados = open("Base.txt", "a")
    continua=True
    k=1
    while continua:
        nome = input("Nome do cliente: ")
        idade = input("Idade do cliente: ")
        while True:
            try:
                sexo = input("Sexo do cliente (m/f): ")
                if sexo == "m" or sexo == "f":
                    break
                else:
                    raise SexoInvalido
            except SexoInvalido:
                print(SexoInvalido())
        BancodeDados.write("Cliente {} Nome {} Idade {} Sexo {}\n".format(k, nome, idade, sexo))
        k += 1
        sessão = 0
        while not sessão == "1" or not sessão == "2":
            sessão = input("Deseja encerrar sessão (1) ou continuar (2)? ")
            if sessão != "1" or sessão != "2":
                sessão = input("Resposta inválida. Deseja encerrar sessão (1) ou continuar (2)? ")
        if sessão == "2":
            continua = True
        elif sessão == "1":
            continua = False
            print("Fechando banco de dados.")
            BancodeDados.close()

I would like to understand why although my condition is specified in while (line 20: while not sessão == "1" or not sessão == "2":, that is, while not inputado 1 or 2) I keep falling in this loop even when inputo 1 or 2 when that should be the exit condition of the loop.

  • 1

    Your condition is "not equal to 1 or not equal to 2", which could be translated to "not equal to 1 or not equal to 2"; when you enter the value 1 it will be different from 2; when you enter the value 2 it will be different from 1. Maybe you should change to and. Incidentally, this you might notice by doing the table test, recommend doing it whenever you have a problem like this.

1 answer

3

The problem is in this if:

if sessão != "1" or sessão != "2":

The condition or means that if any of the options is valid, it if. So if you type "2", the condition sessão != "1" is valid and he enters the if. If you want me to get in this if only if the two conditions are true (if sessão is different from "1" and of "2"), then you must use and in place of or (documentation).

The condition of this while also has this problem, but you could also do so:

while True:
    nome = input("Nome do cliente: ")
    idade = input("Idade do cliente: ")
    while True:
        sexo = input("Sexo do cliente (m/f): ")
        if sexo == "m" or sexo == "f":
            break
        else:
            print('sexo inválido')

    BancodeDados.write("Cliente {} Nome {} Idade {} Sexo {}\n".format(k, nome, idade, sexo))
    k += 1
    while True:
        sessão = input("Deseja encerrar sessão (1) ou continuar (2)? ")
        if sessão != "1" and sessão != "2":
            print("Resposta inválida", end=" ") # só imprime a mensagem
        else:
            break

    if sessão == "1":
        print("Fechando banco de dados.")
        BancodeDados.close()
        break

If sessão is not "1" nor "2", i just print the message indicating it is invalid. No need to use input within the if, for the next iteration of while will do it already (I just put a end=" " in the print so that after the message is printed a space instead of the line break, so the message "Want to end session..." will be on the same line, as you intended to do in your code).

Note the use of break to break the loop. And each break refers to the loop in which it is: the first within if sexo == "m" or sexo == "f" interrupts the loop that reads the sexo, the second within the else interrupts the loop that reads the sessão, and the third within the if sessão == "1" interrupts the main loop (note that because of this, you don’t even need the variable continua).

The if'could also be exchanged for if sexo in ("m", "f") (if the sexo for "m" or "f") and if sessão not in ("1", "2") (if sessão is not "1" nor "2").

I also removed the raise SexoInvalido, i preferred to print the message directly when the sexo is not "m" nor "f".


As the program grows, this pile of while's inside another can end up confusing the code. If you want, you can break it into smaller functions, e.g.:

def ler_sexo():
    while True:
        sexo = input("Sexo do cliente (m/f): ")
        if sexo in ("m", "f"):
            return sexo
        else:
            print('sexo inválido')

def ler_opcao():
    while True:
        opcao = input("Deseja encerrar sessão (1) ou continuar (2)? ")
        if opcao not in ("1", "2"):
            print("Resposta inválida", end=" ")
        else:
            return opcao

BancodeDados = open("Base.txt", "a")
k=1
while True:
    nome = input("Nome do cliente: ")
    idade = input("Idade do cliente: ")
    sexo = ler_sexo()
    BancodeDados.write("Cliente {} Nome {} Idade {} Sexo {}\n".format(k, nome, idade, sexo))
    k += 1
    if ler_opcao() == "1": # a opção nem precisa de variável, pode comparar direto
        print("Fechando banco de dados.")
        BancodeDados.close()
        break

Now in the loops that do the reading of sexo and the option to continue I put return instead of break, so the function only returns the value if it is one of the valid options (if it is not, asks the user to type again).

In the end, I did if ler_opcao() == "1": the result of ler_opcao() does not need a variable, I can compare your return directly with "1". And I don’t even have to check if it’s "2" to know of I must continue the loop, because the function ler_opcao already ensures that will only be returned "1" or "2".

Browser other questions tagged

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