Halo dunia yang menangani kesalahan

9

Tulis program atau fungsi dengan fungsi berikut:

  • Program / fungsi pertama kali mencoba menulis string Hello, world!ke aliran output standar. (Tidak ada bentuk output lain yang dapat diterima untuk tantangan ini, karena fokusnya sangat banyak pada I / O daripada perilaku sepele dari program itu sendiri.) Tergantung pada apakah itu berhasil:
    • Jika berhasil menghasilkan Hello, world!, program / fungsi keluar tanpa perilaku lebih lanjut.
    • Jika gagal menghasilkan output yang benar karena kesalahan, program / fungsi mencoba untuk menulis string Error writing "Hello, world!"ke aliran kesalahan standar. (Untuk keperluan tantangan ini, Anda tidak perlu menangani kesalahan untuk penanganan kesalahan itu sendiri.)

Klarifikasi

  • Program / fungsi Anda akan dijalankan tanpa input (kecuali jika ditulis dalam bahasa yang benar-benar membutuhkan input untuk bekerja, dalam hal ini akan dijalankan dengan input sesederhana mungkin).

  • Saat menghasilkan output, Anda juga dapat menghasilkan satu baris baru jika diinginkan, tetapi melakukannya tidak wajib.

  • Definisi "penulisan kesalahan ke output standar" yang diterapkan oleh program Anda harus memperlakukan setidaknya kasus-kasus berikut sebagai kesalahan:

    • Output standar tidak ada (yaitu stdoutfilehandle tertutup, tidak ada deskriptor file 1 ada, atau bagaimanapun kasus-kasus menerjemahkan ke bahasa dan OS yang Anda gunakan);
    • Output standar mengacu pada file pada disk yang tidak memiliki ruang kosong tersisa;
    • Output standar yang terhubung ke program lain, yang sudah menutup ujung koneksi.

    dan harus memperlakukan setidaknya kasus-kasus berikut sebagai keberhasilan (yaitu bukan kesalahan):

    • Output standar terhubung ke terminal, dan Hello, world!ditampilkan di layar.
    • Output standar terhubung ke file, dan Hello, world!ditulis ke dalam file.

    Anda dapat memilih detail dari apa yang dianggap sebagai kesalahan output, asalkan konsisten dengan aturan di atas.

  • Program / fungsi Anda seharusnya tidak macet saat menemukan salah satu situasi kesalahan yang tercantum di atas. Terserah Anda apa kode keluar yang Anda gunakan.

  • Program / fungsi Anda tidak boleh menggambarkan sifat kesalahan yang ditemui pada aliran kesalahan standar; seharusnya hanya mencetak string yang ditentukan di atas. Keluaran luar pada kesalahan standar (mis. Peringatan kompiler) hanya sah jika diproduksi tanpa syarat, terlepas dari apakah ada kesalahan atau tidak.

  • Program Anda hanya perlu bekerja pada satu sistem operasi (walaupun harus salah satu di mana kesalahan yang tercantum di atas masuk akal; Saya sudah mencoba membuatnya cukup umum untuk bekerja pada sebagian besar sistem operasi konsumen multitasking, tetapi sistem operasi yang lebih aneh mungkin juga dikecualikan dari tantangan ini). Jika program Anda tidak dapat diakses, daftarkan asumsi yang diperlukan untuk menjalankannya dalam judul kiriman Anda.

  • Tugas ini mungkin tidak dapat dilakukan di setiap bahasa (tidak semua bahasa memungkinkan program menangani kesalahan keluaran dengan cara khusus). Anda harus memilih bahasa yang memungkinkan.

  • Pastikan program / fungsi Anda berfungsi! Jangan hanya mempercayai dokumentasi fungsi perpustakaan untuk melakukan apa yang mereka katakan. Penanganan kesalahan fungsi output sederhana sering ternyata rusak dalam praktik, bahkan jika fungsi mengklaim untuk menangani kesalahan dalam teori.

Uji kasus

Berikut adalah cara untuk mensimulasikan masing-masing kondisi kesalahan di atas menggunakan bashdi Linux (Anda tidak harus menggunakan Linux, tetapi kemungkinan sistem yang paling mudah untuk menguji ini):

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

Dua testcases pertama bersifat deterministik. Yang terakhir bukan (itu bergantung pada kondisi balapan); untuk tujuan pengujian, saya sarankan untuk menambahkan penundaan antara awal program Anda dan output aktual ke output standar, untuk memastikan bahwa kondisi balapan diselesaikan dengan cara yang mengekspos kesalahan.

Kondisi kemenangan

Ini adalah tantangan , jadi lebih pendek lebih baik. Seperti (hampir) selalu, kami mengukur panjang program dalam byte.


sumber
1
Apakah Anda tahu jika ada cara untuk menguji ini pada Windows? Saya dapat menguji kriteria pertama, tetapi bukan bagian tentang disk yang penuh ...
Stewie Griffin
Untuk mengurangi kondisi balapan, dapatkah Anda menggunakan sleep 1 < test; (sleep 2; your_program_here) > test?
Neil
Terkait
JayCe

Jawaban:

6

Bash , 71 60 byte

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

Cobalah online!

Bagaimana itu bekerja

Setelah menyimpan Hello, world!ke variabel h , kami melakukan hal berikut.

Pertama, (echo $h)2>&-mencoba mencetak Hello, world!ke STDOUT. 2>&-diperlukan untuk mencegah menampilkan pesan kesalahan echo: write error: deskriptor file salah jika penulisan gagal. Karena menulis ke pipa bernama yang tidak menerima input akan mematikan program Bash dengan sinyal 13 (SIGPIPE), kami menjalankan perintah dalam subshell ( (...)), jadi hanya subshell yang akan terbunuh.

Akhirnya, jika pencetakan ke STDOUT gagal, subkulit akan keluar dengan kode status non-nol (141 untuk SIGPIPE, 1 untuk kesalahan umum), jadi echo Error writing \"$h\">&2cetak pesan yang diinginkan ke STDERR.

Dennis
sumber
2

Python 2 , 65 byte

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

Dua byte dapat disimpan dengan mencetak tanda kutip tunggal.

Cobalah online!

Dennis
sumber
1

Zsh , 55 byte

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

Tidak seperti Bash, sepupunya, Zsh menolak untuk mati karena pipa yang rusak.

Cobalah online!

Dennis
sumber
1

C (gcc) , 87 86 byte

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

Cobalah online!

Tidak disatukan

#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
sumber
bagaimana Anda tahu apa yang mengembalikan? di sini mengatakan hanya> = 0 untuk semuanya ok ...
RosLuP
putsmengembalikan jumlah byte yang telah ditulis atau -1 jika terjadi kesalahan, sehingga mengembalikan 14 (Hello World plus newline) atau -1 . (Itu mungkin khusus untuk platform, tetapi ini adalah bagaimana berperilaku dengan glibc.)
Dennis
K & R2 mengatakan itu mengembalikan EOF [-1 praticly] jika kesalahan; atau nilai tidak negatif jika semuanya ok
RosLuP
1
Di PPCG, bahasa didefinisikan oleh implementasinya, dan gcc / glibc berperilaku seperti yang saya katakan.
Dennis
Saya lebih suka buku yang lama
RosLuP
1

PowerShell, 80 Bytes

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

menjelaskan:

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

belum berhasil untuk benar-benar mencoba ini ketika kesalahan, tetapi pasti ~ harus ~ bekerja.

colsw
sumber
Pesan kesalahan harus ditulis ke STDERR . Menulisnya ke STDOUT tidak dimungkinkan jika terjadi kesalahan selama upaya penulisan pertama.
Dennis
@ Dennis terima kasih untuk itu, diperbarui di sana, tidak membaca pertanyaan sepenuhnya.
colsw
Afaict PowerShell hanya menangkap pengecualian fatal, jadi Anda perlu Write-Host -ErrorAction Stopatau sesuatu seperti itu. Juga, throwmenghasilkan tambahan debugging selain dari garis yang harus dicetak, yang omong-omong harus memiliki huruf kecil W dan tanda kutip ganda di sekitar string HW.
Dennis
@ Dennis info debug tambahan telah menghancurkan saya, jawab diperbarui di sana sekarang.
colsw
1

Javascript, 79 76 byte

try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}
Matthew Roh
sumber
Perhatikan bahwa string yang harus Anda output adalah 'Hello, world!', yang satu byte lebih panjang dari apa yang Anda gunakan. Juga, saya kira menetapkan adi dalam panggilan console.logakan lebih pendek (1B) dan menghapus titik koma setelah l.log(a)menyimpan byte lain.
Luke
@ Lukas Terima kasih, Itu kesalahan yang cukup besar!
Matius Roh
1
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}untuk 76 byte. Pertama, consoleditugaskan l, kemudian "Hello, world!'ditugaskan a, dan kemudian dieksekusi.
Luke
0

Perl 5, 51 byte

membutuhkan -M5.01, yang gratis

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

Diuji dalam Strawberry Perl 5.24.0 dengan menjalankan program apa adanya (dicetak ke output standar) dan dengan menjalankan

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

(dicetak ke kesalahan standar). Saya tidak tahu bagaimana cara menguji kesalahan lain menggunakan Strawberry, tetapi mereka harus ditangani sama ....

msh210
sumber
Sejauh yang saya tahu, ini tidak berhasil. tio.run/nexus/bash#jY3NDoIwEITvfYq1IXCiiD83ys3Ei2/… (String juga tidak memiliki koma.)
Dennis
Saya tidak tahu harus membuat apa dari halaman yang Anda tautkan; bisakah Anda menjelaskannya? Juga, perhatikan bahwa skrip perlu bekerja pada satu OS saja. Dan saya akan menambahkan koma; Terima kasih.
msh210
Output akan ditampilkan Hello, world!setelah === 1 ===dan tidak ada setelah yang lain. Debug seharusnya tidak menampilkan apa pun setelah === 1 ===dan Error writing "Hello, world!"sesudah yang lain. Saya sadar bahwa program Anda tidak harus bekerja pada TIO, tetapi print f...menunjukkan pesan kesalahan yang dimaksud sementara program aslinya tidak.
Dennis
"Output" dan "Debug" tidak menampilkan apa pun sejauh yang saya lihat. Saya juga tidak tahu apa bagian "Header" dan "Footer" seharusnya. Dan saya sepenuhnya tidak terbiasa dengan TIO, tetapi perhatikan bahwa Strawberry Perl berjalan pada MS Windows.
msh210
Hat-tip ke Dennis untuk ide menyimpan string dalam variabel (meskipun saya mungkin akan memikirkannya seandainya saya tidak melihatnya di sana).
msh210
0

REXX, 111 106 byte

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

Program ini mengandalkan aliran yang disebut 'stderr'. Ini mungkin tidak akan terjadi pada sistem IBM.

idrougge
sumber
0

C, 77 byte

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

untuk panggilan

main(){f(1); return 0;}
RosLuP
sumber
Di platform mana Anda menguji ini? Ini tidak berfungsi di Linux jika pipa yang rusak ditemukan.
Dennis
0

R , 91 byte

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

Cobalah online!

Saya mencoba membuat kesalahan dengan menjalankannya dengan cat(s,file=12)alih - alih cat(s), dan mencetak teks yang benar ke stderr. Jika tidak, ini merupakan invalid connectionkesalahan.

JayCe
sumber
Adakah yang tahu cara menguji kesalahan output lainnya?
JayCe