Xin chào thế giới xử lý lỗi


9

Viết chương trình hoặc chức năng với chức năng sau:

  • Trước tiên, chương trình / hàm cố gắng ghi chuỗi Hello, world!vào luồng đầu ra tiêu chuẩn. (Không có hình thức đầu ra nào khác được chấp nhận cho thử thách này, vì trọng tâm tập trung rất nhiều vào I / O thay vì hành vi tầm thường của chính chương trình.) Tùy thuộc vào việc nó có thành công hay không:
    • Nếu nó thành công trong việc xuất ra Hello, world!, chương trình / hàm sẽ thoát mà không có bất kỳ hành vi nào nữa.
    • Nếu không thể tạo ra đầu ra chính xác do lỗi, chương trình / hàm cố gắng ghi chuỗi Error writing "Hello, world!"vào luồng lỗi tiêu chuẩn. (Đối với mục đích của thử thách này, bạn không cần xử lý lỗi cho chính việc xử lý lỗi.)

Làm rõ

  • Chương trình / chức năng của bạn sẽ được chạy mà không có đầu vào (trừ khi nó được viết bằng ngôn ngữ hoàn toàn yêu cầu đầu vào hoạt động, trong trường hợp đó, nó sẽ được chạy với đầu vào đơn giản nhất có thể).

  • Khi sản xuất đầu ra, bạn cũng có thể tạo một dòng mới duy nhất nếu bạn muốn, nhưng làm như vậy là không bắt buộc.

  • Định nghĩa "ghi lỗi vào đầu ra tiêu chuẩn" mà chương trình của bạn thực hiện phải coi ít nhất các trường hợp sau là lỗi:

    • Đầu ra tiêu chuẩn không tồn tại (nghĩa stdoutlà một tệp đóng, không có mô tả tệp 1 tồn tại hoặc các trường hợp đó dịch sang ngôn ngữ và HĐH bạn đang sử dụng);
    • Đầu ra tiêu chuẩn đề cập đến một tệp trên đĩa không còn chỗ trống;
    • Đầu ra tiêu chuẩn kết nối với một chương trình khác, đã kết thúc kết nối.

    và phải coi ít nhất các trường hợp sau là thành công (nghĩa là không có lỗi):

    • Đầu ra tiêu chuẩn kết nối với một thiết bị đầu cuối và Hello, world!được hiển thị trên màn hình.
    • Đầu ra tiêu chuẩn kết nối với một tệp và Hello, world!được ghi vào tệp.

    Bạn có thể chọn chi tiết về lỗi được tính là lỗi đầu ra, miễn là nó phù hợp với các quy tắc trên.

  • Chương trình / chức năng của bạn không bị sập khi gặp bất kỳ tình huống lỗi nào được liệt kê ở trên. Tùy thuộc vào bạn thoát mã nào bạn sử dụng.

  • Chương trình / chức năng của bạn không được mô tả bản chất của lỗi gặp phải trên luồng lỗi tiêu chuẩn; nó chỉ nên in chuỗi được chỉ định ở trên. Đầu ra không liên quan đến lỗi tiêu chuẩn (ví dụ cảnh báo trình biên dịch) chỉ hợp pháp nếu nó được tạo ra vô điều kiện, bất kể có gặp phải lỗi hay không.

  • Chương trình của bạn chỉ cần hoạt động trên một hệ điều hành (mặc dù nó phải là một lỗi mà các lỗi được liệt kê ở trên có ý nghĩa; Tôi đã cố gắng giữ chúng đủ chung để hoạt động trên hầu hết các hệ điều hành đa nhiệm của người tiêu dùng, nhưng các hệ điều hành kỳ lạ có thể loại trừ khỏi thử thách này). Nếu chương trình của bạn không thể truy cập được, hãy liệt kê các giả định mà nó cần để chạy trong tiêu đề của bài đăng của bạn.

  • Nhiệm vụ này có thể không thực hiện được ở mọi ngôn ngữ (không phải mọi ngôn ngữ đều cho phép chương trình xử lý các lỗi đầu ra theo cách tùy chỉnh). Bạn sẽ phải chọn một ngôn ngữ có thể.

  • Hãy chắc chắn rằng chương trình / chức năng của bạn hoạt động! Đừng chỉ tin vào tài liệu của các chức năng thư viện để làm những gì họ nói. Việc xử lý lỗi của các hàm đầu ra đơn giản thường bị hỏng trong thực tế, ngay cả khi các hàm yêu cầu xử lý lỗi trong lý thuyết.

Các trường hợp thử nghiệm

Đây là một cách để mô phỏng từng điều kiện lỗi ở trên bằng cách sử dụng bashtrên Linux (bạn không phải sử dụng Linux, nhưng đây có thể là hệ thống dễ nhất để kiểm tra điều này):

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

Hai testcase đầu tiên là xác định. Cái cuối cùng không (nó phụ thuộc vào điều kiện cuộc đua); cho mục đích thử nghiệm, tôi khuyên bạn nên thêm độ trễ giữa lúc bắt đầu chương trình và đầu ra thực tế vào đầu ra tiêu chuẩn, để đảm bảo rằng điều kiện cuộc đua được giải quyết theo cách phơi bày lỗi.

Điều kiện chiến thắng

Đây là một thử thách , vì vậy ngắn hơn là tốt hơn. Như (gần như) luôn luôn, chúng tôi đang đo chiều dài của chương trình theo byte.


1
Bạn có biết có cách nào để kiểm tra điều này trên Windows không? Tôi có thể kiểm tra tiêu chí đầu tiên, nhưng không phải là phần về đĩa đầy ...
Stewie Griffin

Để giảm điều kiện cuộc đua, bạn có thể sử dụng sleep 1 < test; (sleep 2; your_program_here) > test?
Neil

Câu trả lời:


6

Bash , 71 60 byte

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

Sau khi lưu Hello, world!vào biến h , chúng ta làm như sau.

Đầu tiên, (echo $h)2>&-cố gắng in Hello, world!sang STDOUT. 2>&-được yêu cầu để ngăn hiển thị thông báo lỗi echo: write error: Mô tả tập tin xấu trong trường hợp ghi thất bại. Vì việc ghi vào một ống có tên không chấp nhận đầu vào sẽ giết chương trình Bash bằng tín hiệu 13 (SIGPIPE), chúng tôi thực thi lệnh trong một subshell ( (...)), vì vậy chỉ có subshell sẽ bị giết.

Cuối cùng, nếu in thành STDOUT không thành công, lớp con sẽ thoát với mã trạng thái khác không (141 cho SIGPIPE, 1 cho lỗi chung), vì vậy hãy echo Error writing \"$h\">&2in thông báo mong muốn sang STDERR.




1

C (gcc) , 87 86 byte

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

Hãy thử trực tuyến!

Ung dung

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

Làm thế nào để bạn biết những gì trở lại đặt? ở đây chỉ nói rằng đó là> = 0 cho tất cả đều ổn ...
RosLuP

putstrả về số byte đã được ghi hoặc -1 trong trường hợp có lỗi, do đó, nó sẽ trả về 14 (Hello World cộng với dòng mới) hoặc -1 . (Đó có thể là nền tảng cụ thể, nhưng đây là cách nó hoạt động với glibc.)
Dennis

K & R2 nói rằng nó trả về EOF [-1 praticly] nếu có lỗi; hoặc một giá trị không âm nếu tất cả đều ổn
RosLuP

1
Trên PPCG, các ngôn ngữ được xác định bởi việc triển khai và gcc / glibc hoạt động như tôi đã nói.
Dennis

tôi thích cuốn sách cũ
RosLuP

1

PowerShell, 80 byte

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

giải thích:

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

Tôi đã không thực sự thử điều này khi nó xảy ra lỗi, nhưng nó chắc chắn ~ nên ~ hoạt động.


Thông báo lỗi nên được ghi vào STDERR . Viết nó vào STDOUT là không thể nếu có lỗi xảy ra trong lần ghi đầu tiên.
Dennis

@Dennis cảm ơn vì điều đó, đã cập nhật ở đó, đã không đọc câu hỏi đầy đủ.
colsw

Afaict PowerShell chỉ bắt được các ngoại lệ gây tử vong, vì vậy bạn cần Write-Host -ErrorAction Stophoặc một cái gì đó tương tự. Ngoài ra, việc throwtạo ra sự bổ sung gỡ lỗi bổ sung ngoài dòng cần in, bằng cách này nên có chữ W viết thường và dấu ngoặc kép quanh chuỗi CT.
Dennis

@Dennis thông tin gỡ lỗi bổ sung đã nghiền nát tôi, câu trả lời được cập nhật ngay bây giờ.
colsw

1

Javascript, 79 76 byte

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

Lưu ý rằng chuỗi bạn nên xuất là 'Hello, world!', dài hơn một byte so với chuỗi bạn sử dụng. Ngoài ra, tôi cho rằng việc gán abên trong cuộc gọi console.logsẽ ngắn hơn (1B) và xóa dấu chấm phẩy sau khi l.log(a)lưu một byte khác.
Luke

@Luke Cảm ơn, đó là một sai lầm khá lớn!
Matthew Roh

1
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}cho 76 byte. Đầu tiên, consoleđược gán cho l, sau đó "Hello, world!'được gán cho a, và sau đó nó được thực thi.
Lu-ca

0

Perl 5, 51 byte

yêu cầu -M5.01, miễn phí

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

Đã thử nghiệm trong Strawberry Perl 5.24.0 bằng cách chạy chương trình nguyên trạng (được in ra đầu ra tiêu chuẩn) và bằng cách chạy

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

(in lỗi tiêu chuẩn). Tôi không biết cách kiểm tra các lỗi khác khi sử dụng Dâu tây, nhưng chúng nên được xử lý giống như trên.


Theo như tôi có thể nói, điều này không hoạt động. tio.run/nexus/bash#jY3NDoIwEITvfYq1IXCiiD83ys3Ei2/... (Chuỗi cũng thiếu dấu phẩy.)
Dennis

Tôi không biết phải làm gì với trang mà bạn liên kết đến; bạn có thể giải thích được không? Ngoài ra, lưu ý rằng tập lệnh chỉ cần hoạt động trên một hệ điều hành. Và tôi sẽ thêm dấu phẩy; cảm ơn.
msh210

Đầu ra sẽ hiển thị Hello, world!sau === 1 ===và không có gì sau những cái khác. Gỡ lỗi sẽ không hiển thị gì sau === 1 ===Error writing "Hello, world!"sau những cái khác. Tôi biết rằng chương trình của bạn không phải làm việc trên TIO, nhưng print f...các chương trình dự định thông báo lỗi khi chương trình ban đầu thì không.
Dennis

"Đầu ra" và "Gỡ lỗi" đều không hiển thị gì xa như tôi thấy. Tôi cũng không biết phần "Header" và "Footer" là gì. Và tôi hoàn toàn không quen thuộc với TIO, nhưng lưu ý rằng Strawberry Perl chạy trên MS Windows.
msh210

Hat-tip cho Dennis cho ý tưởng lưu trữ chuỗi trong một biến (mặc dù tôi có thể đã nghĩ về nó nếu tôi không thấy nó ở đó).
msh210

0

REXX, 111 106 byte

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

Chương trình dựa vào việc có một luồng gọi là 'stderr'. Điều này có thể sẽ không xảy ra trên các hệ thống của IBM.


0

C, 77 byte

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

cho cuộc gọi

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

Trên nền tảng nào bạn đã kiểm tra điều này? Nó không hoạt động trên Linux nếu gặp phải một đường ống bị hỏng.
Dennis

0

R , 91 byte

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

Hãy thử trực tuyến!

Tôi đã thử lỗi nó bằng cách chạy nó cat(s,file=12)thay vì cat(s)và nó in văn bản chính xác thành stderr. Đây là một invalid connectionlỗi khác.


Bất kỳ ý tưởng làm thế nào để kiểm tra các lỗi đầu ra khác?
JayCe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.