Systemnahe Programmierung mit Rust
The Book: https://doc.rust-lang.org/book
Letzter Update: 2024-01-18
Wie legt man ein neues Projekt P an?
cargo create P
cargo make P
cargo new P
cargo build
Welche Dateien wurden generiert, nachdem man mit cargo
ein neues Projekt erzeugt, aber noch nicht gebaut hat?
Wie nennt man das Format des Cargo Konfigurationsfiles?
Wo muss sich die Datei ex1.rs
befinden, damit das
folgende Kommando funktioniert:
cargo run --example ex1
Projekt/src/ex1.rs
Projekt/bin/ex1.rs
In Projekt/examples/ex1.rs
Module kann man auch in src/bin/
ablegen. Wie kann man
diese zu ausführbaren Dateien kompilieren?
Wie legt man ein Bibliotheks-Crate mit cargo
an?
Was gibt cargo --list
aus?
cargo
KommandosWie kann man herausfinden, ob es ein Update der Rust Toolchain gibt?
Wie installiert man ein Update der Rust “stable” Toolchain?
Sie möchten ein kurzes eigenständiges Programm in der Quelltextdatei
programm.rs
direkt mit dem Rust Compiler kompilieren und
ausführen. Welche Schritte auf der Kommandozeile sind nötig?
Nennen Sie zwei verschiedene Kommandozeilenaufrufe, um den Rust Quelltext zu formatieren.
Wie macht man einen “Release-Build”?
cargo release
cargo build --release
CARGO_RELEASE=1 cargo build
Wie findet man heraus, welche Rust Toolchains installiert sind und welches die gerade aktive Toolchain ist?
Wie nennt man “Funktionsaufrufe”, die ein Ausrufezeichen ! am Ende
haben, z.B. println!()
oder format!()
?
Wie nennt man die Art Funktion, die wie im folgenden Beispiel durch
::
auf einem Typ (String
) aufgerufen wird?
let mut guess = String::new();
Wie liest man ganz elementar von der Standardeingabe einen String ein?
Ist die Erzeugung von Zufallszahlen in der Rust Standardbibliothek oder benötigt man eine externe Bibliothek (Crate), wenn ja welche?
Wozu dient die Cargo.lock
Datei?
Wie kann man prinzipiell die Abhängigkeiten eines Programms auf neuere Versionen aktualisieren?
Wie prüft man in Rust typischerweise eine Variable, ob sie einen von mehreren vorgegebenen Werten hat? Man kann auch sagen, man prüft, ob ein bestimmtes Muster erfüllt wird.
Aussage: Falls ein Array maximal 256 Elemente gross ist, dann kann
ich es mit einem Index vom Typ u8
indizieren.
Welche Bedeutung hat der Typ usize
?
Wie viele Bytes umfasst der “char” Datentyp?
Beschreiben Sie den Unterschied zwischen b'a'
und
b"a"
?
(hinzugefügt am 2024-12-05)
Wie schreibt man ein Literal vom char
Typ?
Kann ich eine Variable i
vom Datentyp i32
in einen Typ f32
umwandeln?
Welches Ergebnis kommt bei 72 / 10
in Rust heraus?
Welcher Datentyp wird bei folgender Zeile voreingestellt für
f
verwendet?
let f = 3.14;
Geben Sie drei verschiedene Schreibweisen an, wie man die folgende
Zeile ändern kann, so dass explizit der Typ u8
für
j
verwendet wird.
let j = 255;
let j : u8 = 255; let j = 255u8; let j = 255_u8; –>
Wie kann man in Rust numerische Werte lesbarer schreiben?
Ordnen Sie die Datentypen zu:
let u = ();
let w = "Hallo";
let x = [4, 9, 1, 0, 6, 2];
let y = (4, 9, 1, 0, 6, 2);
let z = &x[2..4];
_________
_________
_________
In welchem Speicherbereich liegen die folgenden Variablen und Konstanten?
let u = 42;
let v = [3, 2, 1];
let w = vec![3, 2, 1];
let x = "Hallo".to_string();
let y = &x;
let z: &'static str = "Rust";
static S: u64 = 1;
static mut G: u32 = 42;
const C: i32 = 42;
_____________
_____________
_____________
_____________
____________
Was passiert bei dem folgenden Programm?
fn main() {
let v: Vec<i32> = vec![];
let i = v[0];
}
v[0]
wird in i
kopiert i
ist zum Schluss ein Err(None)
enthalten Welcher Typ wird von v.get(n)
zurückgeliefert, wenn
v
ein Vektor vom Typ Vec<u64>
ist.
n
ist vom Typ usize
.
u64
Result<T, E>
Option<T>
Some(u64)
Welche der folgenden Datentypen können Elemente mit unterschiedlichen Typen beinhalten?
Was wird ausgegeben?
let hello = "Здравствуйте";
println!("{:?}", hello.chars().nth(1).unwrap());
Aus welchen 3 Bestandteilen besteht s
?
let s: String::from("Augsburg");
Aus welchen 2 Bestandteilen besteht t
?
let s: String::from("Augsburg");
let t: &s[4..];
Welchen Wert hat die Variable x
nach der Zeile (2) und
nach der Zeile (3)?
let gerade = true;
let x = if gerade { 2 } else { 3 }; // (2)
let x = if gerade { 2; } else { 3; }; // (3)
Als Platzhalter bei print-Anweisungen wird oft einer der Folgenden
verwendet: {}
, {:?}
, {:#?}
. Wie
unterscheiden sie sich?
Kann man in Rust eine globale Konstante definieren, z.B.
let PI = 3.1415;
. Wie müsste man die Zeile schreiben,
damit es funktioniert?
Auf Typen wie u8
kann man durch ::
getrennt
Funktionen aufrufen, z.B.:
u8::max_value()
Welche Möglichkeiten gibt es, um solche Funktionen für eigene Typen zu definieren?
Was muss an den folgenden Stellen eingetragen werden, damit das Beispiel funktioniert?
let ___ a : i32 = 42;
fn add_one_ref(arg : ___ i32) -> () {
*arg += 1;
}
;
add_one_ref(___ a)println!("{}", a);
Kann man einfach schreiben “if zahl {…}”, so wie in C, d.h. haben die Zahlen auch boolsche Wahrheitswerte?
Muss die Schleifenvariable i
in Zeile (1) definiert
werden oder kann man auf diese Zeile verzichten?
let mut i = 0; // (1)
for i in 0..6 {
println!("{}", i);
}
Welche Kommentare können in einem Programm vorkommen?
// Kommentar a
# Kommentarzeile b
/* Kommentar c */
/*
/* Kommentar d */
*/
Wie viele Leerzeichen werden typischerweise bei der Formatierung des Quelltextes für eine Einrückung verwendet?
Wenn ein Block nur eine Zeile lang ist, darf man dann die Klammern weglassen, so wie in C?
let b = 1;
if b
println!("b is true"0);
Wie nennt man Zeilen im Programmtext, die wie in folgendem Beispiel aussehen:
#[allow(unused_variables)]
Nennen Sie die drei Ownership-Regeln.
Nennen Sie die Regeln für Referenzen.
In einem Code-Abschnitt möchte ich folgende zwei Zeilen nacheinander
ausführen. Die Variable r
ist der Rückgabewert von
std::io::stdin().read_line(&mut guess)
:
println!("{:?}", r.expect("Fehler aufgetreten."));
println!("{:?}", r.unwrap());
Wird das so klappen?
Korrigieren Sie den Fehler in folgendem Programm ohne eine Zeile zu löschen.
struct Test {
: Vec<i32>,
list: i32,
a}
impl Test {
pub fn new() -> Self {
{
Test : vec![1, 2, 3, 4, 5, 6, 7],
list: 0,
a}
}
pub fn run(&mut self) {
for i in self.list.iter() {
self.do_something(*i)
}
}
pub fn do_something(&mut self, n: i32) {
self.a = n;
}
}
(hinzugefügt am 2024-12-05)
Wie nennt man folgende Strukturdefinition?
struct Point(i32, i32);
Ist eine leere Strukturdefinition erlaubt?
struct Empty;
Definieren Sie auf der Struktur Rechteck
eine Methode
flaeche(???) -> ???
, welche die Fläche des Rechtecks
zurückgibt. Den Übergabeparameter und den Rückgabewert wählen Sie
sinnvoll (siehe Platzhalter ???). Erzeugen Sie eine Instanz
r
des Rechteck und rufen Sie die Methoden auf.
struct Rechteck {
: f32,
breite: f32
hoehe}
Demonstrieren Sie die Struct Update Syntax an Hand eines Beispiels.
(hinzugefügt am 2024-12-05)
Kann man auch auf Enums so wie auf Structs mit impl
Funktionen definieren?
(hinzugefügt am 2024-12-05)
Wie kann man den folgenden Code kürzer schreiben?
let config_max = Some(3u8);
match config_max {
Some(max) => println!("The maximum is configured to be {}", max),
=> (),
_ }
Ergänzen Sie den folgenden Code damit in der for
Schleife die Daten ausgegeben werden, die in den Enum-Varianten
stecken.
enum Message {
{ x: i32, y: i32 },
Move String),
Output(i32, i32, i32),
ChangeColor(}
fn main() {
let m = Message::Move { x: 5, y: 15 };
let o = Message::Output("Hallo".to_string());
let c = Message::ChangeColor(10, 20, 30);
for x in [m, o, c] {
// ...
}
}
(hinzugefügt am 2024-12-05)
Markieren Sie die richtigen Aussagen über ein Package.
Cargo.toml
Datei.–> Was macht das super
Schlüsselwort?
Markieren Sie alle Möglichkeiten, wie f2()
in der Zeile
(x) aufgerufen werden kann.
mod omod {
fn f2() {
// ...
}
pub mod imod {
pub fn f() {
// (x)
}
}
}
omod::f3();
super::f3();
crate::omod::f3();
In einem Unit Test test1()
möchten Sie direkt
f1()
ausführen. Welche der use
Anweisungen an
der Stelle (x) sind richtig?
fn f1() { ... }
#[cfg(test)]
mod tests {
// (x)
#[test]
fn test1() {
;
f1()}
}
use crate::f1
use super::f1
use super::*
Wenn man die beiden folgenden use
Anweisungen verwendet,
dann ist der Name Event
nicht mehr eindeutig. Welche der
folgenden Aussagen sind richtig?
use crate::mod1::Event;
use crate::mod2::Event;
use crate::mod1::Event as Event1;
use crate::mod1
und dann mod1::Event
verwendenWie fügt man einem Package das externe Crate rand
als
Abhängigkeit hinzu? Welche Aussagen sind wahr?
Cargo.lock
um rand
erweiternrustup install rand
[dependencies]
in Cargo.toml
erweitern um rand = "0.5";
Wie kann man einen neuen Vektor mit Werten vorbelegen und einer Variablen zuordnen?
Macht es Sinn, wenn man einen String mit einem numerischen Wert indiziert um damit das Zeichen an der entsprechenden Stelle zu bekommen? Mit kurzer Begründung.
Wie iteriert man durch einen String von Zeichen zu Zeichen?
Was passiert beim Aufruf von panic!("Hallo Leute")
?
Was passiert wenn bei der Ausführung der Funktion
read_file()
die Datei testfile.txt
nicht
vorhanden ist?
fn read_file() -> Result<(), io::Error> {
let f = File::open("testfile.txt");
Ok(())
}
panic!()
wird erzeugt.read_file()
kehrt mit einem
io::Error()
zurück.f
ist eine Err(...)
Instanz und die
read_file()
kehrt mit Ok(())
zurück.Wie lassen sich die folgenden mit (x) markierten Zeilen einsparen?
fn read_file() -> Result<(), io::Error> {
let f = File::open("testfile.txt");
let f = match f { // (x)
Err(_) => panic!(), // (x)
Ok(f) => f, // (x)
}; // (x)
...
Nennen Sie eine Varianten von unwrap()
, die keine
panic!
auslöst, sondern eine Closure als Argument erwartet,
die im Fehlerfall ausgeführt wird.
Welche Aussagen zum ?
Operator sind richtig?
?
-Operator funktioniert nur bei
Result<T, E>
, nicht bei
Option<T>
.from()
Funktion im
From
Trait aufgerufen, um die Fehlertypen bei Bedarf
anzupassen.?
-Operator erzeugt eine panic!
, wenn
der zurückgegebene Fehler nicht mit dem Rückgabewert der umschliessenden
Funktion zusammenpasst.Was können Trait-Definitionen enthalten?
Nennen Sie alle Traits, die man mit derive
automatisch
erzeugen lassen kann.
(hinzugefügt am 2024-12-05)
Implementieren Sie für eine selbstgewählte Struktur den
Display
Trait.
(hinzugefügt am 2024-12-05)
Was ist eine assoziierte Funktion?
(hinzugefügt am 2024-12-05)
Ist der Datentyp &T
ein Copy-Typ? Bitte mit kurzer
Begründung!
(hinzugefügt am 2024-12-05)
Wie kann man Tests mit cargo
und rustc
ausführen?
Kopieren Sie den folgenden Code in das Textfeld und füllen Sie die punktierten Bereich mit funktionierendem Code aus.
#[........]
mod tests {
use ........;
#[.....]
fn cnt_test() {
let sum = cnt(); // sum expected to be 42
assert_eq!(...., ....);
}
}
Schreiben Sie eine Closure mit Argument x
und geben Sie
als Rückgabewert x+1
zurück. Weisen Sie diese Closure einer
Variablen c
zu.
Wie nennt man das Konstruct das als Argument von dem folgenden
unwrap_or_else()
verwendet wird:
|error| { panic!("...") }); unwrap_or_else(
Nennen Sie drei unterschiedliche Methoden um über einen Vektor zu iterieren.
Nennen Sie drei Iterator Adaptoren ihrer Wahl
Nennen Sie drei Iterator Konsumenten ihrer Wahl
Wie würden Sie einen Iterator für einen selbstgemachten Datentyp definieren? Nur in Stichpunkten.
Welcher Wert kommt bei der folgenden Verkettung heraus?
let c = Counter::new(); // Iterator: 1, 2, 3, 4, 5
.zip(Counter::new().skip(1))
c.map(|(a, b)| a * b)
.filter(|x| x % 3 == 0)
.sum()
XXX TODO: Hier werden noch einige Fragen zu
Box<T>
, Deref
Trait, Drop
Trait, Rc<T>
, RefCell<T>
kommen!.
Wie kann man eine Variable der folgenden Datenstruktur auf dem Heap anlegen?
struct Circle {
center: (f32, f32),
radius: f32
}
let c = Box::new(Circle { center: (1.0, 4.0), radius: 5.0 });
let c = malloc(Circle { center: (1.0, 4.0), radius: 5.0 });
let c = Rc::new(RefCell::new(Circle { center: (1.0, 4.0), radius: 5.0}));
Benutzt Rust in der Standardbibliothek die Threads des Betriebssystems oder wird ein eigener Thread-Scheduler in der Rust Runtime verwendet?
Wie kann man einen Thread für eine bestimmte Zeit schlafen legen?
Mit welchen Mitteln können Threads untereinander kommunizieren?
Wofür steht “mpsc”?
Wie kann das Hauptprogramm warten, bis alle vorher erzeugten Threads beendet wurden?
Kann man Methoden nur auf Strukturen (struct) definieren, oder kann man das auf beliebigen Datentypen machen?
struct
.Wie wir die in der objektorientierten Programmierung übliche Methodenauswahl zur Laufzeit in Rust erzielt?
In der objektorientierten Programmierung gibt es Beziehungen zwischen Klassen, so dass eine Instanz der Klasse A (Typ A) auch eine Instanz der Klasse B (Typ B) ist. Wie werden diese Beziehungen in Rust realisiert?