Hola mundo que maneja errores

9

Escriba un programa o función con la siguiente funcionalidad:

  • El programa / función primero intenta escribir la cadena Hello, world!en la secuencia de salida estándar. (No se aceptan otras formas de salida para este desafío, ya que el enfoque se centra principalmente en la E / S y no en el comportamiento trivial del programa en sí mismo). Dependiendo de si tuvo éxito:
    • Si tuvo éxito en la salida Hello, world!, el programa / función se cierra sin ningún comportamiento adicional.
    • Si no pudo producir la salida correcta debido a un error, el programa / función intenta escribir la cadena Error writing "Hello, world!"en la secuencia de error estándar. (Para los propósitos de este desafío, no necesita manejo de errores para el manejo de errores en sí).

Aclaraciones

  • Su programa / función se ejecutará sin entrada (a menos que esté escrito en un lenguaje que requiera absolutamente entrada para funcionar, en cuyo caso se ejecutará con la entrada más simple posible).

  • Al producir resultados, también puede producir una nueva línea final si lo desea, pero hacerlo no es obligatorio.

  • La definición de "error al escribir en la salida estándar" que implementa su programa debe tratar al menos los siguientes casos como errores:

    • La salida estándar no stdoutexiste ( es decir, es un identificador de archivo cerrado, no existe un descriptor de archivo 1 o, sin embargo, esos casos se traducen al idioma y al sistema operativo que está utilizando);
    • Salida estándar que se refiere a un archivo en un disco que no tiene espacio libre restante;
    • Salida estándar que se conecta a otro programa, que ya ha cerrado su final de la conexión.

    y debe tratar al menos los siguientes casos como exitosos (es decir, no como un error):

    • La salida estándar se conecta a un terminal y Hello, world!se muestra en la pantalla.
    • La salida estándar se conecta a un archivo y Hello, world!se escribe en el archivo.

    Puede elegir los detalles de lo que cuenta como un error de salida, siempre que sea coherente con las reglas anteriores.

  • Su programa / función no debe bloquearse al encontrar cualquiera de las situaciones de error enumeradas anteriormente. Depende de usted qué código de salida usa.

  • Su programa / función no debe describir la naturaleza del error encontrado en la secuencia de error estándar; solo debe imprimir la cadena especificada anteriormente. El resultado extraño en un error estándar (p. Ej., Advertencias del compilador) solo es legal si se produce incondicionalmente, independientemente de si se encuentra un error o no.

  • Su programa solo necesita funcionar en un sistema operativo (aunque debe ser uno en el que los errores enumerados anteriormente tengan sentido; he tratado de mantenerlos lo suficientemente generales como para funcionar en la mayoría de los sistemas operativos de consumo multitarea, pero los sistemas operativos más extraños pueden ser excluidos de este desafío). Si su programa no es portátil, enumere las suposiciones que necesita ejecutar en el título de su envío.

  • Es posible que esta tarea no sea posible en todos los idiomas (no todos los idiomas permiten que un programa maneje errores de salida de forma personalizada). Tendrás que elegir un idioma donde sea posible.

  • ¡Asegúrese de que su programa / función funcione! No solo confíe en la documentación de las funciones de la biblioteca para hacer lo que dicen que hacen. El manejo de errores de funciones de salida simples a menudo se rompe en la práctica, incluso si las funciones afirman manejar errores en teoría.

Casos de prueba

Aquí hay una manera de simular cada una de las condiciones de error anteriores usando bashLinux (no es necesario que use Linux, pero es probable que sea el sistema más fácil para probar esto):

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

Los dos primeros casos de prueba son deterministas. El último no es (se basa en una condición de carrera); Para fines de prueba, recomiendo agregar un retraso entre el inicio de su programa y la salida real a la salida estándar, para garantizar que la condición de carrera se resuelva de la manera que expone el error.

Condición de victoria

Este es un desafío de , por lo que más corto es mejor. Como (casi) siempre, estamos midiendo la longitud del programa en bytes.


fuente
1
¿Sabes si hay una manera de probar esto en Windows? Puedo probar el primer criterio, pero no la parte de que el disco esté lleno ...
Stewie Griffin
Para reducir la condición de carrera, ¿podrías usar sleep 1 < test; (sleep 2; your_program_here) > test?
Neil
Relacionado
JayCe

Respuestas:

6

Bash , 71 60 bytes

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

Pruébalo en línea!

Cómo funciona

Después de guardar Hello, world!en la variable h , hacemos lo siguiente.

Primero, (echo $h)2>&-intenta imprimir Hello, world!en STDOUT. 2>&-es necesario para evitar mostrar el mensaje de error echo: error de escritura: descriptor de archivo incorrecto en caso de que falle la escritura. Dado que escribir en una tubería con nombre que no acepta entrada mataría al programa Bash con la señal 13 (SIGPIPE), ejecutamos el comando en una subshell ( (...)), por lo que solo se matará la subshell.

Finalmente, si la impresión en STDOUT falló, la subshell saldrá con un código de estado distinto de cero (141 para SIGPIPE, 1 para un error genérico), por lo que echo Error writing \"$h\">&2imprime el mensaje deseado en STDERR.

Dennis
fuente
2

Python 2 , 65 bytes

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

Se pueden guardar dos bytes imprimiendo comillas simples.

Pruébalo en línea!

Dennis
fuente
1

Zsh , 55 bytes

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

A diferencia de su primo Bash, Zsh se niega a morir debido a una tubería rota.

Pruébalo en línea!

Dennis
fuente
1

C (gcc) , 87 86 bytes

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

Pruébalo en línea!

Sin golf

#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
fuente
¿Cómo sabes lo que pone el retorno? aquí dice que es> = 0 para estar bien ...
RosLuP
putsdevuelve el número de bytes que se han escrito o -1 en caso de error, por lo que devuelve 14 (Hello World más nueva línea) o -1 . (Eso puede ser específico de la plataforma, pero así es como se comporta con glibc.)
Dennis
K & R2 dice que devuelve EOF [-1 practicamente] si se produce un error; o un valor no negativo si todo está bien
RosLuP
1
En PPCG, los idiomas se definen por su implementación, y gcc / glibc se comportan como dije.
Dennis
prefiero el libro antiguo
RosLuP
1

PowerShell, 80 bytes

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

explicado:

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

no he logrado probar esto cuando falla, pero definitivamente ~ debería ~ funcionar.

colsw
fuente
El mensaje de error debe escribirse en STDERR . No es posible escribirlo en STDOUT si se produce un error durante el primer intento de escritura.
Dennis
@ Dennis gracias por eso, actualizado allí, no leyó la pregunta por completo.
colsw
Afaict PowerShell solo detecta excepciones fatales, por lo que necesitarías Write-Host -ErrorAction Stopo algo así. Además, throwproduce una información de depuración adicional aparte de la línea que debe imprimir, que por cierto debe tener una W minúscula y comillas dobles alrededor de la cadena HW.
Dennis
@Dennis, la información de depuración adicional me ha aplastado, la respuesta actualizada allí ahora.
colsw
1

Javascript, 79 76 bytes

try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}
Matthew Roh
fuente
Tenga en cuenta que la cadena que debe generar es 'Hello, world!', que es un byte más larga que la que usa. Además, supongo que asignar adentro de la llamada a console.logsería más corto (1B) y eliminar el punto y coma después de l.log(a)guardar otro byte.
Lucas
@Luke Gracias, ¡fue un gran error!
Matthew Roh el
1
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}por 76 bytes. Primero, consolese asigna a l, luego "Hello, world!'se asigna a a, y luego se ejecuta.
Lucas
0

Perl 5, 51 bytes

requiere -M5.01, que es gratis

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

Probado en Strawberry Perl 5.24.0 ejecutando el programa tal cual (impreso en la salida estándar) y ejecutando

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

(impreso al error estándar). No sé cómo probar otros errores usando Strawberry, pero deberían manejarse de la misma manera ...

msh210
fuente
Por lo que puedo decir, esto no funciona. tio.run/nexus/bash#jY3NDoIwEITvfYq1IXCiiD83ys3Ei2/… (A la cadena también le falta una coma.)
Dennis
No sé qué hacer con esa página a la que vinculaste; ¿Puedes explicar, por favor? Además, tenga en cuenta que el script solo debe funcionar en un sistema operativo. Y agregaré la coma; Gracias.
msh210
La salida debería aparecer Hello, world!después === 1 ===y nada después de los demás. La depuración no debe mostrar nada después === 1 ===y Error writing "Hello, world!"después de los demás. Soy consciente de que su programa no tiene que funcionar en TIO, pero print f...muestra los mensajes de error previstos mientras que el programa original no lo hace.
Dennis
"Output" y "Debug" no muestran nada por lo que veo. Tampoco sé qué se supone que son las secciones "Encabezado" y "Pie de página". Y no estoy completamente familiarizado con TIO, pero tenga en cuenta que Strawberry Perl se ejecuta en MS Windows.
msh210
Un consejo para Dennis por la idea de almacenar la cadena en una variable (aunque probablemente habría pensado en ello si no la hubiera visto allí).
msh210
0

REXX, 111 106 bytes

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

El programa se basa en que haya una secuencia llamada 'stderr'. Este probablemente no será el caso en los sistemas IBM.

idrougge
fuente
0

C, 77 bytes

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

para llamar

main(){f(1); return 0;}
RosLuP
fuente
¿En qué plataforma probaste esto? No funciona en Linux si se encuentra una tubería rota.
Dennis
0

R , 91 bytes

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

Pruébalo en línea!

Intenté equivocarlo ejecutándolo con en cat(s,file=12)lugar de cat(s), e imprime el texto correcto en stderr. Esto es un invalid connectionerror de lo contrario.

JayCe
fuente
¿Alguna idea de cómo probar otros errores de salida?
JayCe