Hallo Welt, die Fehler behandelt

9

Schreiben Sie ein Programm oder eine Funktion mit den folgenden Funktionen:

  • Das Programm / die Funktion versucht zunächst, die Zeichenfolge Hello, world!in den Standardausgabestream zu schreiben . (Für diese Herausforderung sind keine anderen Ausgabeformen akzeptabel, da der Schwerpunkt eher auf der E / A als auf dem trivialen Verhalten des Programms selbst liegt.) Je nachdem, ob es erfolgreich war:
    • Wenn die Ausgabe erfolgreich war Hello, world!, wird das Programm / die Funktion ohne weiteres Verhalten beendet.
    • Wenn aufgrund eines Fehlers nicht die richtige Ausgabe erstellt werden konnte, versucht das Programm / die Funktion, die Zeichenfolge Error writing "Hello, world!"in den Standardfehlerstrom zu schreiben . (Für die Zwecke dieser Herausforderung benötigen Sie keine Fehlerbehandlung für die Fehlerbehandlung selbst.)

Klarstellungen

  • Ihr Programm / Ihre Funktion wird ohne Eingabe ausgeführt (es sei denn, es ist in einer Sprache geschrieben, für deren Eingabe unbedingt eine Eingabe erforderlich ist. In diesem Fall wird es mit der einfachstmöglichen Eingabe ausgeführt).

  • Wenn Sie eine Ausgabe erstellen, können Sie auf Wunsch auch eine einzelne nachfolgende neue Zeile erstellen. Dies ist jedoch nicht obligatorisch.

  • Die Definition von "Fehler beim Schreiben in die Standardausgabe", die Ihr Programm implementiert, muss mindestens die folgenden Fälle als Fehler behandeln:

    • Die Standardausgabe ist nicht vorhanden (dh es stdouthandelt sich um ein geschlossenes Dateihandle, es existiert kein Dateideskriptor 1, oder diese Fälle werden jedoch in die von Ihnen verwendete Sprache und das verwendete Betriebssystem übersetzt).
    • Standardausgabe bezieht sich auf eine Datei auf einer Festplatte, auf der kein freier Speicherplatz mehr vorhanden ist.
    • Standardausgang, der eine Verbindung zu einem anderen Programm herstellt, dessen Verbindungsende bereits geschlossen wurde.

    und muss mindestens die folgenden Fälle als Erfolg behandeln (dh keinen Fehler):

    • Die Standardausgabe wird an ein Terminal angeschlossen und auf dem Hello, world!Bildschirm angezeigt.
    • Die Standardausgabe stellt eine Verbindung zu einer Datei her und Hello, world!wird in die Datei geschrieben.

    Sie können die Details auswählen, die als Ausgabefehler gelten, sofern dies mit den oben genannten Regeln übereinstimmt.

  • Ihr Programm / Ihre Funktion sollte nicht abstürzen, wenn eine der oben aufgeführten Fehlersituationen auftritt. Es liegt an Ihnen, welchen Exit-Code Sie verwenden.

  • Ihr Programm / Ihre Funktion sollte nicht die Art des aufgetretenen Fehlers im Standardfehlerstrom beschreiben. Es sollte nur die oben angegebene Zeichenfolge gedruckt werden. Eine externe Ausgabe bei Standardfehlern (z. B. Compiler-Warnungen) ist nur zulässig, wenn sie bedingungslos erzeugt wird, unabhängig davon, ob ein Fehler auftritt oder nicht.

  • Ihr Programm muss nur auf einem Betriebssystem funktionieren (obwohl es eines sein muss, auf dem die oben aufgeführten Fehler sinnvoll sind; ich habe versucht, sie allgemein genug zu halten, um auf den meisten Multitasking-Consumer-Betriebssystemen zu funktionieren, aber seltsamere Betriebssysteme können es auch sein von dieser Herausforderung ausgeschlossen). Wenn Ihr Programm nicht portierbar ist, listen Sie die Annahmen, die es ausführen muss, im Titel Ihrer Einreichung auf.

  • Diese Aufgabe ist möglicherweise nicht in jeder Sprache möglich (nicht in jeder Sprache kann ein Programm Ausgabefehler auf benutzerdefinierte Weise behandeln). Sie müssen eine Sprache auswählen, in der dies möglich ist.

  • Stellen Sie sicher, dass Ihr Programm / Ihre Funktion funktioniert! Vertrauen Sie nicht nur der Dokumentation von Bibliotheksfunktionen, um das zu tun, was sie sagen. Die Fehlerbehandlung einfacher Ausgabefunktionen stellt sich in der Praxis häufig als fehlerhaft heraus, selbst wenn die Funktionen behaupten, Fehler theoretisch zu behandeln.

Testfälle

Hier ist eine Möglichkeit, die oben genannten Fehlerbedingungen unter bashLinux zu simulieren (Sie müssen Linux nicht verwenden, aber es ist wahrscheinlich das einfachste System, auf dem dies getestet werden kann):

your_program_here >&-           # nonexistent stdout
your_program_here > /dev/full   # out of disk space
mkfifo test  # note: change "test" to a filename that isn't in use
true < test &
your_program_here > test        # connecting to a program that doesn't want input
rm test      # clean up the FIFO we used earlier

Die ersten beiden Testfälle sind deterministisch. Das letzte ist nicht (es hängt von einer Rennbedingung ab); Zu Testzwecken empfehle ich, eine Verzögerung zwischen dem Start Ihres Programms und der tatsächlichen Ausgabe zur Standardausgabe hinzuzufügen, um sicherzustellen, dass die Rennbedingung auf die Weise behoben wird, die den Fehler aufdeckt.

Siegbedingung

Dies ist eine Herausforderung, also ist kürzer besser. Wie (fast) immer messen wir die Länge des Programms in Bytes.


quelle
1
Wissen Sie, ob es eine Möglichkeit gibt, dies unter Windows zu testen? Ich kann das erste Kriterium testen, aber nicht den Teil, in dem die Festplatte voll ist ...
Stewie Griffin
Könnten Sie verwenden, um die Rennbedingungen zu verringern sleep 1 < test; (sleep 2; your_program_here) > test?
Neil
Verwandte
JayCe

Antworten:

6

Bash , 71 60 Bytes

h=Hello,\ world!
(echo $h)2>&-||echo Error writing \"$h\">&2

Probieren Sie es online aus!

Wie es funktioniert

Nach dem Speichern Hello, world!in der Variablen h gehen wir wie folgt vor.

Erstens, (echo $h)2>&-zu drucken versucht Hello, world!zu STDOUT. 2>&-ist erforderlich, um zu verhindern, dass die Fehlermeldung echo angezeigt wird: Schreibfehler: Ungültiger Dateideskriptor, falls der Schreibvorgang fehlschlägt. Da das Schreiben in eine Named Pipe, die keine Eingaben akzeptiert, das Bash-Programm mit Signal 13 (SIGPIPE) beenden würde, führen wir den Befehl in einer Subshell ( (...)) aus, sodass nur die Subshell beendet wird.

Wenn das Drucken nach STDOUT fehlgeschlagen ist, wird die Unterschale mit einem Statuscode ungleich Null beendet (141 für SIGPIPE, 1 für einen generischen Fehler), sodass echo Error writing \"$h\">&2die gewünschte Nachricht an STDERR gedruckt wird.

Dennis
quelle
2

Python 2 , 65 Bytes

h='Hello, world!'
try:print h
except:exit('Error writing "%s"'%h)

Durch Drucken von einfachen Anführungszeichen können zwei Bytes gespeichert werden.

Probieren Sie es online aus!

Dennis
quelle
1

Zsh , 55 Bytes

h=Hello,\ world!
2>&-<<<$h||<<<'Error writing "'$h\">&2

Im Gegensatz zu seinem Cousin Bash weigert sich Zsh, wegen eines Rohrbruchs zu sterben.

Probieren Sie es online aus!

Dennis
quelle
1

C (gcc) , 87 86 Bytes

f(){signal(13,1);write(1-puts("Hello, world!"),"Error writing \"Hello, world!\"",29);}

Probieren Sie es online aus!

Ungolfed

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void f(void)
{
    signal(SIGPIPE, SIG_IGN); // Works (and is required) on TIO. YMMV
    int fd = (puts("Hello, world!")) < 0 ? 2 : -13;
    write(fd, "Error writing \"Hello, world!\"", 29);
}
Dennis
quelle
Woher weißt du, was die Rendite bringt? hier sagt nur es ist> = 0 für alles in
Ordnung
putsGibt die Anzahl der geschriebenen Bytes oder -1 im Fehlerfall zurück, sodass entweder 14 (Hello World plus Newline) oder -1 zurückgegeben wird . (Das mag plattformspezifisch sein, aber so verhält es sich mit glibc.)
Dennis
K & R2 sagt, dass es EOF [-1 praticly] zurückgibt, wenn Fehler; oder ein Wert nicht negativ, wenn alles in
Ordnung ist
1
In PPCG werden Sprachen durch ihre Implementierung definiert, und gcc / glibc verhalten sich so, wie ich es gesagt habe.
Dennis
Ich bevorzuge das alte Buch
RosLuP
1

PowerShell, 80 Byte

try{echo($h="Hello, World!") -ea 4}catch{$host.ui|% *rL* "Error writing ""$h"""}

erklärt:

try{
    #Attempt to 'echo' (write output) the string, and assign it to $h
    #Make sure the 'error action' is set to '4' to make it a terminating error.
    echo($h="Hello, World!") -ea 4
} catch { 
    #Use the "WriteErrorLine" function in $host.ui to stderr
    $host.ui|% *rL* "Error writing ""$h"""
}

Ich habe es nicht geschafft, dies tatsächlich zu versuchen, wenn es fehlerhaft ist, aber es sollte definitiv funktionieren.

colsw
quelle
Die Fehlermeldung sollte in STDERR geschrieben werden . Das Schreiben in STDOUT ist nicht möglich, wenn beim ersten Schreibversuch ein Fehler auftritt.
Dennis
@ Tennis danke dafür, dort aktualisiert, die Frage nicht vollständig gelesen.
Colsw
Afaict PowerShell fängt nur schwerwiegende Ausnahmen ab, die Sie benötigen Write-Host -ErrorAction Stopoder so etwas. Außerdem throwerzeugt das neben der zu druckenden Zeile eine zusätzliche Debugging-Information, die übrigens ein W in Kleinbuchstaben und doppelte Anführungszeichen um die HW-Zeichenfolge haben sollte.
Dennis
@ Tennis die zusätzlichen Debug-Informationen haben mich zerquetscht, Antwort dort jetzt aktualisiert.
Colsw
1

Javascript, 79 76 Bytes

try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}
Matthew Roh
quelle
Beachten Sie, dass die Zeichenfolge, die Sie ausgeben sollten 'Hello, world!', ein Byte länger ist als die von Ihnen verwendete. Außerdem würde die Zuweisung ainnerhalb des Aufrufs console.logkürzer sein (1B) und das Entfernen des Semikolons nach dem l.log(a)Speichern eines weiteren Bytes.
Luke
@ Luke Danke, das war ein ziemlich großer Fehler!
Matthew Roh
1
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}für 76 Bytes. Zuerst consolewird zugewiesen l, dann "Hello, world!'wird zugewiesen aund dann wird es ausgeführt.
Luke
0

Perl 5, 51 Bytes

erfordert -M5.01, was kostenlos ist

say$h="Hello, world!"or die"Error writing \"$h\"$/"

Getestet in Strawberry Perl 5.24.0 durch Ausführen des Programms wie es ist (gedruckt auf Standardausgabe) und durch Ausführen

print f $h="Hello, world!"or die"Error writing \"$h\"$/"

(auf Standardfehler gedruckt). Ich weiß nicht, wie ich mit Strawberry auf andere Fehler testen soll, aber sie sollten gleich behandelt werden.

msh210
quelle
Soweit ich das beurteilen kann, funktioniert das nicht. tio.run/nexus/bash#jY3NDoIwEITvfYq1IXCiiD83ys3Ei2/… (Der String fehlt auch ein Komma.)
Dennis
Ich weiß nicht, was ich von dieser Seite halten soll, auf die Sie verlinkt haben. Kannst du bitte erklären? Beachten Sie außerdem, dass das Skript nur auf einem Betriebssystem ausgeführt werden muss. Und ich werde das Komma hinzufügen; Vielen Dank.
msh210
Die Ausgabe sollte Hello, world!nach === 1 ===und nichts nach den anderen angezeigt werden . Das Debuggen sollte nach === 1 ===und Error writing "Hello, world!"nach den anderen nichts anzeigen . Ich bin mir bewusst, dass Ihr Programm nicht mit TIO arbeiten muss, sondern print f...die beabsichtigten Fehlermeldungen anzeigt, während das ursprüngliche Programm dies nicht tut.
Dennis
"Output" und "Debug" zeigen meines Erachtens beide nichts an. Ich weiß auch nicht, wie die Abschnitte "Kopfzeile" und "Fußzeile" aussehen sollen. TIO ist mir völlig unbekannt, aber beachten Sie, dass Strawberry Perl unter MS Windows ausgeführt wird.
msh210
Hut ab vor Dennis für die Idee, den String in einer Variablen zu speichern (obwohl ich wahrscheinlich daran gedacht hätte, wenn ich ihn dort nicht gesehen hätte).
msh210
0

REXX, 111 106 Bytes

signal on notready
a='Hello, world!'
_=lineout(,a)
exit
notready:_=lineout('stderr','Error writing "'a'"')

Das Programm setzt voraus, dass es einen Stream namens 'stderr' gibt. Dies wird auf IBM-Systemen wahrscheinlich nicht der Fall sein.

Idrougge
quelle
0

C 77 Bytes

f(a){a="Error writing \"Hello, world!\"";write(1,a+15,13)-13&&write(2,a,29);}

für einen Anruf

main(){f(1); return 0;}
RosLuP
quelle
Auf welcher Plattform haben Sie das getestet? Unter Linux funktioniert es nicht, wenn ein Rohrbruch auftritt.
Dennis
0

R 91 Bytes

s="Hello, world!"
tryCatch(cat(s),error=function(e)cat('Error writing "','"',file=2,sep=s))

Probieren Sie es online aus!

Ich habe versucht, es zu korrigieren, indem ich es mit cat(s,file=12)anstelle von ausgeführt habe cat(s), und es gibt den richtigen Text an stderr aus. Dies ist invalid connectionansonsten ein Fehler.

JayCe
quelle
Irgendeine Idee, wie man auf andere Ausgabefehler testet?
JayCe