Das Betriebssystem stellt für ein Programm üblicherweise 3 Kanäle _(streams)_ zur Verfügung:
- Standardeingabekanal `stdin`
- Standardausgabekanal `stdout` und
- Standardfehlerausgabekanal `stderr`.
Wenn das Programm in einem Terminal (oder Konsole bzw. Shell) gestartet wird, kann das Programm über `stdin` die Tastatureingaben
einlesen und Ausgaben über `stdout` sowie `stdout` erscheinen im Terminal.
- Schreiben nach `stdout`: `print()`,`println()`,`printstyled()`
- Schreiben nach `stderr`: `print(strerr,...)`, `println(stderr,...)`, `printstyled(stderr,...)`
- Lesen von `stdin`: `readline()`
### Umwandeln von Strings in andere Typen:
- `chomp()` entfernt newline
- `split()` zerlegt in "Wörter"
- `parse()` wandelt in andere Typen um
### Eingaben
### Buffer
Die Sprache _Python_ stellt eine Funktion `input()` zur Verfügung:
```{.python}
ans = input("Bitte eine positive Zahl eingeben!")
```
Die Funktion gibt den Prompt aus, wartet auf eine Eingabe und liefert die
Eingabe als `string` zurück.
- `write`-Zugriffe werden gebuffert.
- `flush(stdout)` leert Buffer
In Julia kann man diese Funktion so implementieren:
```{julia}
function input(prompt = "Eingabe:")
println(prompt)
flush(stdout)
return chomp(readline())
end
```
**Anmerkungen**
- Schreibanweisungen werden von modernen Betriebssystemen gebuffert. Mit `flush(stdout)` wird die Leerung des Buffers und sofortige Schreiboperation erzwungen.
- `readline()` liefert einen String zurück, der mit einer Newline `\n` endet. Die Funktion `chomp()` entfernt einen eventuellen Zeilenumbruch vom Ende eines Strings.
```{julia}
#| eval: false
a = input("Bitte 2 Zahlen eingeben!")
```
```{julia}
#| echo: false
a = "34 56"
```
### Verarbeitung der Eingabe
> `split(str)` zerlegt einen String in "Wörter" und liefert einen _(array of strings)_:
```{julia}
av = split(a)
```
```{julia}
parse.(Int, av)
```
> `parse(T, str)` versucht, `str` in den Typ `T` umzuwandeln:
```{julia}
# Ausgaben auf den Fehlerkanal stderr erscheinen im Jupyter in rot:
@warn "Das @warn-Macro schreibt nach stderr."
println("Hallo!")
println(stderr, "Das sollte nicht passieren!")
v = parse.(Int, av)
```
`parse()` erzeugt einen Fehler, wenn der String sich nicht als Wertangabe von Typ `T` parsen lässt. Man kann den Fehler mit
`try/catch` abfangen oder die Funktion `tryparse(T, str)` verwenden, die in so einem Fall `nothing` zurückgibt - worauf man dann
z.B. mit `isnothing()` testen kann.
### Einzelne Tastenanschläge einlesen
- `readline()` u.ä. warten auf den Abschluss der Eingabe durch Drücken der `Enter`-Taste.
- Zum Einlesen einzelner _keystrokes_:
- Techniken zum Einlesen einzelner _keystrokes_ findet man hier:
Die Macros `@sprintf` und `@printf` sind den gleichnamigen C-Funktionen nachempfunden
- Formatstring: Normaler String mit Platzhaltern
- Platzhalter haben die Form
## Formatierte Ausgabe mit dem `Printf`-Makro
Oft möchte man Zahlen oder Strings mit einer strikten Formatvorgabe - Gesamtlänge, Nachkommastellen, rechts/linksbündig usw - ausgeben.
Dazu definiert das Paket `Printf` die Makros `@sprintf` und `@printf`, welche sehr ähnlich wie die gleichnamigen C-Funktionen arbeiten.
```{julia}
using Printf
x = 123.7876355638734
@printf("Ausgabe rechtsbündig mit max. 10 Zeichen Platz und 3 Nachkommastellen: x= %10.3f", x)
```
Das erste Argument ist ein String, der Platzhalter (hier: `%10.3`) für auszugebende Variablen enthält; gefolgt von diesen Variablen als weitere Argumente.
Platzhalter haben die Form
```
%[flags][width][.precision]type
```
(wobei die Angaben in eckigen Klammern alle optional sind)
- Typen:
```
%s string
%i integer
%o integer octal (base=8)
%x, %X integer hexadecimal (base=16) with digits 0-9abcdef or 0-9ABCDEF, resp.
%f floatong point number
%e floating point number, scientific representation
%g floating point, uses %f or %e depending on value
```
wobei die Angaben in eckigen Klammern alle optional sind.
- Flags:
```
Pluszeichen: rechtsbündig (Standard)
Minuszeichen: linksbündig
Null: mit führenden Nullen
```
**Typangaben im Platzhalter**
| | |
|:--|:------------|
|`%s`| `string`|
|`%i`| `integer`|
|`%o`| `integer octal (base=8)`|
|`%x, %X`| `integer hexadecimal (base=16) with digits 0-9abcdef or 0-9ABCDEF, resp.`|
|`%f`| `floating point number`|
|`%e`| `floating point number, scientific representation`|
|`%g`| `floating point, uses %f or %e depending on value`|
: {.striped .hover}
**Flags**
| | |
|:----|:-----|
|Pluszeichen| rechtsbündig (Standard)|
|Minuszeichen| linksbündig|
|Null| mit führenden Nullen|
: {.striped .hover}
**Width**
- Width:
```
Anzahl der minimal verwendeten Zeichen (wenn nötig, werden auch mehr genommen)
```
Zeit für Beispiele:
### Beispiele:
```{julia}
@ -130,6 +178,7 @@ using Printf # Paket laden nicht vergessen!
```{julia}
@printf("|%s|", "Hallo") # string mit Platzhalter für String
```
Die senkrechten Striche sind nicht Teil des Platzhalters. Sie sollen die Begrenzung des Ausgabefeldes anzeigen.
```{julia}
@ -144,7 +193,7 @@ using Printf # Paket laden nicht vergessen!
```{julia}
@printf("|%3s|", "Hallo") # Längenangabe kann überschritten werden
# besser eine 'kaputt formatierte' Tabelle als falsche Werte!!
# besser eine 'kaputt formatierte' Tabelle als falsche Werte!
```
@ -156,21 +205,21 @@ l = 3342678
@printf("j= %012i, k= %-12i, l = %12i", j, k, l) # 0-Flag für führende Nullen
```
`@printf` und `@sprintf` können wie alle Macros wie Funktionen aufgerufen werden:
`@printf` und `@sprintf` können wie alle Makros wie Funktionen aufgerufen werden:
```{julia}
@printf("%i %i", 22, j)
```
-- oder wie Macros, also ohne Funktionsklammern und ohne Komma:
-- oder wie Makros, also ohne Funktionsklammern und ohne Komma:
```{julia}
@printf "%i %i" 22 j
```
`@printf` kann als erstes Argument noch einen stream übergeben bekommen.
`@printf` kann als erstes Argument noch einen Stream übergeben bekommen.
Ansonsten besteht die Argumentliste aus
@ -183,7 +232,7 @@ Ansonsten besteht die Argumentliste aus
j, "(geschätzt)" ,k)
```
`@sprintf` druckt nichts, sondern liefert den ausgefüllten formatierten String zurück:
Das Makro `@sprintf` druckt nichts, sondern liefert den ausgefüllten formatierten String zurück:
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.