สวัสดีชาวโลกที่จัดการข้อผิดพลาด


9

เขียนโปรแกรมหรือฟังก์ชั่นด้วยฟังก์ชั่นต่อไปนี้:

  • โปรแกรม / ฟังก์ชั่นครั้งแรกพยายามที่จะเขียนสตริงHello, world!ไปยังกระแสออกมาตรฐาน (ไม่มีรูปแบบอื่น ๆ ของการส่งออกเป็นที่ยอมรับสำหรับความท้าทายนี้เนื่องจากการมุ่งเน้นเป็นอย่างมากกับ I / O มากกว่าพฤติกรรมเล็กน้อยของโปรแกรมเอง) ขึ้นอยู่กับว่ามันประสบความสำเร็จ:
    • ถ้ามันประสบความสำเร็จในการส่งHello, world!ออกโปรแกรม / ฟังก์ชั่นออกโดยไม่มีพฤติกรรมใด ๆ เพิ่มเติม
    • หากไม่สามารถสร้างเอาต์พุตที่ถูกต้องเนื่องจากข้อผิดพลาดโปรแกรม / ฟังก์ชันจะพยายามเขียนสตริงError writing "Hello, world!"ลงในสตรีมข้อผิดพลาดมาตรฐาน (สำหรับวัตถุประสงค์ของการท้าทายนี้คุณไม่จำเป็นต้องจัดการข้อผิดพลาดเพื่อจัดการข้อผิดพลาดเอง)

ชี้แจง

  • โปรแกรม / ฟังก์ชั่นของคุณจะทำงานโดยไม่มีการป้อนข้อมูล (เว้นแต่จะเขียนด้วยภาษาที่ต้องใช้อินพุตในการทำงานซึ่งในกรณีนี้มันจะทำงานด้วยอินพุตที่เป็นไปได้ง่ายที่สุด)

  • เมื่อสร้างเอาต์พุตคุณอาจสร้างบรรทัดใหม่ขึ้นหนึ่งบรรทัดหากคุณต้องการ แต่การทำเช่นนั้นไม่จำเป็น

  • คำจำกัดความของ "การเขียนข้อผิดพลาดไปยังเอาต์พุตมาตรฐาน" ที่โปรแกรมของคุณดำเนินการต้องปฏิบัติอย่างน้อยกรณีต่อไปนี้เป็นข้อผิดพลาด:

    • เอาต์พุตมาตรฐานไม่มีอยู่ (เช่นstdoutfilehandle ปิดไม่มีไฟล์ descriptor 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 หรือไม่ ฉันสามารถทดสอบเกณฑ์แรก แต่ไม่ได้เป็นส่วนหนึ่งเกี่ยวกับดิสก์ถูกเต็ม ...
สตีวีกริฟฟิ

เพื่อลดสภาพการแข่งขันคุณสามารถใช้sleep 1 < test; (sleep 2; your_program_here) > test?
Neil

คำตอบ:


6

Bash , 71 60 ไบต์

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

ลองออนไลน์!

มันทำงานอย่างไร

หลังจากบันทึกHello, world!ลงในตัวแปรhเราจะทำสิ่งต่อไปนี้

ก่อนอื่น(echo $h)2>&-ให้ลองพิมพ์Hello, world!ไปที่ STDOUT 2>&-จำเป็นเพื่อป้องกันการแสดงข้อความแสดงข้อผิดพลาดecho: ข้อผิดพลาดในการเขียน: ตัวอธิบายไฟล์ไม่ถูกต้องในกรณีที่การเขียนล้มเหลว เนื่องจากการเขียนไปยังไพพ์ที่มีชื่อซึ่งไม่ยอมรับอินพุตจะทำให้โปรแกรม Bash มีสัญญาณ 13 (SIGPIPE) เราดำเนินการคำสั่งใน subshell ( (...)) ดังนั้นเฉพาะ subshell เท่านั้นที่จะถูกฆ่า

ท้ายที่สุดหากการพิมพ์ไปที่ STDOUT ล้มเหลว subshell จะออกด้วยรหัสสถานะที่ไม่เป็นศูนย์ (141 สำหรับ SIGPIPE, 1 สำหรับข้อผิดพลาดทั่วไป) ดังนั้นecho Error writing \"$h\">&2พิมพ์ข้อความที่ต้องการไปยัง STDERR




1

C (gcc) , 87 86 ไบต์

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

ลองออนไลน์!

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

คุณจะรู้ได้อย่างไรว่าผลตอบแทนอะไรทำให้? นี่บอกแค่ว่ามันคือ> = 0 เพื่อให้ทุกคนโอเค ...
RosLuP

putsส่งกลับจำนวนไบต์ที่ได้รับการเขียนหรือ-1ในกรณีที่มีข้อผิดพลาดดังนั้นมันทั้งผลตอบแทนที่14 (Hello World บวกขึ้นบรรทัดใหม่) หรือ-1 (นั่นอาจจะเป็นแพลตฟอร์มที่เฉพาะเจาะจง แต่นี้เป็นวิธีการที่จะทำงานกับ glibc.)
เดนนิส

K & R2 แจ้งว่าส่งคืน EOF [-1 praticly] หากมีข้อผิดพลาด หรือค่าจะไม่เป็นลบหากตกลงทั้งหมด
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)บันทึกไบต์อื่น
ลุค

@ ลุคขอบคุณนั่นเป็นความผิดพลาดครั้งใหญ่!
Matthew Roh

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 ไบต์

ต้องการ-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

ฉันไม่รู้ว่าจะทำอย่างไรของหน้าที่คุณเชื่อมโยงไป คุณช่วยอธิบายได้ไหม นอกจากนี้โปรดทราบว่าสคริปต์ต้องทำงานบนระบบปฏิบัติการเดียวเท่านั้น และฉันจะเพิ่มเครื่องหมายจุลภาค; ขอบคุณ
msh210

ผลลัพธ์ควรแสดงHello, world!หลังจาก=== 1 ===และไม่มีอะไรหลังจากรายการอื่น ดีบักไม่ควรแสดงอะไรหลังจาก === 1 ===และError writing "Hello, world!"หลังจากที่อื่น ๆ ฉันทราบว่าโปรแกรมของคุณไม่จำเป็นต้องทำงานกับ TIO แต่print f...จะแสดงข้อความแสดงข้อผิดพลาดในขณะที่โปรแกรมดั้งเดิมไม่ทำงาน
เดนนิส

"Output" และ "Debug" ทั้งคู่ไม่แสดงอะไรเลยเท่าที่ฉันเห็น ฉันยังไม่รู้ด้วยซ้ำว่าส่วน "หัว" และ "ท้ายกระดาษ" คืออะไร และฉันไม่คุ้นเคยกับ TIO ทั้งหมด แต่ทราบว่า Strawberry Perl ทำงานบน MS Windows
msh210

Hat-tip ถึงDennisสำหรับแนวคิดในการเก็บสายอักขระไว้ในตัวแปร
msh210

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.