====== std.io ====== Ergänzungen zur Konsolenausgabe: zeilenbrechende Varianten der Ausgabe-Builtins, Umwandlung von Wahrheitswerten und Fließkommazahlen in Text, formatierte Ausgabe über typisierte ''Printf…''-Funktionen und ein benannter Prozessabbruch. → [[lyx_-_programmiersprache:units:string|std.string]] · [[lyx_-_programmiersprache:sprache:exit-codes|Exit-Codes]] · [[lyx_-_programmiersprache:units|Standard Library]] Alle Beispiele dieser Seite sind mit ''lyxc 1.0.21A'' übersetzt und ausgeführt; die gezeigten Ausgaben sind echte Programmausgaben. > **Für die Grundausgabe braucht es diese Unit nicht.** ''Print'', ''PrintLn'', ''PrintStr'', ''PrintInt'', ''PrintFloat'', ''PrintBool'', ''PrintF64'' und ''IntToStr'' sind **Compiler-Builtins** und ohne jeden ''import'' verfügbar. Frühere Fassungen dieser Seite führten sie als Funktionen von ''std.io'' — das stimmt nicht; die Unit definiert nur ''Print'' als Hülle um das Builtin ''PrintStr''. > > ''StrToInt'' gehört ebenfalls nicht hierher, sondern zu [[lyx_-_programmiersprache:units:string|std.string]]. // Builtins: kein Import noetig fn main(): int64 { Print("ohne Zeilenumbruch, "); PrintLn("mit Zeilenumbruch"); PrintInt(42); PrintLn(""); PrintF64(3.5); PrintLn(StrConcat("Zahl als Text: ", IntToStr(42))); return 0; } ohne Zeilenumbruch, mit Zeilenumbruch 42 3.500000 Zahl als Text: 42 ---- ===== Was die Unit beisteuert ===== ^ Signatur ^ Beschreibung ^ | ''Print(s: pchar): void'' | Hülle um das Builtin ''PrintStr'' — ohne Zeilenumbruch | | ''PrintStrLn(s: pchar): void'' | Text mit Zeilenumbruch | | ''PrintIntLn(n: int64): void'' | Ganzzahl mit Zeilenumbruch | | ''PrintFloatLn(x: f64): void'' | Fließkommazahl mit Zeilenumbruch (sechs Nachkommastellen) | | ''PrintBoolLn(b: bool): void'' | ''true'' / ''false'' mit Zeilenumbruch | | ''BoolToStr(b: bool): pchar'' | ''true'' / ''false'' als Text | | ''FloatToStr(val: f64, prec: int64): pchar'' | Fließkommazahl mit gewählter Stellenzahl — **liefert falsche Werte, siehe Kasten** | | ''ExitProc(code: int64): void'' | Namensalias für das Builtin ''exit()'' | ''PrintIntLn'' und ''PrintStrLn'' waren früher als Builtin registriert, aber in keinem Backend umgesetzt — der Aufruf bestand die Semantikprüfung und scheiterte erst im Codegen. Seither leben sie hier. ''ExitProc'' beendet den Prozess sofort; unter Linux zählen nur die unteren acht Bit des Codes (→ [[lyx_-_programmiersprache:sprache:exit-codes|Exit-Codes]]). ---- ===== Zahlen als Text ===== > **''FloatToStr'' gibt für die meisten Werte eine falsche Zahl aus** — nicht ungenau, sondern falsch ([[https://github.com/SEOLizer/LyX-Compiler/issues/1430|#1430]]): > > ^ Aufruf ^ Ergebnis ^ richtig wäre ^ > | ''%%FloatToStr(5.02, 2)%%'' | ''5.1'' | ''5.02'' | > | ''%%FloatToStr(1.05, 2)%%'' | ''1.4'' | ''1.05'' | > | ''%%FloatToStr(0.07, 2)%%'' | ''0.6'' | ''0.07'' | > | ''%%FloatToStr(7.001, 3)%%'' | ''7.0'' | ''7.001'' | > | ''%%FloatToStr(12.3, 2)%%'' | ''12.29'' | ''12.30'' | > > Ursache: Der Nachkommateil wird als ganze Zahl gerechnet und **ohne führende Nullen** ausgegeben; zusätzlich wird abgeschnitten statt gerundet. Aus 5,02 € werden so 5,10 €, ohne dass irgendetwas auffällt. > > **Bis das behoben ist:** Für Geldbeträge in Festkomma rechnen (''int64'' × 100) und die Nachkommastellen selbst zusammensetzen. Für Anzeigezwecke ist das Builtin ''PrintF64'' die bessere Wahl — es gibt sechs Stellen aus und schneidet nur die letzte ab (''5.019999'' statt ''5.020000''). Ein Wert und wachsende Stellenzahl zeigt das Muster: FloatToStr(20.1, 1) -> 20.0 richtig: 20.1 FloatToStr(20.1, 2) -> 20.9 richtig: 20.10 FloatToStr(20.1, 3) -> 20.99 richtig: 20.100 Richtig behandelt werden dagegen die Sonderfälle: ''inf'' und ''nan'' liefern seit #1284 genau diese Wörter statt Zahlenmüll, und der Zielpuffer ist kein String-Literal mehr. ---- ===== Formatierte Ausgabe ===== Lyx kennt keine variadischen Funktionen. Statt eines einzigen ''Printf'' gibt es deshalb **eine Funktion je Argumentmuster**, benannt nach den Typen: ''S'' für ''pchar'', ''I'' für ''int64'', ''F'' für ''f64'', ''B'' für ''bool''. ^ Argumente ^ Verfügbare Muster ^ | eines | ''PrintfS'', ''PrintfI'', ''PrintfF'', ''PrintfB'' | | zwei | ''PrintfSS'', ''PrintfSI'', ''PrintfIS'', ''PrintfII'', ''PrintfIF'', ''PrintfFF'' | | drei | ''PrintfSSS'', ''PrintfSIS'', ''PrintfISI'', ''PrintfIII'', ''PrintfFFF'' | | vier | ''PrintfSSSS'', ''PrintfIIII'', ''PrintfISIF'' | Alle liefern die Zahl der ausgegebenen Zeichen zurück. ^ Platzhalter ^ Bedeutung ^ | ''%s'' | nächstes Argument | | ''%d'' | nächstes Argument | | ''%f'' | nächstes Argument | | ''%%%%'' | ein Prozentzeichen | > **''%s'', ''%d'' und ''%f'' sind gleichwertig.** Die Umwandlung in Text erledigt die aufgerufene ''Printf…''-Variante anhand ihres Namens, bevor der Formatkern die Argumente sieht — dieser setzt sie nur noch der Reihe nach ein. Ein ''%d'' an der Stelle eines Textarguments ist also kein Fehler, sondern liefert denselben Text. Maßgeblich ist die **Reihenfolge**, nicht der Buchstabe. > > Ein **unbekannter Platzhalter** wird wörtlich ausgegeben: ''%q'' erscheint als ''%q''. Feldbreiten, Genauigkeit und Flags (''%5d'', ''%.2f'', ''%-10s'') gibt es nicht. import std.io; import std.string; fn main(): int64 { // Aus der Unit: Zeilenbrechende Varianten und Umwandlungen PrintStrLn("PrintStrLn haengt den Umbruch an"c); PrintIntLn(42); PrintFloatLn(2.5); PrintBoolLn(true); PrintLn(StrConcat("BoolToStr(false): ", BoolToStr(false))); // Formatierte Ausgabe: der Name nennt die Argumenttypen var n: int64 := PrintfSI("Nutzer %s hat %d Punkte\n"c, "anna"c, 42); PrintLn(StrConcat(" ausgegebene Zeichen: ", IntToStr(n))); PrintfII("%d + %d\n"c, 2, 3); PrintfS("Prozent: 100%% fertig\n"c, ""c); PrintfS("Unbekannter Platzhalter: %q\n"c, "x"c); return 0; } PrintStrLn haengt den Umbruch an 42 2.500000 true BoolToStr(false): false Nutzer anna hat 42 Punkte ausgegebene Zeichen: 26 2 + 3 Prozent: 100% fertig Unbekannter Platzhalter: %q > **''__PrintfCore'' schreibt in ein String-Literal.** Der Formatkern gibt jedes Zeichen einzeln aus und benutzt dafür das Literal ''%%" "%%'' als Ein-Byte-Puffer — dieselbe Klasse, die in dieser Datei schon zweimal Fehler verursacht hat (#1259, #1260; in ''FloatToStr'' mit #1284 behoben). Heute geht es gut, weil der Datenbereich beschreibbar ist; sobald Literale schreibgeschützt liegen, stürzt jeder ''Printf…''-Aufruf ab ([[https://github.com/SEOLizer/LyX-Compiler/issues/1431|#1431]]). > > Nebenwirkung heute schon: ein Syscall je ausgegebenem Zeichen. Für größere Ausgaben ist ''StrConcat'' + ''PrintLn'' schneller. > > ''__PrintfCore'' ist zudem ''pub'' und taucht deshalb in der Schnittstelle auf, obwohl der Name sie als intern kennzeichnet. ---- ===== Wann was ===== ^ Aufgabe ^ Empfehlung ^ | Text ausgeben | ''PrintLn'' / ''Print'' (Builtins) | | Zahl anhängen | ''%%StrConcat(text, IntToStr(n))%%'' | | Fließkommazahl anzeigen | ''PrintF64'' (Builtin) — **nicht** ''FloatToStr'' | | Geldbetrag ausgeben | Festkomma (''int64'' × 100) und Nachkommastellen selbst setzen | | Zeile mit mehreren Werten | ''Printf…'' passend zur Argumentfolge | | Viel Text am Stück | in einem Puffer sammeln, einmal ausgeben | | Programm beenden | ''exit()'' (Builtin) oder ''ExitProc'' | ---- ===== Fallstricke ===== * **''FloatToStr'' nicht für Zahlen verwenden, die stimmen müssen** ([[https://github.com/SEOLizer/LyX-Compiler/issues/1430|#1430]]). * **''prec = 0'' liefert trotzdem einen Dezimalpunkt**: ''%%FloatToStr(2.5, 0)%%'' ergibt ''2.0''. * **Der Name der ''Printf…''-Variante muss zur Argumentfolge passen** — es gibt keine Prüfung zur Übersetzungszeit, ob Formatstring und Argumentzahl zusammenpassen. Mehr Platzhalter als Argumente bleiben schlicht leer. * **Keine Feldbreiten und keine Genauigkeit** in Formatstrings; für Ausrichtung selbst mit Leerzeichen auffüllen. * **Nicht jedes Argumentmuster existiert.** Für Kombinationen außerhalb der Tabelle (etwa ''pchar'', ''f64'', ''pchar'') die Werte vorher in Text umwandeln und ''PrintfSSS'' nehmen. * **''Print'' der Unit und ''Print'' des Compilers** tragen denselben Namen; nach ''import std.io'' ruft man die Hülle, ohne Import das Builtin. Verhalten ist identisch. * **Keine Ausgabe auf stderr**, keine Pufferung, kein Zeilenumbruch-Handling für Windows — alles geht ungepuffert nach stdout. ---- **Weiterführend:** [[lyx_-_programmiersprache:units:string|std.string — StrConcat, IntToStr, StrToInt]] · [[lyx_-_programmiersprache:units:fs|std.fs — Dateien lesen und schreiben]] · [[lyx_-_programmiersprache:sprache:exit-codes|Exit-Codes]] · [[lyx_-_programmiersprache:units|Standard Library]] **Quelle:** ''std/io.lyx'' (315 Zeilen) · **Autor:** Andreas Röne · **Copyright:** 2024–2025 Andreas Röne Letzte Aktualisierung: 2026-08-13 — Seite gegen ''std/io.lyx'' überarbeitet. Die Funktionsliste nannte ''PrintStr'', ''PrintInt'', ''PrintFloat'', ''PrintBool'' und ''IntToStr'' als Bestandteile der Unit — es sind **Compiler-Builtins**; ''StrToInt'' gehört zu ''std.string''. Neu: zwei lauffähige Beispiele mit echter Ausgabe, Übersicht der ''Printf…''-Muster samt Platzhalter-Verhalten, Entscheidungstabelle, Fallstricke. Belegt und als Issue erfasst: ''FloatToStr'' liefert falsche Zahlen ([[https://github.com/SEOLizer/LyX-Compiler/issues/1430|#1430]]), ''__PrintfCore'' schreibt in ein String-Literal und ist fälschlich ''pub'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1431|#1431]]). Geprüft mit ''lyxc 1.0.21A''.