Palindrome-Finder: Rust-Programm zur Entdeckung rückwärts lesbaren Textes

Der Palindrome-Finder ist ein benutzerfreundliches Programm, das in einer Textdatei nach Wörtern sucht, die auch rückwärts gelesen einen Sinn ergeben. Die Idee hinter Palindromen ist faszinierend: Wörter wie “Otto” oder Sätze wie “Renate bittet Tibetaner” sind Beispiele für Texte, die in beide Richtungen gelesen denselben Sinn ergeben.

Das Programm benutzt clap zum Einlesen der Kommandozeilenargumente.

Ordnerstruktur

palindromefinder
├── Cargo.toml
├── src
│   └── main.rs

Cargo.toml

[package]
name = "palindromefinder"
version = "0.1.0"
edition = "2021"
description = "Findet Palindrome in Textdateien"

[dependencies]
clap = "3.2.25"

main.rs

use clap::{App, Arg};           // Importiere bestimmte Teile der clap-Bibliothek für die Verwendung
use std::collections::HashSet;  // Importiere die HashSet-Datenstruktur für eindeutige Wörter
use std::error::Error;          // Importiere das Error-Trait für Fehlerbehandlung
use std::fs::File;              // Importiere die File-Struktur für Dateioperationen
use std::io::{self, BufRead};   // Importiere IO-Module für Ein- und Ausgabe

fn main() {
    // Hauptfunktion, die das Programm startet
    
    // Versuche, die `run`-Funktion auszuführen
    if let Err(err) = run() {
        // Wenn ein Fehler auftritt, gib eine Fehlermeldung aus und beende das Programm mit einem Fehlercode
        eprintln!("Fehler: {}", err);
        std::process::exit(1);
    }
}

fn run() -> Result<(), Box<dyn Error>> {
    // Die `run`-Funktion, die den Hauptteil des Programms enthält

    // Definition der Kommandozeilenargumente mit Hilfe der `clap`-Bibliothek
    let matches = App::new(env!("CARGO_PKG_NAME")) // Programmname aus Cargo.toml
        .version(env!("CARGO_PKG_VERSION")) // Programmversion aus Cargo.toml
        .about(env!("CARGO_PKG_DESCRIPTION")) // Programm-Beschreibung aus Cargo.toml
        .author(env!("CARGO_PKG_AUTHORS")) // Autor(en) aus Cargo.toml
        .arg(
            Arg::new("inputfile")
                .help("Legt die Eingabedatei fest, die gelesen werden soll")
                .required(true) // Das Argument ist erforderlich
                .index(1), // Es handelt sich um das erste Argument nach dem Programmnamen
        )
        .arg(
            Arg::new("readme")
                .short('r') // Kurze Option: -r
                .long("readme") // Lange Option: --readme
                .help("Zeigt an, was das Programm macht"), // Beschreibung der Option
        )
        .get_matches(); // Verarbeite die Kommandozeilenargumente

    // Wenn die Option "--readme" angegeben ist, zeige eine Beschreibung des Programms und beende es
    if matches.is_present("readme") {
        println!("Dieses Programm findet in einer Textdatei Wörter, die auch rückwärts gelesen einen Sinn ergeben.");
        println!("Es gibt nur Wörter aus, die mindestens 3 Buchstaben haben und sortiert sie aufsteigend.");
        return Ok(()); // Beende das Programm erfolgreich
    }

    // Holen Sie den Namen der Eingabedatei aus den Kommandozeilenargumenten
    let eingabedatei_name = matches.value_of("inputfile").unwrap();

    // Versuche, die Eingabedatei zu öffnen
    let datei = match File::open(eingabedatei_name) {
        Ok(datei) => datei, // Wenn die Datei erfolgreich geöffnet wurde, fahre fort
        Err(err) => {
            if err.kind() == io::ErrorKind::NotFound {
                // Wenn die Datei nicht gefunden wurde, gib eine Fehlermeldung aus
                return Err(From::from(format!("Datei {} nicht gefunden", eingabedatei_name)));
            } else {
                // Andernfalls, wenn ein anderer Fehler auftritt, gib eine Fehlermeldung aus
                return Err(From::from(err));
            }
        }
    };

    // Erzeuge einen Pufferleser, um die Datei Zeile für Zeile zu lesen
    let leser = io::BufReader::new(datei);

    // Erzeuge eine leere Menge (HashSet), um eindeutige Wörter zu speichern
    let mut wort_set = HashSet::new();

    // Durchgehe die Eingabedatei Zeile für Zeile
    for zeile in leser.lines() {
        let wort = zeile?; // Zeile in ein Wort umwandeln; ? behandelt Fehler

        // Überprüfe, ob das Wort mindestens 3 Buchstaben hat
        if wort.len() > 2 {
            wort_set.insert(wort); // Füge das Wort zum Set hinzu
        }
    }

    // Konvertiere das Set in einen Vektor und sortiere ihn aufsteigend
    let mut sortierte_wörter: Vec<&String> = wort_set.iter().collect();
    sortierte_wörter.sort();

    // Durchgehe den sortierten Vektor und gib Wörter aus, die rückwärts gelesen einen Sinn ergeben
    for wort in sortierte_wörter {
        let umgekehrtes_wort: String = wort.chars().rev().collect();
        if wort_set.contains(&umgekehrtes_wort) {
            println!("{}", wort);
        }
    }

    Ok(()) // Beende das Programm erfolgreich
}

Siehe auch

Magische Buchstabenquadrate