Hello World处理错误


9

编写具有以下功能的程序或函数:

  • 程序/函数首先尝试将字符串写入Hello, world!标准输出流。(此挑战没有其他形式的输出是可以接受的,因为重点是I / O而不是程序本身的琐碎行为。)取决于程序是否成功:
    • 如果成功输出Hello, world!,则程序/功能将退出而没有任何进一步的行为。
    • 如果由于错误而未能产生正确的输出,则程序/函数会尝试将字符串写入Error writing "Hello, world!"标准错误流。(出于此挑战的目的,您无需为错误处理本身进行错误处理。)

澄清说明

  • 您的程序/函数将在没有输入的情况下运行(除非以绝对需要输入才能正常工作的语言编写,在这种情况下,它将使用最简单的输入来运行)。

  • 产生输出时,如果愿意,也可以产生一个尾随换行符,但这不是强制性的。

  • 程序实现的“写入标准输出错误”的定义必须至少将以下情况视为错误:

    • 不存在标准输出(即,stdout是封闭的文件句柄,不存在文件描述符1,或者这些情况会转换为您使用的语言和操作系统);
    • 标准输出,指的是磁盘上没有可用空间的文件;
    • 标准输出连接到另一个程序,该程序已经关闭了连接的末端。

    并且必须至少将以下情况视为成功(即不是错误):

    • 标准输出连接到终端,并Hello, world!显示在屏幕上。
    • 标准输出连接到文件,并Hello, world!写入文件中。

    您可以选择什么才是输出错误的详细信息,只要它与上述规则一致即可。

  • 遇到上面列出的任何错误情况,您的程序/功能都不会崩溃。由您决定使用哪种退出代码。

  • 您的程序/函数不应在标准错误流上描述遇到的错误的性质;它应该只打印上面指定的字符串。标准错误的无关输出(例如,编译器警告)只有在无条件产生的情况下才是合法的,无论是否遇到错误。

  • 您的程序仅需要在一个操作系统上运行(尽管必须是上面列出的错误才有意义的操作系统;我试图使它们具有足够的通用性,以使其能够在大多数多任务消费者操作系统上运行,但是怪异的操作系统可能会排除在此挑战之外)。如果您的程序不可移植,请在提交的标题中列出需要运行的假设。

  • 并非每种语言都可能完成此任务(并非每种语言都允许程序以自定义方式处理输出错误)。您必须选择一种可能的语言。

  • 确保您的程序/功能有效!不要仅仅相信库函数的文档就能完成他们说的事情。简单的输出函数的错误处理在实践中常常被证明是错误的,即使函数声称在理论上处理错误。

测试用例

这是一种bash在Linux 上使用的方法,可以模拟上述每种错误情况(您不必使用Linux,但这可能是最简单的测试系统):

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

前两个测试用例是确定性的。最后一个不是(它取决于比赛条件)。出于测试目的,我建议在程序启动与实际输出到标准输出之间增加一个延迟,以确保以暴露错误的方式解决竞争状况。

胜利条件

这是一个 挑战,所以越短越好。与(几乎)总是一样,我们正在测量程序的长度(以字节为单位)。


1
您知道是否可以在Windows上进行测试吗?我可以测试第一个条件,但不能测试磁盘已满的部分...
Stewie Griffin

为了减少比赛条件,您可以使用sleep 1 < test; (sleep 2; your_program_here) > test吗?
尼尔,

Answers:


6

Bash71 60字节

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

在线尝试!

怎么运行的

保存Hello, world!到变量h之后,我们执行以下操作。

首先,(echo $h)2>&-尝试打印Hello, world!到STDOUT。2>&-防止显示错误消息echo是必需的:write error:如果写入失败,则错误的文件描述符。由于写入不接受输入的命名管道会杀死信号为13(SIGPIPE)的Bash程序,因此我们在子外壳程序((...))中执行命令,因此只有子外壳程序会被杀死。

最后,如果打印到STDOUT失败,则子外壳程序将退出,并返回一个非零的状态代码(对于SIGPIPE为141,对于一般错误为1),因此echo Error writing \"$h\">&2将所需的消息打印到STDERR。



1

Zsh,55个字节

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

与表弟Bash不同,Zsh由于管道破裂而拒绝死亡。

在线尝试!


1

C(gcc)87 86字节

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

在线尝试!

不打高尔夫球

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

您如何知道收益回报?这里说只是> = 0,就可以了...
RosLuP

puts返回已写入的字节数,如果发生错误则返回-1,因此它返回14(Hello World加换行符)或-1。(这可能是特定于平台的,但这是glibc的行为方式。)
Dennis

K&R2表示如果出错,则返回EOF [-1(实际上)。或所有值都可以的非负值
RosLuP

1
在PPCG上,语言是由其实现定义的,并且gcc / glibc的行为就像我说的那样。
丹尼斯,

我更喜欢旧书
RosLuP

1

PowerShell,80字节

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

解释:

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

出现错误时还没有设法进行尝试,但是绝对可以。


错误消息应写入STDERR。如果在第一次写入尝试期间发生错误,则不可能将其写入STDOUT。
丹尼斯

@Dennis对此表示感谢,并在那里进行了更新,没有完全阅读问题。
colsw

Afaict PowerShell仅捕获致命异常,因此您将需要Write-Host -ErrorAction Stop或类似的东西。同样,throw除了在它应该打印的行之外,生产程序还会产生其他调试信息,顺便说一下,它应该有一个小写的W和在HW字符串周围有双引号。
丹尼斯,

@Dennis的其他调试信息使我迷惑不解,请在此处答复更新。
colsw

1

Javascript,79 76字节

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

请注意,您应该输出的字符串是'Hello, world!',比您使用的字符串长一字节。另外,我想将a内部调用分配给console.log会更短(1B),并在l.log(a)保存另一个字节之后删除分号。
路加福音

@Luke谢谢,那是一个很大的错误!
马修·罗

1
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}为76个字节。首先,console将分配给l,然后"Hello, world!'分配给a,然后执行它。
路加福音

0

Perl 5,51个字节

required -M5.01,这是免费的

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

通过按原样运行程序(打印到标准输出)并运行在Strawberry Perl 5.24.0中进行测试

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

(打印到标准错误)。我不知道如何使用Strawberry测试其他错误,但是应该以相同的方式处理它们。


据我所知,这是行不通的。tio.run/nexus/bash#jY3NDoIwEITvfYq1IXCiiD83ys3Ei2/…(该字符串也缺少逗号。)
Dennis

我不知道您链接到的页面的内容。你能解释一下吗?另外,请注意,该脚本仅需要在一个OS上运行。我将添加逗号;谢谢。
msh210 '17

输出应显示Hello, world!=== 1 ===后面,其他之后不显示。调试应显示后没有 === 1 ===Error writing "Hello, world!"其他人后。我知道,你的程序不具有对工作的TIO,但print f...节目而原来的程序并没有预期的错误消息。
丹尼斯

据我所知,“输出”和“调试”均未显示任何内容。我也不知道“页眉”和“页脚”部分应该是什么。我完全不熟悉TIO,但是请注意,Strawberry Perl在MS Windows上运行。
msh210 '17

丹尼斯(Dennis)提出建议,以将字符串存储在变量中(尽管如果我在那里看不到它,我可能会想到它)。
msh210 '17

0

REXX,111个 106字节

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

该程序依赖于称为“ stderr”的流。在IBM系统上可能不是这种情况。


0

C,77字节

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

打电话

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

您在哪个平台上对此进行了测试?如果遇到管道中断,则在Linux上不起作用。
丹尼斯,

0

R,91字节

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

在线尝试!

我尝试通过运行它来错误 cat(s,file=12)代替来cat(s),它将正确的文本输出到stderr。invalid connection否则,这是一个错误。


知道如何测试其他输出错误吗?
JayCe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.