Eingabe-Validierung

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
Karon1981
User
Beiträge: 6
Registriert: Samstag 15. Mai 2021, 19:10

Samstag 15. Mai 2021, 19:15

Hallo zusammen,

ich bin gerade am verzweifeln. Ich stehe vor folgendem Problem:

Ich möchte hintereinander mehrere Daten eingeben, wie das Körper-Gewicht und die Körper-Größe.

Die eingegebenen Daten sollen auf Richtigkeit (keine Buchstaben und bestimmte Zahlenbereiche) überprüft werden. Das mit den Buchstaben bekomme ich hin, aber die gleichzeitige Überprüfung der Zahlenbereiche haut nicht hin, er überspringt diese und springt dann zur Eingabe der Größe. Wo mache ich etwas falsch?

Code: Alles auswählen

        while True:
                    try:
                        gewicht = 0
                        gewicht = int(input ("Bitte gib dein Körpergewicht (kg) ein: "))
                    except ValueError:
                        if gewicht < 1 or gewicht > 300:
                            print ("Wert unrealistisch, bitte noch einmal eingeben!")
                    else:
                        break 
            
        while True:
                    try:
                        groesse = int(input ("Bitte gib deine Körpergröße ein (cm): "))
                    except ValueError:
                        print("Bitte nur Zahlen eingeben!")
                    else:
                        break
                        if groesse > 250 or groesse < 100:
                            print ("Wert nicht realistisch, bitte noch einmal eingeben! ")
                            groesse = int(input ("Bitte gib deine Größe (cm) ein: "))
Jemand eine Idee?
Vielen Dank und viele Grüße
Karon
Benutzeravatar
sparrow
User
Beiträge: 2745
Registriert: Freitag 17. April 2009, 10:28

Samstag 15. Mai 2021, 21:27

Eingerückt wird in Python mit 4 Leerzeichen. Nciht mit Tabs - oder was auch immer du da nimmst.
Zwichen den Funktionsnamen und die öffnende Klammer gehört kein Leerzeichen.

Der except-Block wird nur betreten, wenn die abzufangende Exception auch auftritt. Demnach wird nur geprüft, ob das Gewicht in einem gültigen Bereich ist, wenn zuvor ein Value Error aufgetreten ist.
Karon1981
User
Beiträge: 6
Registriert: Samstag 15. Mai 2021, 19:10

Samstag 15. Mai 2021, 21:43

Vielen Dank schon einmal...

Wie muss denn der Quellcode heißen, damit beide Überprüfungen (nur Zahlen und die Bereiche) funktionieren? Habe schon alle möglichen Varianten getestet. 🙄
Benutzeravatar
sparrow
User
Beiträge: 2745
Registriert: Freitag 17. April 2009, 10:28

Samstag 15. Mai 2021, 22:04

Geh den Quellcode doch mal Zeile für Zeile durch und erklär mal, was er macht
rogerb
User
Beiträge: 262
Registriert: Dienstag 26. November 2019, 23:24

Sonntag 16. Mai 2021, 13:59

Hallo Karon 1981,

du warst nah dran, nur die Reihenfolge stimmte nicht ganz.
Hier ist eine lauffähige Umsetzung mit Kommentaren. Das sagt manchmal mehr als viele Worte:

Code: Alles auswählen

gewicht = 0
groesse = 0

while True:
    try:
        gewicht = int(input("Bitte gib dein Körpergewicht (kg) ein: "))
        
    except ValueError:
        # ValueError wird abgefangen, falls die Eingabe nicht in Zahlenwerte umgewandelt werden konnte
        print("Es dürfen nur Zahlen eingegeben werden, bitte noch einmal eingeben")

        # mit continue wird die Bearbeitung des Schleifendurchlaufs hier
        # abgrebrochen und wieder von vorn begonnen
        continue

    # Die Eingabe konnte in einen Zahlenwert umgewandelt werden
    # jetzt kann der Bereich validiert werden
    if gewicht < 1 or gewicht > 300:
        print("Wert unrealistisch, bitte noch einmal eingeben!")
    else:
        # Eingabe war erfolgreich, die while-Schleife kann verlassen werden
        break

while True:
    try:
        groesse = int(input("Bitte gib deine Körpergröße ein (cm): "))
    except ValueError:
        print("Bitte nur Zahlen eingeben!")
        continue

    if groesse > 250 or groesse < 100:
        print("Wert nicht realistisch, bitte noch einmal eingeben! ")
    else:
        break

print(f"Gewicht: {gewicht}")
print(f"Groesse: {groesse}")
Benutzeravatar
__blackjack__
User
Beiträge: 8856
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Sonntag 16. Mai 2021, 15:40

@rogerb: Die Verwendung von ``continue`` ist hier aber eher ein Rückschritt, denn ``try``/``excep`` kennt, genau wie Karon1981, auch einen ``else``-Zweig. Dann hat man keinen unbedingten Sprung an den Schleifenanfang der sich nicht an der Einrückung ablesen lässt, und man hat die Chance auch am Ende *jedes* Schleifendurchlaufs noch Code hinzuzufügen, den ein ``continue`` umgehen würde.

`gewicht` und `groesse` mit 0en vorzubelegen die niemals irgendwo benutzt werden macht keinen Sinn. Zudem wären Beide Werte ja auch ausserhalb des Zahlenbereichs der gültig sein soll.

@Karon1981: Ob ein Wert innerhalb eines Zahlenbereichs liegt, prüft man am lesbarsten mit einem verketteten Vergleich, wie man das auch aus der Mathematik kennt. Also statt ``if x > 10 or x < 1:`` würde man ``if not 1 <= x <= 10:`` schreiben.

Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3


def main():
    while True:
        try:
            gewicht = int(input("Bitte gib dein Körpergewicht (kg) ein: "))
        except ValueError:
            print(
                "Es dürfen nur Zahlen eingegeben werden,"
                " bitte noch einmal eingeben!"
            )
        else:
            if 1 <= gewicht <= 300:
                break

            print("Wert unrealistisch, bitte noch einmal eingeben!")

    while True:
        try:
            groesse = int(input("Bitte gib deine Körpergröße ein (cm): "))
        except ValueError:
            print("Bitte nur Zahlen eingeben!")
        else:
            if 100 <= groesse <= 250:
                break

            print("Wert nicht realistisch, bitte noch einmal eingeben!")

    print(f"Gewicht: {gewicht}")
    print(f"Groesse: {groesse}")


if __name__ == "__main__":
    main()
Jetzt hat man für beide Eingaben aber strukturell den gleichen Code wiederholt. Solche Codewiederholungen macht man als Programmierer nicht, sondern zieht das als Funktion heraus.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3


def ask_integer(prompt, lower_limit, upper_limit):
    while True:
        try:
            result = int(input(prompt))
        except ValueError:
            print(
                "Es dürfen nur Zahlen eingegeben werden,"
                " bitte noch einmal eingeben!"
            )
        else:
            if lower_limit <= result <= upper_limit:
                return result

            print("Wert unrealistisch, bitte noch einmal eingeben!")


def main():
    gewicht = ask_integer("Bitte gib dein Körpergewicht (kg) ein: ", 1, 300)
    groesse = ask_integer("Bitte gib deine Körpergröße ein (cm): ", 100, 250)
    print(f"Gewicht: {gewicht}")
    print(f"Groesse: {groesse}")


if __name__ == "__main__":
    main()
Q: What is the volume of a pizza of radius z and thickness a?
A: pi·z·z·a
Karon1981
User
Beiträge: 6
Registriert: Samstag 15. Mai 2021, 19:10

Montag 17. Mai 2021, 09:49

Hallo,

das hat schon einmal super geholfen und habe ich jetzt eingebaut, vielen Dank... :)

Habe aber noch eine Frage:
Ich möchte den Stoffwechsel berechnen und habe jeweils die Berechnung von Frau und Mann in eine separate Funktion gepackt.

Um aber im Hauptprogramm die Eingabe zu überprüfen, habe ich das so gelöst:

Code: Alles auswählen

print ("Programm zur Berechnung des Stoffwechsels")
name = input("Bitte gib deinen Namen ein: ")
print ("Hallo", name)
gender = input ("Bist du ein Mann oder eine Frau? ")
if gender == "Mann" or "m" or "mann":
    mann()
    sys.exit()
elif gender == "Frau" or "w" or "frau":
    frau()
    sys.exit()
Habt ihr noch eine bessere Idee, wie man das Geschlecht unterscheiden kann?
Sirius3
User
Beiträge: 14798
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 17. Mai 2021, 10:21

Du verwendest `or` falsch, die Ausführungsreihenfolge ist (gender == "Mann") or "m" or "mann" und ein nicht-leerer String ist immer wahr, so dass man das zu True vereinfachen kann, was Du suchst ist der in-Operator.
`sys.exit` braucht man selten, hier ist es falsch, weil man nicht mittendrin ein Programm beenden sollte.
Hier ist wohl das biologische Geschlecht (sex) gemeint.

Code: Alles auswählen

print("Programm zur Berechnung des Stoffwechsels")
name = input("Bitte gib deinen Namen ein: ")
print ("Hallo", name)
sex = input ("Bist du ein Mann oder eine Frau? ")
if sex in ["Mann", "m", "mann"]:
    mann()
elif sex in ["Frau", "w", "frau"]:
    frau()
Ich denke, dass sowohl in `mann` als auch in `frau` Größe und Gewicht gebraucht werden, das ist also eine Aufgabe für's Hauptprogramm, ebenso wie die Ausgabe, die wohl auch für beide Geschlechter gleich sind.
Funktionen sollten nach Tätigkeiten benannt werden.
Karon1981
User
Beiträge: 6
Registriert: Samstag 15. Mai 2021, 19:10

Freitag 21. Mai 2021, 08:49

Hallo zusammen,

vielen Dank schon einmal für die ganze Hilfe, das Programm läuft jetzt soweit.

Könnt ihr aber noch einem Nicht-Entwickler und Nicht-ITler (meiner Freundin) die Funktion von

Code: Alles auswählen

while True
try:
...
expect ValueError:
...
continue
erklären? Sie muss die Funktion erklären nächste Woche Dienstag,

Vielen Dank... :-)
Sirius3
User
Beiträge: 14798
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 21. Mai 2021, 09:18

Das `continue` sollte gar nicht vorkommen, wie in __blackjacks__ Antwort ausführlich beschrieben.
Was darin versteht Deine Freundin denn konkret nicht?
Karon1981
User
Beiträge: 6
Registriert: Samstag 15. Mai 2021, 19:10

Freitag 21. Mai 2021, 09:39

Sirius3 hat geschrieben:
Freitag 21. Mai 2021, 09:18
Das `continue` sollte gar nicht vorkommen, wie in __blackjacks__ Antwort ausführlich beschrieben.
Was darin versteht Deine Freundin denn konkret nicht?
Sie versteht nicht, warum man sowas verwendet und was genau in dieser Schleife passiert. Wie gesagt, Non-ITler und mit IT nix zu tun... :D
Sirius3
User
Beiträge: 14798
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 21. Mai 2021, 09:46

Schleifen verwendet man, um etwas zu wiederholen. Hier wird die Eingabe so lange wiederholt, bis sie fehlerfrei ist. except benutzt man um Fehler abzufangen. Tritt innerhalb eines try-Blocks ein Fehler auf, wird in den passenden except-Block gesprungen sonst in den else-Block.
Karon1981
User
Beiträge: 6
Registriert: Samstag 15. Mai 2021, 19:10

Freitag 21. Mai 2021, 10:50

Sirius3 hat geschrieben:
Freitag 21. Mai 2021, 09:46
Schleifen verwendet man, um etwas zu wiederholen. Hier wird die Eingabe so lange wiederholt, bis sie fehlerfrei ist. except benutzt man um Fehler abzufangen. Tritt innerhalb eines try-Blocks ein Fehler auf, wird in den passenden except-Block gesprungen sonst in den else-Block.
Okay, ich glaube, ihr ist noch nicht so ganz klar, wieso man gerade diese Funktion einsetzt, wie eben den Try-Block und das Except... :D
Sirius3
User
Beiträge: 14798
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 21. Mai 2021, 11:14

Welche Funktion? Das Mittel zur Fehlerbehandlung ist ein try-except-Konstrukt, das Wieso ist also, weil man Fehler behandeln möchte.
Benutzeravatar
noisefloor
User
Beiträge: 3197
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Freitag 21. Mai 2021, 12:39

Hallo,

`try...except` macht doch genau das, was die englischen Worte beschreiben. Frei übersetzt auf deutsch:

"Probier mal ...., aber wenn ein Fehler auftritt, dann ...." (-> das würde für ein nacktes `try...except`gelten, was man eigentlich nicht benutzt)

Bei dir wäre es mit der konkreten Feherlbehandlung so was wie: "Probier mal..., aber wenn ein Fehler mit dem Wert auftritt, dann ..."

Gruß, noisefloor
Antworten