Ciao mondo che gestisce gli errori


9

Scrivi un programma o una funzione con le seguenti funzionalità:

  • Il programma / funzione tenta innanzitutto di scrivere la stringa Hello, world!nel flusso di output standard. (Nessun'altra forma di output è accettabile per questa sfida, poiché l'attenzione è focalizzata sull'I / O piuttosto che sul comportamento banale del programma stesso.) A seconda che abbia avuto successo:
    • Se l'output è riuscito Hello, world!, il programma / funzione esce senza ulteriori comportamenti.
    • Se non è riuscito a produrre l'output corretto a causa di un errore, il programma / funzione tenta di scrivere la stringa Error writing "Hello, world!"nel flusso di errori standard. (Ai fini di questa sfida, non è necessaria la gestione degli errori per la stessa gestione degli errori.)

chiarimenti

  • Il tuo programma / funzione verrà eseguito senza input (a meno che non sia scritto in una lingua che richiede assolutamente l'input per funzionare, nel qual caso verrà eseguito con l'input più semplice possibile).

  • Quando si produce output, è anche possibile produrre una nuova riga finale se si desidera, ma farlo non è obbligatorio.

  • La definizione di "errore nella scrittura nell'output standard" implementata dal programma deve trattare almeno i seguenti casi come errori:

    • L'output standard è inesistente (ovvero stdoutè un filehandle chiuso, non esiste alcun descrittore di file 1 o comunque quei casi si traducono nella lingua e nel sistema operativo in uso);
    • Output standard riferito a un file su un disco a cui non è rimasto spazio libero;
    • Uscita standard che si collega a un altro programma, che ha già chiuso la sua fine della connessione.

    e deve trattare almeno i seguenti casi come un successo (ovvero non un errore):

    • L'output standard si collega a un terminale e Hello, world!viene visualizzato sullo schermo.
    • L'output standard si collega a un file e Hello, world!viene scritto nel file.

    Puoi scegliere i dettagli di ciò che conta come un errore di output, purché sia ​​coerente con le regole di cui sopra.

  • Il programma / funzione non deve arrestarsi in modo anomalo quando si verifica una delle situazioni di errore sopra elencate. Dipende da te quale codice di uscita usi.

  • Il programma / funzione non deve descrivere la natura dell'errore riscontrato sul flusso di errori standard; dovrebbe solo stampare la stringa sopra specificata. L'output esterno in caso di errore standard (ad es. Avvisi del compilatore) è legale solo se prodotto incondizionatamente, indipendentemente dal fatto che si verifichi o meno un errore.

  • Il tuo programma deve funzionare solo su un sistema operativo (anche se deve essere uno su cui hanno senso gli errori sopra elencati; ho cercato di mantenerli abbastanza generali da funzionare sulla maggior parte dei sistemi operativi consumer multitasking, ma i sistemi operativi più strani potrebbero essere escluso da questa sfida). Se il tuo programma non è portabile, elenca le ipotesi che deve essere eseguito nel titolo del tuo invio.

  • Questa attività potrebbe non essere possibile in tutte le lingue (non tutte le lingue consentono a un programma di gestire gli errori di output in modo personalizzato). Dovrai scegliere una lingua dove è possibile.

  • Assicurati che il tuo programma / funzione funzioni! Non fidarti solo della documentazione delle funzioni di libreria per fare ciò che dicono di fare. La gestione degli errori di semplici funzioni di output risulta spesso interrotta in pratica, anche se le funzioni dichiarano di gestire gli errori in teoria.

Casi test

Ecco un modo per simulare ciascuna delle condizioni di errore sopra usando bashsu Linux (non devi usare Linux, ma è probabilmente il sistema più semplice su cui testarlo):

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

I primi due test sono deterministici. L'ultimo non lo è (dipende da una condizione di gara); a scopo di test, consiglio di aggiungere un ritardo tra l'inizio del programma e l'output effettivo all'output standard, al fine di garantire che le condizioni di gara vengano risolte nel modo in cui si espone l'errore.

Condizione di vittoria

Questa è una sfida per il , quindi più breve è meglio. Come (quasi) sempre, stiamo misurando la lunghezza del programma in byte.


1
Sai se c'è un modo per testarlo su Windows? Posso testare il primo criterio, ma non la parte relativa al disco pieno ...
Stewie Griffin

Per ridurre le condizioni di gara, potresti usare sleep 1 < test; (sleep 2; your_program_here) > test?
Neil,

Risposte:


6

Bash , 71 60 byte

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

Provalo online!

Come funziona

Dopo aver salvato Hello, world!nella variabile h , facciamo quanto segue.

Innanzitutto, (echo $h)2>&-tenta di stampare Hello, world!su STDOUT. 2>&-è necessario per impedire la visualizzazione del messaggio di errore echo: errore di scrittura: descrittore di file errato nel caso in cui la scrittura fallisca. Dato che scrivere su una pipe denominata che non accetta input ucciderebbe il programma Bash con il segnale 13 (SIGPIPE), eseguiamo il comando in una subshell ( (...)), quindi solo la subshell verrà uccisa.

Infine, se la stampa su STDOUT non è riuscita, la subshell uscirà con un codice di stato diverso da zero (141 per SIGPIPE, 1 per un errore generico), quindi echo Error writing \"$h\">&2stampa il messaggio desiderato su STDERR.


2

Python 2 , 65 byte

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

Due byte possono essere salvati stampando virgolette singole.

Provalo online!


1

Zsh , 55 byte

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

A differenza di suo cugino Bash, Zsh si rifiuta di morire a causa di un tubo rotto.

Provalo online!


1

C (gcc) , 87 86 byte

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

Provalo online!

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);
}

come fai a sapere cosa mette il ritorno? qui dice solo che è> = 0 per essere tutto ok ...
RosLuP

putsrestituisce il numero di byte che sono stati scritti o -1 in caso di errore, quindi restituisce 14 (Hello World più newline) o -1 . (Potrebbe essere specifico per la piattaforma, ma è così che si comporta con glibc.)
Dennis

K & R2 dice che restituisce EOF [-1 praticamente] in caso di errore; o un valore non negativo se tutto ok
RosLuP

1
Su PPCG, i linguaggi sono definiti dalla loro implementazione e gcc / glibc si comportano come ho detto.
Dennis,

preferisco il vecchio libro
RosLuP

1

PowerShell, 80 byte

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

ha spiegato:

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"""
}

non sono riuscito a provare effettivamente questo quando si verificano errori, ma sicuramente ~ dovrebbe ~ funzionare.


Il messaggio di errore deve essere scritto su STDERR . Scriverlo su STDOUT non è possibile se si verifica un errore durante il primo tentativo di scrittura.
Dennis,

@Dennis grazie, aggiornato lì, non ho letto completamente la domanda.
Colsw,

Afaict PowerShell rileva solo eccezioni fatali, quindi ne avresti bisogno Write-Host -ErrorAction Stopo qualcosa del genere. Inoltre, throwproduce ulteriori informazioni di debug oltre alla riga che dovrebbe stampare, che tra l'altro dovrebbe avere una W minuscola e doppie virgolette attorno alla stringa HW.
Dennis,

@Dennis le informazioni di debug aggiuntive mi hanno schiacciato, risposta aggiornata lì adesso.
Colsw,

1

Javascript, 79 76 byte

try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}

Nota che la stringa che dovresti generare è 'Hello, world!', che è un byte più lunga di quella che usi. Inoltre, suppongo che assegnare aall'interno della chiamata console.logsarebbe più breve (1B) e rimuovere il punto e virgola dopo aver l.log(a)salvato un altro byte.
Luca,

@Luke Grazie, è stato un grosso errore!
Matthew Roh,

1
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}per 76 byte. Innanzitutto, consoleviene assegnato a l, quindi "Hello, world!'viene assegnato a a, quindi viene eseguito.
Luca,

0

Perl 5, 51 byte

richiede -M5.01, che è gratuito

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

Testato in Strawberry Perl 5.24.0 eseguendo il programma così com'è (stampato sullo standard output) ed eseguendolo

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

(stampato sull'errore standard). Non so come testare altri errori usando Strawberry, ma dovrebbero essere gestiti allo stesso modo….


Per quanto ne so, questo non funziona. tio.run/nexus/bash#jY3NDoIwEITvfYq1IXCiiD83ys3Ei2/… (La stringa manca anche una virgola.)
Dennis

Non so cosa fare di quella pagina a cui ti sei collegato; puoi spiegare, per favore? Inoltre, tieni presente che lo script deve funzionare su un solo sistema operativo. E aggiungerò la virgola; Grazie.
msh210,

L'output dovrebbe essere visualizzato Hello, world!dopo === 1 ===e niente dopo gli altri. Il debug non dovrebbe mostrare nulla dopo === 1 ===e Error writing "Hello, world!"dopo gli altri. Sono consapevole che il tuo programma non deve funzionare su TIO, ma print f...mostra i messaggi di errore previsti mentre il programma originale no.
Dennis,

"Output" e "Debug" non visualizzano entrambi nulla per quello che vedo. Inoltre non so quali dovrebbero essere le sezioni "Intestazione" e "Piè di pagina". E non ho familiarità con TIO, ma nota che Strawberry Perl funziona su MS Windows.
msh210,

Punta di cappello a Dennis per l'idea di archiviare la stringa in una variabile (anche se probabilmente ci avrei pensato se non l'avessi visto lì).
msh210,

0

REXX, 111 106 byte

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

Il programma si basa sull'esistenza di un flusso chiamato "stderr". Questo probabilmente non sarà il caso dei sistemi IBM.


0

C, 77 byte

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

per chiamata

main(){f(1); return 0;}

Su quale piattaforma hai provato questo? Non funziona su Linux se si incontra una pipe rotta.
Dennis,

0

R , 91 byte

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

Provalo online!

Ho provato a sbagliarlo eseguendolo con cat(s,file=12)invece di cat(s), e stampa il testo corretto su stderr. Questo è un invalid connectionerrore altrimenti.


Qualche idea su come testare altri errori di output?
JayCe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.