Formatierte Ausgabe

Ausgabe-Makros

Rusts Druck-(Ausgabe-)Funktionalität wird durch eine Reihe von Makros im Modul std::fmt realisiert. Hier die Erklärung der gängigen Makros:

  • format! : Schreibt formatierten Text in eine Zeichenkette
  • print! : Gibt Inhalt auf der Konsole (Standardausgabe) aus
  • println! : Gleich wie print!, fügt automatisch einen Zeilenumbruch am Ende hinzu
  • eprint! : Gibt Inhalt auf den Standardfehlerstrom aus
  • eprintln! : Gleich wie eprint!, fügt automatisch einen Zeilenumbruch am Ende hinzu

Alle Makros mit der Endung ln fügen einen Zeilenumbruch hinzu, nach der Ausgabe wechselt die Zeile.

Das vorangestellte e steht für error und dient zur Ausgabe von Fehlermeldungen

Alle oben genannten Makros verwenden identische Formatierungssyntax, zudem prüft Rust zur Kompilierzeit, ob der Formatierungscode gültig ist.

Anwendungsbeispiele

Einfacher Platzhalter {}

{} ist ein universeller Platzhalter, er wird nacheinander durch die nachfolgend übergebenen Parameter ersetzt und automatisch zu einer Zeichenkette umgewandelt zur Ausgabe.

fn main() {
    println!("{} days", 31);
    // Ausgabe: 31 days
}Code-Sprache: JavaScript (javascript)

Positionsparameter

Gib innerhalb von {} einen numerischen Index (beginnend bei 0) an, um manuell festzulegen, welcher Parameter verwendet wird. Mehrfachverwendung und vertauschte Reihenfolge sind erlaubt.

fn main() {
    println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob");
    // Ausgabe: Alice, this is Bob. Bob, this is Alice
}Code-Sprache: JavaScript (javascript)

Wie am Beispiel ersichtlich müssen die Parameterindizes nicht der Reihenfolge 0 1 2 … folgen, sie können beliebig vertauscht werden. Die nachfolgenden Parameter „Alice“, „Bob“ erhalten jeweils den Index 0 und 1.

Benannte Parameter

Falls die Index-basierte Nutzung unübersichtlich ist, kannst du „benannte Parameter“ verwenden: Nutze {Parametername} in der Format-Zeichenkette und übergib Werte in der Form Parametername=Wert. Die Übergabereihenfolge spielt keine Rolle, die Lesbarkeit steigt deutlich.

fn main() {
    println!("{subject} {verb} {object}",
         object="the lazy dog",
         subject="the quick brown fox",
         verb="jumps over");
    // Ausgabe: the quick brown fox jumps over the lazy dog
}Code-Sprache: JavaScript (javascript)

Im Grunde gibst du den nachfolgenden Parametern einen Namen und kannst diesen per {Parametername} in der Format-Zeichenkette aufrufen – das ist deutlich intuitiver.

Basis-Formatierung (:Formatzeichen)

Mit einem : gefolgt von Formatzeichen im Platzhalter lassen sich Zahlen in Binär-, Oktal- und Hexadezimalsystem sowie weitere Basen umwandeln.

  • :b : Binär
  • :o : Oktal
  • :x : kleines Hexadezimal
fn main() {
    println!("Dezimal:    {}",   69420);    // 69420
    println!("Binär:    {:b}", 69420);    // 10000111100101100
    println!("Oktal:    {:o}", 69420);    // 207454
    println!("Hex:      {:x}", 69420);    // 10f2c
}Code-Sprache: JavaScript (javascript)

Breitenausrichtung und Auffüllung

1 Rechtsausrichtung (>Breite)

{:>n} bedeutet eine Gesamtbreite von n, der Inhalt wird rechtsbündig dargestellt, links mit Leerzeichen aufgefüllt.

fn main() {
    println!("{number:>5}", number=1);
    // Gesamtbreite 5, 4 Leerzeichen links → Ausgabe:    1
}Code-Sprache: JavaScript (javascript)
2 Null-Auffüllung bei Ausrichtung

Füge vor dem Ausrichtungszeichen eine 0 hinzu, um Lücken statt mit Leerzeichen mit der Ziffer 0 aufzufüllen.

  • :0>5 : Rechtsbündig, links mit Nullen auffüllen
  • :0<5 : Linksbündig, rechts mit Nullen auffüllen
fn main() {
    println!("{number:0>5}", number=1); // Rechtsbündig, Nullen auffüllen → 00001
    println!("{number:0<5}", number=1); // Linksbündig, Nullen auffüllen → 10000
}Code-Sprache: JavaScript (javascript)

Du kannst beliebige andere Zeichen statt 0 verwenden. Das nachfolgende Beispiel füllt links mit dem Großbuchstaben A auf

fn main() {
    println!("{number:A>5}", number=1); // Rechtsbündig, A auffüllen → AAAA1
    println!("{number:A<5}", number=1); // Linksbündig, A auffüllen → 1AAAA
}Code-Sprache: PHP (php)
3 Dynamische Breite (Variablenname$)

Die Breite wird nicht fest im Code hinterlegt, sondern per Variablenname$ auf externe benannte Parameter / Variablen verwiesen, um die Breite dynamisch zu steuern.

Das heißt: Die Breite lässt sich über eine Variable steuern, statt fest im Code geschrieben zu werden.

fn main() {
    // Variante 1: Kombination mit benannten Parametern
    println!("{number:0>width$}", number=1, width=8);

    // Variante 2: Direkter Verweis auf Code-interne Variablen (ab Rust 1.58 unterstützt)
    let number: f64 = 1.0;
    let width: usize = 8;
    println!("{number:>width$}"); // Ausgabe:    1
}Code-Sprache: JavaScript (javascript)

Parameterprüfung zur Kompilierzeit

Rust prüft zur Kompilierzeit, ob die Anzahl der Platzhalter mit der Anzahl übergebener Parameter übereinstimmt – fehlende Parameter führen direkt zu einem Kompilierfehler.

fn main() {
    // 2 Platzhalter, aber nur 1 Parameter übergeben → Kompilierung schlägt fehl
    println!("My name is {0}, {1} {0}", "Bond");
    // Korrektur: Parameter "James" ergänzen
    println!("My name is {0}, {1} {0}", "Bond", "James");
}Code-Sprache: JavaScript (javascript)

Kompilierhinweis: Die Position {1} ist ungültig, da nur ein einzelner Parameter übergeben wurde.

Fehler: Verweis auf nicht vorhandenen Positionsparameter 1 (es wurde nur 1 Parameter übergeben)
 --> D:\rustdemo\hello.rs:3:29
  |
3 |     println!("My name is {0}, {1} {0}", "Bond");
  |                                ^
  |
  = Hinweis: Positionsparameter beginnen mit der Nummer 0

Fehler: Kompilierung abgebrochen, insgesamt 1 FehlerCode-Sprache: JavaScript (javascript)

Einschränkungen bei der Formatierung eigener Typen

Standardmäßig lassen sich mit {} nur Typen formatieren, die das Trait fmt::Display implementieren. Eigene Structs implementieren dieses Trait nicht von Haus aus – direktes Ausgeben mit {} erzeugt einen Kompilierfehler.

fn main() {
    struct Structure(i32);
    // Der folgende Code kompiliert nicht
    println!("{}", Structure(3));
}Code-Sprache: JavaScript (javascript)
Fehler[E0277]: Der Struct `Structure` implementiert das Trait `std::fmt::Display` nicht
 --> D:\rustdemo\hello.rs:4:20
4 |     println!("{}", Structure(3));
  |               --   ^^^^^^^^^^^^ Dieser Typ kann nicht mit dem Standard-Formatter ausgegeben werden
  |               |
  |               Dieser Formatparameter erfordert, dass der Typ das Display-Trait implementiert

Hinweis: Der Struct `Structure` hat keine Implementierung von `std::fmt::Display`
 --> D:\rustdemo\hello.rs:2:2
2 |     struct Structure(i32);
  |     ^^^^^^^^^^^^^^^^

Zusatzhinweis: Versuche stattdessen im Formatstring {:?} (oder leserliches Pretty-Print mit {:#?}) zu verwenden
Kompilierung abgebrochen, 1 Fehler aufgetreten.

Zur Anzeige der Fehlerdetails führe den Befehl aus: rustc --explain E0277Code-Sprache: PHP (php)

* 1 Wenn du einen Struct ausgeben möchtest, musst du das Display-Trait implementieren (merke dir dies vorerst einfach, wir behandeln es später detailliert)

use std::fmt;

struct Structure(i32);

// Implementiere das Display-Trait für den Struct
impl fmt::Display for Structure {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // self.0 greift auf den i32-Wert im Tupel-Struct zu
        write!(f, "Wert: {}", self.0)
    }
}

fn main() {
    println!("{}", Structure(3));
}Code-Sprache: PHP (php)
* 2 Temporäres Debuggen → Debug-Format {:?} / {:#?} verwenden

Geeignet für Entwickler-Debugging: Wenn es keine Produktivumgebung ist und du nur prüfen möchtest, welche Werte im Struct gespeichert sind, nutze das Debug-Trait zum Debuggen

Rust implementiert das Debug-Trait standardmäßig für eigene Typen, du kannst sie mit {:?} ausgeben:

#[derive(Debug)]
#[allow(dead_code)] // Warnungen über ungenutzten Code/Felder unterdrücken
struct Structure(i32);

fn main() {
    println!("{:?}", Structure(3));
    println!("{:#?}", Structure(3));
}Code-Sprache: PHP (php)

* Zwei zentrale Formatierungs-Traits von std::fmt

Das Modul std::fmt enthält mehrere Traits zur Steuerung der Textanzeige, die zwei wichtigsten sind:

  1. fmt::Debug in Kombination mit dem Platzhalter {:?}, speziell für die Anzeige in Debug-Szenarien.
  2. fmt::Display in Kombination mit dem Platzhalter {}, gibt Inhalte in normierter, benutzerfreundlicher Form für Endnutzer aus.

Eingebaute Typen der Standardbibliothek haben beide Traits bereits implementiert und können direkt ausgegeben werden; eigene Typen funktionieren nicht sofort, du musst das entsprechende Trait manuell implementieren.

Wenn du für einen Typ fmt::Display implementierst, wird automatisch auch das Trait ToString mitimplementiert, um den Typ in eine Zeichenkette umwandeln zu können.

#[allow(dead_code)]

#[allow(dead_code)] ist ein Code-Attribut, das auf das direkt folgende Code-Element angewendet wird, um Warnungen über „ungenutzten Code“ zu unterdrücken.

Nehmen wir das obige Beispiel

fn main() {
    struct Structure(i32);
    // Der folgende Code kompiliert nicht
    //println!("{}", Structure(3));
}Code-Sprache: JavaScript (javascript)

Die zweite Zeile println!(„{}“, Structure(3)); erzeugt einen Fehler und ist daher auskommentiert. Wenn du den Code in diesem Zustand ausführst,

Warnung: Der Struct `Structure` wird niemals instanziiert
 --> D:\rustdemo\hello.rs:2:12
  |
2 |     struct Structure(i32);
  |            ^^^^^^^^^
  |
  = Hinweis: `#&#91;warn(dead_code)]` (Teil von `#&#91;warn(unused)]`) ist standardmäßig aktiviert

1 Warnung ausgegeben
Code-Sprache: JavaScript (javascript)

Diese Warnung erscheint, weil der Code struct Structure(i32); niemals verwendet wird. Wenn du diese Warnung unterdrücken möchtest, füge dieses Attribut hinzu

fn main() {
    #[allow(dead_code)] 
    struct Structure(i32);
    // Der folgende Code kompiliert nicht
    //println!("{}", Structure(3));
}Code-Sprache: PHP (php)
Nachkommastellen bei Gleitkommazahlen festlegen

Definiere eine Variable pi = 3.141592, schreibe einen formatierten Ausgabe-Code, der drei Nachkommastellen beibehält, gewünschte Ausgabe: Pi is roughly 3.142.

fn main() {
    let pi = 3.141592;
    println!("Pi is roughly {:.3}", pi);//3.142
    println!("Pi is roughly {0}", pi); //3.141592
}Code-Sprache: JavaScript (javascript)
Previous:

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert