TransWikia.com

"break" não termina a execução como deveria

Stack Overflow em Português Asked by Silvano Junior on November 21, 2020

Crie um programa onde o usuário possa digitar vários valores numéricos e cadastre-os em uma lista. Caso o número já exista lá dentro, ele não será adicionado. No final, serão exibidos todos os valores únicos digitados, em ordem crescente.

E até ai tudo bem essa foi a minha solução:

lista= []
     while True:
         ad = (int(input('Digite um valor: ')))
         if ad not in lista:
             lista.append(ad)
             print('Adicionado com sucesso!')
         else:
             print('Valor duplicado. Adição negada.')
         ask = str(input('Deseja continuar?[S/N] ')).strip().upper()[0]
         while ask not in 'SN':
             if ask == 'S':
                 continue
             elif ask == 'N':
                 break
             elif ask != 'SN':
                 print('Resposta inválida, por favor escolha entre [S/N]')
                 while ask not in 'SN':
                    ask = str(input('Deseja continuar?[S/N] ')).strip().upper()[0]
print('-=' * 30)
lista.sort()
print(f'Voce digitou os números: {lista}')

Quando perguntado se quero continuar e eu respondo ‘N’ o programa segue funcionando sem dar o break. Entretanto o mesmo código no PyCharm de outro colega funciona sem problema nenhum.

O que pode ser isso? Um bug? É possível resolvê-lo?

3 Answers

Na verdade, o PyCharm só executa, através do Python, o que você fez, então, o erro está no código.

O primeiro erro que ocorre é: se o usuário digitar corretamente 'S' ou 'N', ele nunca vai entrar no while ask not in 'SN', pois, essa condição significa: enquanto "ask" não estiver em 'SN'. Ou seja, ask estará dentro de 'SN', logo, a condição não é verdadeira, e ele não entra no while.

O outro erro é: se ask realmente não estiver em 'SN', então, ele não passará nas primeira e segunda condições dentro do segundo while, pois:

  • ask não será igual a 'S'
  • ask também não será igual a 'N'

Mas, ask será diferente de 'SN', então ele irá imprimir o aviso, e começará isso tudo de novo.

Então, você primeiro tem que testar se ask é igual a 'S', ou igual a 'N', antes de executar o while. E, se entrar no while, você faz a pergunta novamente, atribuindo a nova resposta para ask.

No entanto, após isso, você deverá criar uma forma de saber se a resposta "interna" foi não (ou 'N'), pois, o break que você executa dentro do segundo while só fará o mesmo parar, mas o primeiro while, que é o while True, continuará.

Tendo tudo isso em mente, acho que você poderia fazer desse modo:

lista= []
while True:
    ad = (int(input('Digite um valor: ')))
    if ad not in lista:
        lista.append(ad)
        print('Adicionado com sucesso!')
    else:
        print('Valor duplicado. Adição negada.')
    ask = str(input('Deseja continuar?[S/N] ')).strip().upper()[0]
    if ask == 'N':
        break
    resposta = None
    while ask not in 'SN':
        ask = str(input('Deseja continuar?[S/N] ')).strip().upper()[0]
        if ask == 'S':
            break
        elif ask == 'N':
            resposta = ask
            break
    if resposta == 'N':
        break
print('-=' * 30)
lista.sort()
print(f'Voce digitou os números: {lista}')

Espero ter ajudado!

Answered by Gustavo Sampaio on November 21, 2020

Não, não é bug no PyCharm, muito menos funciona no computador do seu colega. Não funciona porque o código está errado.

Primeiro, indentação. A indentação define os blocos de código no Python e é fundamental que ela esteja correta. Diferente da maioria das linguagens, o código não funcionará com a indentação errada. Seu primeiro laço está indentado em relação à definição da variável na primeira linha e isso não pode. Ambos devem estar no mesmo nível:

lista = []
while True:
    ...

Segundo, a função input sempre retorna uma string, então fazer str(input(...)) é redundante e completamente desnecessário. Você remove os espaços do valor lido, converte para maiúsculas e pega o primeiro caractere:

lista= []
while True:
    ad = (int(input('Digite um valor: ')))
    if ad not in lista:
        lista.append(ad)
        print('Adicionado com sucesso!')
    else:
        print('Valor duplicado. Adição negada.')
    ask = input('Deseja continuar?[S/N] ').strip().upper()[0]

Terceiro, você espera que o usuário digite apenas S ou N, mas na linha abaixo você faz:

lista= []
while True:
    ad = (int(input('Digite um valor: ')))
    if ad not in lista:
        lista.append(ad)
        print('Adicionado com sucesso!')
    else:
        print('Valor duplicado. Adição negada.')
    ask = input('Deseja continuar?[S/N] ').strip().upper()[0]
    while ask not in 'SN':
        ...

Enquanto ask não for S ou N, faça... e logo depois você verifica se é S ou N. Essas condições nunca serão satisfeitas uma vez que o while garante que ask é diferente de S e N. Usar o continue ou o break aqui também não faz sentido, pois eles atuarão sobre o último laço de repetição, que é justamente o while ask not in 'SN', mas isso não faz sentido.

Quarto, a sua última condição elif ask != 'SN' também está errada. Se você garantiu que ask é somente o primeiro caractere informado, ele nunca possuirá dois caracteres, portanto a igualdade sempre será satisfeita.


Melhorias:

  1. Use set no lugar de list; ele, por definição, não possui valores duplicados;
  2. Trate a exceção lançada por int quando a conversão para inteiro falhar;
  3. Você pode parar a leitura quando o usuário informar algo que não seja um número;

Por exemplo:

numeros = set()

while True:
    try:
        numero = int(input('Número? '))
        numeros.add(numero)
    except ValueError:
        break

print('Ordem crescente: ', sorted(numeros))

Ficando:

Número? 5
Número? 3
Número? 4
Número? 8
Número? 1
Número? 9
Número?
Ordem crescente:  [1, 3, 4, 5, 8, 9]

Answered by Woss on November 21, 2020

Certamente não porque o PyCharm é só um editor de código. E também não é no Python, porque duas coisas exatamente iguais só podem dar o mesmo resultado, mesmo que tivesse um bug. bugs não são mágicos que aparecem e desaparecem. Mas se não é tudo exatamente igual, aí pode dar resultado diferente, e não dá para culpar o IDE pelo problema, o problema está no que é diferente, ou seja, seu código, sua configuração. De qualquer forma, milhões de pessoas usam Python há anos, quais as chances que você teria de achar um bug em um código bem básico logo no começo do seu aprendizado? Não parece mais óbvio que seja um problema no seu código e que deveria partir dessa premissa antes de pensar em bug de uma ferramenta consagrada?

Eu fui tentar compilar, dava erro, eu consertava, dava outro, eu consertava e dava outro, até que eu desisti de tentar.

De qualquer forma eu vi alguns problemas conceituais no código e pelo menos um de lógica que causa todo o problema. Se você cria dois laços aninhados e no mais interno dá um break nele, para onde acha que ele vai? Para o final desse laço. Imagino que está achando que ele sai dos dois laços, mas não é o caso. Além disto está criando mais um terceiro e repetindo as mesmas coisas que já havia programado antes. Não só isto, uma condição testa se é S ou N, depois testa-as individualmente e depois se não é nenhuma das duas, isto não faz sentido.

Assim é mais simples, mais organizado e funciona:

def entrada(lista):
    while True:
        ad = (int(input('Digite um valor: ')))
        if ad not in lista:
            lista.append(ad)
            print('Adicionado com sucesso!')
        else:
            print('Valor duplicado. Adição negada.')
        while True:
            ask = str(input('Deseja continuar?[S/N] ')).strip().upper()[0]
            if ask == 'S':
                break
            elif ask == 'N':
                return
lista = []
entrada(lista)
print(lista)

Veja funcionando no ideone. E no repl.it. Também coloquei no GitHub para referência futura.

Answered by Maniero on November 21, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP