Reflexionen über die Programmiersprache Rust 17

*Benutzereingaben

Endlich ist es soweit, endlich darf der Benutzer auch mal was tun. Also mir kommt vor, dass die meisten Programmierer überhaupt Sorge haben, wenn der Benutzer was eingibt. Der könnte etwas kaputt machen, was der Programmierer vorher nicht durchdacht hat.Dabei ist eigentlich die Interaktion zwischen Benutzer und System überhaupt das Interessanteste, finde ich. Leider ist es nicht so, dass wir einfach nur let input = Benutzereingabe verwenden können. Wie in einem früheren Abschnitt erwähnt, sind Benutzereingaben prinzipiell als Strings zu behandeln. Es sind Strings.

Bevor wir anfangen, brauchen wir noch eine Bibliothek, in Rust ein sogenanntes Crate, in den Code eingebunden.

use std::io;
fn main (){
..rustcode...
}

use std::io ist quasi die importierte Kiste, die Eingaben vom Benutzer, mit der Rust-Standardbibliothek einlesen kann. Sie befindet sich im Regelfall oberhalb der Main-Funktion

Der nächste Schritt legt eine Variable an, wo die Nutzerdaten gespeichert werden, wie gesagt, ein String.

let mut var_benutzereingabe = String::new();

Warum ist das ein mut? Weil der String::new durch den Benutzer verändert werden wird. Was muss jetzt mit diesem String gemacht werden? Er wird eingelesen, in einer bestimmten Form. Das sieht anfangs vielleicht etwas langwierig aus, aber es sind letztlich nur ein paar zusammenhängende Wörter, die bestimmte Aufgaben erfüllen.

io::stdin().read_line(&mut var_benutzereingabe).expect("Fehlermeldung!");

Schritt für Schritt
*io::stdin() -> damit wird von io(Input/Output) aus der Standardbibliothek die Funktion aufgerufen, die für das Einlesen zuständig ist. (Vielleicht ist es per genauerer Definition auch keine Funktion)
*.read_line(&mut var_benutzereingabe) -> Was eingelesen werden soll.
*.expect("Fehlermeldung!") -> Was bei einem Fehler ausgegeben werden soll.

Jetzt könnte man mit dem Thema schon Schluss machen, wenn der Nutzer nur Text eingibt und das Programm das nicht weiter verarbeitet. Leider, wie kann es anders sein, ist es nicht so. Der Nutzer könnte auch Zahlen eingeben und diese Zahlen sehen bekanntlich nur wie Zahlen aus, werden aber nicht als Erstes so gewertet. Immerhin könnte der Nutzer zB eine Telefonnummer schreiben, oder eine Straße mit Hausnummer, also etwas Textuelles und nichts Mathematisches meinen. Damit da nix durcheinander kommt, wird das strikt unterschieden.

Aber wie macht man das jetzt?

Als erstes ist es hilfreich zu überlegen, was man vom Benutzer will. Danach ist die Entscheidung des Vorgehens schon wesentlich einfacher. Nehmen wir diesmal eine Addition an, wo der Benutzer zwei Zahlen eingibt. Nein, vereinfachen wir das Ganze und lassen den Benutzer zwei Zahlen eingeben, die wir per Funktionen in die Grundrechnungsarten umwandeln lassen.

Für den Anfang möchte ich den Befehl trim zeigen. Diesen hätten wir vorher auch schon verwenden können. Dieser ist dafür zuständig, dass sämtliche unnötigen whitespaces am Anfang und Ende der Benutzereingabe getilgt werden. Falls der Benutzer aus irgendeinem Grund am Anfang, oder Ende, oder Beidem, Leerzeichen, Zeilenvorschub, oder Tabulator drückt, sind diese dann weg. Bei Text kann man diese durchaus lassen, bis auf das Design hat es keinen negativen Effekt. Vielleicht wollte der Benutzer das ja so schreiben.
Wenn es um mathematische Aufgaben geht, ist es nicht so vorteilhaft, ganz im Gegenteil, denn ein Integer oder Float können mit einem Leerzeichen überhaupt nichts anfangen. Optimal setzt man trim direkt unter dem Einlesen, damit darauffolgende Elemente bereits sauber damit arbeiten können.
Sieht dann zB so aus:

    println!("Bitte gib deinen Text ein:");
    let mut var_benutzereingabe = String::new();
    io::stdin().read_line(&mut var_benutzereingabe).expect("Fehler!");
    let var_benutzereingabe = var_benutzereingabe.trim();
    println!("Du hast folgendes eingegeben: {}", var_benutzereingabe);

Und in der Anwendung sind dann tatsächlich die Leerzeichen weg.

image.png

Nachdem das jetzt bekannt ist, können wir uns das mal konkret mit den Zahlen ansehen. Also, lassen wir zuerst etwas vom Benutzer einlesen, schreiben die nötigen Funktionen und sehen uns die nötigen Befehle zum Umwandeln des Datenformats an.

use std::io;

fn add (a:f32,b:f32) -> f32{
    let result = a+b;
    println!("Addition:\n{} + {} = {}",a,b,result);
        result
}

fn min (a:f32,b:f32) -> f32{
    let result = a-b;
    println!("Subtraktion:\n{} + {} = {}",a,b,result);
        result
}

fn multi (a:f32,b:f32) -> f32{
    let result = a*b;
    println!("Multiplikation:\n{} + {} = {}",a,b,result);
        result
}

fn div (a:f32,b:f32) -> f32{
    let result = a/b;
    println!("Division:\n{} + {} = {}",a,b,result);
        result
}

fn main (){
    
    let mut zahl1 = String::new();
    println!("Bitte gib die erste Zahl ein");
    io::stdin().read_line(&mut zahl1).expect("Fehler!");
    let mut zahl2 = String::new();
    println!("Bitte gib die zweite Zahl ein");
    io::stdin().read_line(&mut zahl2).expect("Fehler!");
        
    let zahl1:f32 = zahl1.trim().parse().unwrap();
        let zahl2:f32 = zahl2.trim().parse().unwrap();
        
    add(zahl1,zahl2);
        min(zahl1,zahl2);
        multi(zahl1,zahl2);
        div(zahl1,zahl2);

}

Ausgabe Beispiel

image.png

Ok, Entschuldigung. Das ist ein Schwulst an Informationen. Vor allem relevant sind die Zeilen, bevor die Funktionsaufrufe ganz unten anfangen.
let zahl... Im Prinzip sind nur 2 Anweisungen wichtig.

.parse()

und

.unwrap()

parse ist dafür zuständig, die Benutzereingabe von String in diesem Fall in Floats zu verwandeln. Im übrigen ist parse speziell für die Umwandlung von Benutzereingaben gemacht worden. unwrap hat die Aufgabe, die Informationen von parse zu extrahieren und zu verwerten. unwrap werden wir im späteren Verlauf noch gelegentlich zu Gesicht bekommen.

Zusammenfassung

use std::io;

fn add (a:f32,b:f32) -> f32{
    let result = a+b;
    println!("Addition:\n{} + {} = {}",a,b,result);
        result
}

fn min (a:f32,b:f32) -> f32{
    let result = a-b;
    println!("Subtraktion:\n{} + {} = {}",a,b,result);
        result
}

fn multi (a:f32,b:f32) -> f32{
    let result = a*b;
    println!("Multiplikation:\n{} + {} = {}",a,b,result);
        result
}

fn div (a:f32,b:f32) -> f32{
    let result = a/b;
    println!("Division:\n{} + {} = {}",a,b,result);
        result
}

fn main (){
    println!("Bitte gib deinen Text ein:");
    let mut var_benutzereingabe = String::new();
    io::stdin().read_line(&mut var_benutzereingabe).expect("Fehler!");
    let var_benutzereingabe = var_benutzereingabe.trim();
    println!("Du hast folgendes eingegeben: {}", var_benutzereingabe);

    let mut zahl1 = String::new();
    println!("Bitte gib die erste Zahl ein");
    io::stdin().read_line(&mut zahl1).expect("Fehler!");
    let mut zahl2 = String::new();
    println!("Bitte gib die zweite Zahl ein");
    io::stdin().read_line(&mut zahl2).expect("Fehler!");
        let zahl1:f32 = zahl1.trim().parse().unwrap();
        let zahl2:f32 = zahl2.trim().parse().unwrap();
        add(zahl1,zahl2);
        min(zahl1,zahl2);
        multi(zahl1,zahl2);
        div(zahl1,zahl2);
}


Vom Editor

17.png

0.05171121 BEE
0 comments