for-Schleife mit Abbruch

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Mr.Gnu
User
Beiträge: 4
Registriert: Samstag 13. Februar 2016, 18:26

Hi Leute,

habe vor wenigen tagen mit Python angefangen und versuche das erlernte auch gleich
in kleinen Programmen umzusetzen.

Nun bin ich allerdings seit heute Mittag an einem kniffligen Problem,
bei dem ich nicht weiter komme.

Es handelt sich dabei um eine kleines Programm, welches einem die Höhe der Lohnsteuer
ausrechnen soll.

Sobald ein Gehalt unter 450,00 € angegeben wird, fordert das Programm die erneute
Eingabe des Gehalt´s. (das funktioniert)

Sobald man ein höheres Gehalt eingibt, spuckt das Programm die Lohnsteuer aus. (und das funktioniert auch :) )
Nachdem das Ergebnis ausgespuckt wurde, kommt allerdings als Abschluss unten stehende Ausgabe, welche
nur bei der Eingabe eines zu niedrigen Gehalt´s kommen sollte.

Code: Alles auswählen

Das Gehalt wurde zu oft falsch eingeben. Das Programm wird beendet.
Programm beendet!

Kann mir jemand sagen, weshalb break nicht funktioniert bzw. was ich falsch mache?

Code: Alles auswählen

# Schleife
for i in 1, 2, 3, 4:

    # Eingabe
    print("Bitte geben Sie Ihr Gehalt und Ihren Familienstand ein: 1 = ledig, 2 = verheiratet")
    gehalt = int(input())
    fs = int(input())
    print("Ihr Gehalt:", gehalt,"Euro, Ihr Familienstand:", fs)    

    # Berechnung
    if gehalt >= 450 and fs == 1 or gehalt == 2000 and fs == 1:
       steuersatz = gehalt * 20 / 100
       print("Ihr Steuersatz beträgt:", steuersatz, "Euro")
       print("Ende")
       break
    elif gehalt == 450 or gehalt <= 2000 and fs == 2:
         steuersatz = gehalt * 18 / 100
         print("Ihr Steuersatz beträgt:", steuersatz, "Euro")
         print("Ende")
         break
    elif gehalt > 2000 and fs == 1 or fs == 2:
         steuersatz = gehalt * 22 / 100
         print("Ihr Steuersatz beträgt:", steuersatz, "Euro")
         print("Ende")
         break

    else:
        print("Ihre Gehaltseingabe in Höhe von",gehalt ,"Euro ist zu niedrig!")

print("Das Gehalt wurde zu oft falsch eingeben. Das Programm wird beendet.")
print("Programm beendet!")
BlackJack

@Mr.Gnu: Wieso denkst Du ``break`` würde dafür sorgen das von den beiden `print()`-Aufrufen nach der Schleife, die also mit der Schleife überhaupt nichts zu tun haben, nur der zweite Aufruf ausgeführt werden würde? ``break`` bricht die Schleife ab.

Vielleicht wolltest Du die erste Ausgabe in einen ``else``-Zweig zum ``for`` setzen.

Allerdings ist die Aufteilung so nicht wirklich sinnvoll. Die Berechnung sollte erst nach erfolgreicher Eingabe stehen und nicht schon in der Schleife welche die Eingabe sicherstellen soll. Am besten teilt man so etwas auch auf mehrere Funktionen auf. Also eine Funktion die den Familienstand erfragt (und auch so lange bis eine gültige Antwort kan), dann eine die das Gehalt abfragt, eine welche die Steuer ausrechnet, und zum Schluss dann das Hauptprogramm, welches all diese Funktionen benutzt um das Gesamtproblem zu lösen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Mr.Gnu
User
Beiträge: 4
Registriert: Samstag 13. Februar 2016, 18:26

Hallo BlackJack,

vielen Dank für deine Antwort.

Mein Gedankengang war folgender:

Wenn "break" die Schleife abbricht, kommt nach Ausgabe der Lohnsteuer

Code: Alles auswählen

print("Ende")
und es muss danach auch nichts weiteres mehr eingegeben werden.

Code: Alles auswählen

print("Das Gehalt wurde zu oft falsch eingeben. Das Programm wird beendet.")
print("Programm beendet!")
sollte nur erscheinen, wenn das Gehalt mehrfach falsch eingegeben wurde.

Über die sinnvolle Aufteilung des Programms hatte ich mir noch keine Gedanken gemacht, wollte damit ersteinmal
die Schleifen und Kontrollstrukturen für mich verständlicher machen. :roll:

Kannst du mir bezüglich "else"-Zweig zum "for" setzen, ein kleines Beispiel nennen?
Mr.Gnu
User
Beiträge: 4
Registriert: Samstag 13. Februar 2016, 18:26

Hallo LKX,

vielen Dank für den Code mit dem Zähler.

Hatte das Tutorial welches ich gelesen hatte, so verstanden, dass man

Code: Alles auswählen

for i in 1, 2, 3, 4:

für falsche Eingaben wie z. B. zu niedriges Gehalt verwenden kann und somit dann auf eine erneute Eingabe hinweist
bzw. abbricht sobald beim vierten mal wieder eine falsche Eingabe getätigt wurde.

Werde nun mal mit "unvalidInput = 3:" herum experimentieren.

Vielen Dank nochmals
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@Mr.Gnu: Python kennt auch bei for-Schleifen einen else-Teil, der genau dann ausgeführt wird, wenn die Schleife bis zum Ende ohne break abgearbeitet wurde, also genau das was Du willst:

Code: Alles auswählen

for i in 1, 2, 3, 4:
    # Eingabe
    print("Bitte geben Sie Ihr Gehalt und Ihren Familienstand ein: 1 = ledig, 2 = verheiratet")
    gehalt = int(input())
    fs = int(input())
    print("Ihr Gehalt:", gehalt,"Euro, Ihr Familienstand:", fs)    

    # Berechnung
    if gehalt >= 450 and fs == 1 or gehalt == 2000 and fs == 1:
       steuersatz = gehalt * 20 / 100
       print("Ihr Steuersatz beträgt:", steuersatz, "Euro")
       print("Ende")
       break
    elif gehalt == 450 or gehalt <= 2000 and fs == 2:
         steuersatz = gehalt * 18 / 100
         print("Ihr Steuersatz beträgt:", steuersatz, "Euro")
         print("Ende")
         break
    elif gehalt > 2000 and fs == 1 or fs == 2:
         steuersatz = gehalt * 22 / 100
         print("Ihr Steuersatz beträgt:", steuersatz, "Euro")
         print("Ende")
         break
    else:
        print("Ihre Gehaltseingabe in Höhe von",gehalt ,"Euro ist zu niedrig!")
else:
    print("Das Gehalt wurde zu oft falsch eingeben. Das Programm wird beendet.")
    print("Programm beendet!")
Sinnvoller ist es aber, die Eingabe von der Verarbeitung in verschiedene Funktionen zu trennen:

Code: Alles auswählen

def lese_familienstand():
    for i in range(4):
        print("Bitte geben Sie Ihren Familienstand ein: 1 = ledig, 2 = verheiratet")
        fs = int(input())
        if fs in (1,2):
            return fs
    raise ValueError("Der Familienstand wurde zu oft falsch eingeben.")

def lese_gehalt():
    for i in range(4):
        print("Bitte geben Sie Ihr Gehalt ein:")
        gehalt = int(input())
        if gehalt >= 450:
            return gehalt
        print("Ihre Gehaltseingabe in Höhe von %s Euro ist zu niedrig!" % gehalt)
    raise ValueError("Der Gehalt wurde zu oft falsch eingeben.")

def main():
    try:
        gehalt = lese_gehalt()
        fs = lese_familienstand()
    except ValueError as e:
        print(e)
        return

    print("Ihr Gehalt: %s Euro, Ihr Familienstand: % s" % (gehalt, fs))

    if gehalt > 2000:
        steuersatz = 0.22
    elif gehalt == 450 or fs == 2:
        steuersatz = 0.18
    else:
        steuersatz = 0.20

    steuern = gehalt * steuersatz
    print("Ihre Steuern betragen: %.2f Euro" % steuern)

if __name__ == '__main__':
    main()
BlackJack

Also korrektes Englisch wäre `invalidInput`, kontionielle Schreibweise wäre `invalid_input`, und dann ist es aber immer noch inhaltlich ein schlechter Name weil der nicht für eine ungültige Eingabe steht sondern für einen Zähler. Und dafür würde man tatsächlich eher eine ``for``-Schleife verwenden statt das manuell selber hoch zu zählen.
Mr.Gnu
User
Beiträge: 4
Registriert: Samstag 13. Februar 2016, 18:26

Hi Sirius3,

vielen Dank für den Hinweis mit

Code: Alles auswählen

else: print("Das Gehalt wurde zu oft falsch eingeben. Das Programm wird beendet.")
               print("Programm beendet!")
Genau das ist die Lösung die ich gesucht habe. :)

Wie gesagt, bin momentan nur am experimentieren mit den Schleifen und Kontrollstrukturen.
Wenn ich mit den Übungen fertig bin, werde ich eure Ratschläge bezüglich Programmaufteilung
beherzigen und umsetzen.

Vielen Dank nochmal für eure Hilfe und Bemühungen.
Antworten