Olá mundo que lida com erros

9

Escreva um programa ou função com a seguinte funcionalidade:

  • O programa / função tenta primeiro gravar a sequência Hello, world!no fluxo de saída padrão. (Nenhuma outra forma de saída é aceitável para esse desafio, pois o foco está muito na E / S, e não no comportamento trivial do próprio programa.) Dependendo do êxito:
    • Se conseguiu produzir Hello, world!, o programa / função sai sem nenhum comportamento adicional.
    • Se ele falhou em produzir a saída correta devido a um erro, o programa / função tenta gravar a sequência Error writing "Hello, world!"no fluxo de erros padrão. (Para os fins deste desafio, você não precisa da manipulação de erros para a própria manipulação de erros.)

Esclarecimentos

  • Seu programa / função será executado sem entrada (a menos que esteja escrito em um idioma que exija absolutamente entrada para funcionar, caso em que será executado com a entrada mais simples possível).

  • Ao produzir saída, você também pode produzir uma nova linha à direita, se desejar, mas isso não é obrigatório.

  • A definição de "gravação de erro na saída padrão" implementada pelo programa deve tratar pelo menos os seguintes casos como erros:

    • A saída padrão é inexistente (ou seja, stdouté um manipulador de arquivo fechado, não existe nenhum descritor de arquivo 1 ou, no entanto, esses casos são traduzidos para o idioma e o SO que você está usando);
    • Saída padrão referente a um arquivo em um disco que não tem espaço livre restante;
    • Saída padrão conectada a outro programa, que já fechou o final da conexão.

    e deve tratar pelo menos os seguintes casos como êxito (ou seja, não é um erro):

    • A saída padrão se conecta a um terminal e Hello, world!é exibida na tela.
    • A saída padrão se conecta a um arquivo e Hello, world!é gravada no arquivo.

    Você pode escolher os detalhes do que conta como erro de saída, desde que seja consistente com as regras acima.

  • Seu programa / função não deve falhar ao encontrar qualquer uma das situações de erro listadas acima. Depende de você o código de saída que você usa.

  • Seu programa / função não deve descrever a natureza do erro encontrado no fluxo de erros padrão; deve apenas imprimir a string especificada acima. A saída estranha em erro padrão (por exemplo, avisos do compilador) é válida apenas se produzida incondicionalmente, independentemente de um erro ser encontrado ou não.

  • Seu programa só precisa funcionar em um sistema operacional (embora deva ser um no qual os erros listados acima façam sentido; tentei mantê-los gerais o suficiente para funcionar na maioria dos sistemas operacionais de consumo multitarefa, mas é possível que sistemas operacionais mais estranhos sejam excluídos deste desafio). Se o seu programa não for portável, liste as suposições necessárias para executar no título do seu envio.

  • Esta tarefa pode não ser possível em todos os idiomas (nem todos os idiomas permitem que um programa lide com erros de saída de maneira personalizada). Você terá que escolher um idioma onde for possível.

  • Verifique se o seu programa / função funciona! Não confie apenas na documentação das funções da biblioteca para fazer o que elas dizem que fazem. O tratamento de erros de funções simples de saída geralmente acaba sendo quebrado na prática, mesmo que as funções pretendam manipular erros na teoria.

Casos de teste

Aqui está uma maneira de simular cada uma das condições de erro acima usando bashno Linux (você não precisa usar o Linux, mas é provavelmente o sistema mais fácil para testar isso):

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

Os dois primeiros casos de teste são determinísticos. O último não é (depende de uma condição de corrida); para fins de teste, recomendo adicionar um atraso entre o início do seu programa e a saída real à saída padrão, para garantir que a condição de corrida seja resolvida da maneira que expõe o erro.

Condição de vitória

Este é um desafio do , então quanto menor, melhor. Como (quase) sempre, estamos medindo o comprimento do programa em bytes.


fonte
11
Você sabe se existe uma maneira de testar isso no Windows? Eu posso testar o primeiro critério, mas não a parte sobre o disco estar cheio ...
Stewie Griffin
Para reduzir a condição de corrida, você poderia usar sleep 1 < test; (sleep 2; your_program_here) > test?
Neil
Relacionado
JayCe

Respostas:

6

Bash , 71 60 bytes

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

Experimente online!

Como funciona

Depois de salvar Hello, world!na variável h , fazemos o seguinte.

Primeiro, (echo $h)2>&-tenta imprimir Hello, world!em STDOUT. 2>&-é necessário para impedir a exibição da mensagem de erro eco: erro de gravação: Descritor de arquivo incorreto no caso de falha na gravação. Como gravar em um pipe nomeado que não aceita entrada mataria o programa Bash com o sinal 13 (SIGPIPE), executamos o comando em um subshell ( (...)), para que apenas o subshell seja morto.

Por fim, se a impressão em STDOUT falhar, o subshell sairá com um código de status diferente de zero (141 para SIGPIPE, 1 para um erro genérico) e, portanto, echo Error writing \"$h\">&2imprime a mensagem desejada em STDERR.

Dennis
fonte
2

Python 2 , 65 bytes

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

Dois bytes podem ser salvos imprimindo aspas simples.

Experimente online!

Dennis
fonte
1

Zsh , 55 bytes

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

Ao contrário de seu primo Bash, Zsh se recusa a morrer por causa de um cano quebrado.

Experimente online!

Dennis
fonte
1

C (gcc) , 87 86 bytes

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

Experimente 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);
}
Dennis
fonte
como você sabe o que o retorno coloca? aqui diz apenas que é> = 0 para ficar tudo ok ...
RosLuP
putsretorna o número de bytes que foram gravados ou -1 em caso de erro; portanto, retorna 14 (Hello World mais nova linha) ou -1 . (Isso pode ser específico da plataforma, mas isso é como ele se comporta com glibc.)
Dennis
K & R2 diz que retorna EOF [-1 na prática] se erro; ou um valor não negativo se tudo ok
RosLuP
11
No PPCG, as linguagens são definidas por sua implementação e o gcc / glibc se comporta como eu disse.
216 Dennis
Eu prefiro o velho livro
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"""
}

não consegui realmente tentar isso quando erros, mas definitivamente ~ deveria ~ funcionar.

colsw
fonte
A mensagem de erro deve ser gravada em STDERR . Não é possível gravá-lo no STDOUT se ocorrer um erro durante a primeira tentativa de gravação.
Dennis
@ Dennis obrigado por isso, atualizado lá, não leu a pergunta completamente.
colsw
Afinal, o PowerShell captura apenas exceções fatais, então você precisaria Write-Host -ErrorAction Stopou algo assim. Além disso, throwproduz informações adicionais de depuração além da linha que deve ser impressa, que por sinal deve ter um W minúsculo e aspas duplas ao redor da string HW.
Dennis
@ Dennis as informações adicionais de depuração me esmagaram, resposta atualizada lá agora.
colsw
1

Javascript, 79 76 bytes

try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}
Matthew Roh
fonte
Observe que a string que você deve gerar 'Hello, world!'é um byte a mais que o que você usa. Além disso, suponho que atribuir adentro da chamada a console.logseja mais curto (1B) e remover o ponto e vírgula após l.log(a)salvar outro byte.
Lucas
@ Lucas Obrigado, isso foi um grande erro!
Matthew Roh
11
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}por 76 bytes. Primeiro, consoleé atribuído a l, depois "Hello, world!'é atribuído a ae, em seguida, é executado.
Lucas
0

Perl 5, 51 bytes

requer -M5.01, que é gratuito

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

Testado no Strawberry Perl 5.24.0 executando o programa como está (impresso na saída padrão) e executando

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

(impresso com erro padrão). Não sei como testar outros erros usando o Strawberry, mas eles devem ser tratados da mesma maneira….

msh210
fonte
Até onde eu sei, isso não funciona. tio.run/nexus/bash#jY3NDoIwEITvfYq1IXCiiD83ys3Ei2/... (A seqüência também está faltando uma vírgula.)
Dennis
Não sei o que fazer com essa página à qual você vinculou; você pode explicar por favor? Além disso, observe que o script precisa funcionar apenas em um sistema operacional. E eu vou adicionar a vírgula; obrigado.
msh210
A saída deve ser exibida Hello, world!depois === 1 ===e nada depois das outras. A depuração não deve exibir nada depois === 1 ===e Error writing "Hello, world!"depois dos outros. Estou ciente de que seu programa não precisa funcionar no TIO, mas print f...mostra as mensagens de erro pretendidas enquanto o programa original não.
Dennis
"Saída" e "Depuração" exibem nada até onde eu vejo. Também não sei quais devem ser as seções "Cabeçalho" e "Rodapé". E não estou familiarizado com o TIO, mas observe que o Strawberry Perl é executado no MS Windows.
msh210
Dica de chapéu para Dennis pela idéia de armazenar a string em uma variável (embora eu provavelmente pensaria nisso se não a visse lá).
Msh210
0

REXX, 111 106 bytes

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

O programa conta com a existência de um fluxo chamado 'stderr'. Provavelmente não será esse o caso nos sistemas IBM.

idrougge
fonte
0

C, 77 bytes

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

para chamada

main(){f(1); return 0;}
RosLuP
fonte
Em qual plataforma você testou isso? Não funciona no Linux se um tubo quebrado for encontrado.
217 Dennis
0

R , 91 bytes

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

Experimente online!

Tentei errar ao executá-lo com, em cat(s,file=12)vez de cat(s), e ele imprime o texto correto no stderr. invalid connectionCaso contrário, este é um erro.

JayCe
fonte
Alguma idéia de como testar outros erros de saída?
Jayce