EMZETT.
Login

Kurz: // Shadowing: neue Variable mit demselben Namen let x = 5; let x = x * 2; let x = format!(“{x} Stück”);

Teil des Kurses Rust

Kapitel 2 von 13 im Kurs Rust (Abschnitt „Grundlagen“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

fn main() {
    let name = "Mia";            // unveränderlich (Standard)
    let mut punkte = 0;          // veränderlich
    punkte += 10;
    let alter: u32 = 17;         // Typ ausdrücklich
    const MAX: u32 = 100;        // Konstante: immer Typ nötig
 
    // Shadowing: neue Variable mit demselben Namen
    let x = 5;
    let x = x * 2;
    let x = format!("{x} Stück");
 
    println!("{name} hat {punkte} Punkte, ist {alter}, Max {MAX}");
    println!("{x}");
    println!("{} + {} = {}", 3, 4, 3 + 4);
    println!("{:>6}|{:<6}|{:^6}|{:06.2}|{:#x}|{:#b}", "ab", "cd", "ef", 3.14159, 255, 5);
    println!("{0} {1} {0} {n}", "a", "b", n = 5);
    println!("{:?} {:?}", (1, "zwei"), vec![1, 2, 3]);
}

Ausgabe:

Mia hat 10 Punkte, ist 17, Max 100
10 Stück
3 + 4 = 7
    ab|cd    |  ef  |003.14|0xff|0b101
a b a 5
(1, "zwei") [1, 2, 3]
  • let legt eine Variable an, standardmäßig unveränderlich
  • let mut macht sie veränderlich
  • Shadowing (let x = ... erneut) legt eine neue Variable an, auch mit anderem Typ
  • {} gibt mit Display aus, {:?} mit Debug (für Entwickler), {name} setzt Variablen direkt ein

Datentypen

TypBeschreibung
i8 i16 i32 i64 i128 isizevorzeichenbehaftete ganze Zahlen (i32 Standard)
u8 u16 u32 u64 u128 usizevorzeichenlose; usize für Indizes und Größen
f32, f64Kommazahlen (f64 Standard)
booltrue / false
charein Unicode-Zeichen (4 Byte), in '...'
&strTextsicht (String-Slice), "..."
Stringwachsender, besitzender Text
()Einheitstyp (“nichts”)
(A, B)Tupel
[T; N]Array fester Länge
Vec<T>wachsende Liste
fn main() {
    let a: i32 = -42;
    let b: u8 = 255;
    let c = 3.14;              // f64
    let d = 'ß';
    let t = (500, 6.4, "x");   // Tupel
    let (x, y, z) = t;         // Destructuring
    let feld = [1, 2, 3, 4, 5];
    let nullen = [0; 4];
 
    println!("{a} {b} {c} {d} {} {} {} {}", t.0, x + 1, y, z);
    println!("{} {} {:?} {:?}", feld[0], feld.len(), nullen, &feld[1..3]);
    println!("{} {} {}", i32::MAX, u8::MAX, f64::EPSILON > 0.0);
    println!("{}", 7 / 2);          // 3: Ganzzahldivision
    println!("{}", 7.0 / 2.0);
    println!("{}", -7 % 3);
}

Ausgabe:

-42 255 3.14 ß 500 501 6.4 x
1 5 [0, 0, 0, 0] [2, 3]
2147483647 255 true
3
3.5
-1

Umwandlungen

Rust wandelt Zahlentypen nie automatisch um. Du schreibst as oder die From/TryFrom-Methoden:

fn main() {
    let i: i32 = 300;
    let f = i as f64 / 7.0;
    let klein = i as u8;              // schneidet ab: 300 -> 44 (Vorsicht!)
    let sicher = u8::try_from(i);     // Result: Fehler bei Überlauf
    let gross: i64 = i.into();        // verlustfreie Umwandlung
    println!("{f:.2} {klein} {:?} {gross}", sicher.is_err());
 
    let n: i32 = "42".parse().unwrap();
    let kaputt = "abc".parse::<i32>();
    println!("{} {:?}", n + 1, kaputt.is_err());
    println!("{}", 255u8.checked_add(1).is_none());     // Überlauf prüfen
    println!("{} {}", 250u8.wrapping_add(10), 250u8.saturating_add(10));
}

Ausgabe:

42.86 44 true 300
43 true
true
4 255

Im Debug-Modus bricht ein Ganzzahl-Überlauf (255u8 + 1) mit einer Panic ab; im Release-Modus läuft er um. Nutze checked_*, wrapping_* oder saturating_*, wenn du das Verhalten festlegen willst.

Strings: String und &str

fn main() {
    let literal: &str = "Hallo";            // fest im Programm, unveränderlich
    let mut s = String::from("Hallo");      // wächst
    s.push_str(", Welt");
    s.push('!');
    println!("{s} {} {}", s.len(), s.to_uppercase());
    println!("{} {} {:?}", s.contains("Welt"), s.replace("Hallo", "Servus"), s.find("Welt"));
    println!("{}", &s[0..5]);                // Teilstring (Bytes!)
    for (i, c) in "aß".chars().enumerate() { print!("{i}:{c} "); }
    println!();
    println!("{} {}", "ß".len(), "ß".chars().count());   // Bytes vs Zeichen
    let teile: Vec<&str> = "a,b,c".split(',').collect();
    println!("{teile:?} {}", teile.join("+"));
    let zusammen = format!("{literal}-{s}");
    println!("{zusammen} {}", literal.trim().is_empty());
}

Ausgabe:

Hallo, Welt! 12 HALLO, WELT!
true Servus, Welt! Some(7)
Hallo
0:a 1:ß
2 1
["a", "b", "c"] a+b+c
Hallo-Hallo, Welt! false

String besitzt seinen Text auf dem Heap, &str ist eine Sicht darauf. Funktionen nehmen meist &str als Parameter.

Merke

  • let (unveränderlich) und let mut; Shadowing legt neue Variablen an
  • Typen: i32, u8, f64, bool, char, &str, String, Tupel, Arrays, Vec<T>
  • Keine automatische Umwandlung zwischen Zahlentypen: as, into, try_from
  • {} Display, {:?} Debug, {name} Inline-Variablen
  • checked_*/wrapping_*/saturating_* steuern Überlaufverhalten

Übungsaufgabe

Wandle eine Temperatur in Celsius (f64) in Fahrenheit um und gib sie mit einer Nachkommastelle aus.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Was ist Rust?

Weiter: Bedingungen, Schleifen und match

Alle Kapitel: Rust im Überblick