ความแตกต่างระหว่างการพิมพ์และการวางคืออะไร?


261

เช่นในบรรทัดของรหัสนี้ฉันเขียนprintและputsให้ผลลัพธ์ที่แตกต่าง

1.upto(1000).each { |i| print i if i % 2 == 0 }

คำตอบ:


377

puts เพิ่มบรรทัดใหม่ในตอนท้ายของแต่ละอาร์กิวเมนต์หากยังไม่มีอีกหนึ่งบรรทัด

print ไม่เพิ่มบรรทัดใหม่


ตัวอย่างเช่น:

puts [[1,2,3], [4,5,nil]] จะกลับมา:

1
2
3
4
5

ในขณะที่print [[1,2,3], [4,5,nil]] จะกลับมา:

[[1,2,3], [4,5, ไม่มี]
ขอให้สังเกตว่าการใส่ไม่ส่งออกค่าศูนย์ในขณะที่พิมพ์ไม่

88
ที่จริงแล้วขึ้นบรรทัดใหม่หลังจากแต่ละอาร์กิวเมนต์ นั่นคือจุดสำคัญและไม่ชัดเจนจาก Ruby docs (เนื่องจากตัวอย่างมีเพียง 1 อาร์กิวเมนต์)
cdunn2001

3
มีอีกสิ่งหนึ่ง ... ขยายคลาสอาเรย์และแทนที่เมธอด to_s ทำให้ไม่ใช้ to_s ใหม่สำหรับวัตถุของคลาสใหม่ของคุณในขณะที่พิมพ์ไม่
kapv89

1
การใช้ irb 0.9.5 puts ("a") และ put ("a \ n") มีเอาต์พุตเดียวกันบน REPL
Marcus Junius Brutus

@ kapv89 นั้นไม่เป็นความจริง: ฉันเพิ่งลองและทำให้ทั้งสองพิมพ์ e ใช้วิธี to_s เฉพาะ p ไม่ได้ใช้
collimarco

6
@ ผู้ให้คำปรึกษานั่นเป็นเพียงข้อโต้แย้งเดียว คอมไพเลอร์เชื่อมต่อสตริงที่อยู่ติดกัน
cdunn2001

61

ความแตกต่างใหญ่คือถ้าคุณกำลังแสดงอาร์เรย์ โดยเฉพาะกับ NIL ตัวอย่างเช่น:

print [nil, 1, 2]

จะช่วยให้

[nil, 1, 2]

แต่

puts [nil, 1, 2]

จะช่วยให้

1
2

หมายเหตุไม่มีรายการใดปรากฏ (เพียงบรรทัดว่าง) และแต่ละรายการในบรรทัดที่แตกต่างกัน


1
ฉันสังเกตเห็นวันนี้ซึ่งพาฉันมาที่นี่ ฉันชอบที่จะรู้ว่าการคิดในเรื่องนั้น ดูเหมือนว่าเป็นกรณีพิเศษสำหรับการใส่เพื่อจัดการอาร์เรย์เช่นนั้น สงสัยว่าเหตุผลคืออะไร ... มันเหมือนกับภาษาอื่น ๆ หรือเปล่า?
Dan Barron

มันสมเหตุสมผลแล้วเนื่องจาก put จะออกมาพร้อมกับบรรทัดใหม่ดังนั้นคุณสามารถคิดได้ว่าเป็นการวนซ้ำในอาร์เรย์และการเรียกวางในแต่ละบรรทัด ... มันแปลก แต่ที่มันไม่ออกnil
Muers

42

printเอาท์พุทแต่ละโต้แย้งตามด้วย$,ที่จะตามมาด้วย$stdout $\มันเทียบเท่ากับargs.join($,) + $\

putsชุดทั้งสอง$,และ$\เพื่อ "\ n" printและจากนั้นจะเป็นสิ่งเดียวกับ แตกต่างที่สำคัญการที่แต่ละอาร์กิวเมนต์putsเป็นสายใหม่ที่มี

คุณสามารถrequire 'english'ที่จะเข้าถึงตัวแปรทั่วโลกผู้ที่มีชื่อที่ใช้งานง่าย


คำแนะนำที่ดีเกี่ยวกับenglishlib
lacostenycoder

18

เอกสาร APIให้คำแนะนำที่ดี:

print() → nil

print(obj, ...) → nil

เขียนวัตถุที่กำหนด (s) เพื่อiOS nilผลตอบแทน

ต้องเปิดสตรีมเพื่อการเขียน แต่ละวัตถุที่กำหนดซึ่งไม่ใช่สตริงจะถูกแปลงโดยการเรียกto_sใช้เมธอด $_เมื่อเรียกโดยไม่มีข้อโต้แย้งพิมพ์เนื้อหาของ

หาก$,ไม่ได้แยกเอาท์พุทฟิลด์ ( ) nilมันจะถูกแทรกระหว่างวัตถุ หาก$\ไม่ได้แยกเอาท์พุทบันทึก ( ) nilมันจะผนวกเข้ากับเอาท์พุท

...

puts(obj, ...) → nil

เขียนวัตถุที่กำหนด (s) เพื่อiOS เขียนขึ้นบรรทัดใหม่หลังจากที่ไม่ได้ลงท้ายด้วยลำดับการขึ้นบรรทัดใหม่ nilผลตอบแทน

ต้องเปิดสตรีมเพื่อการเขียน หากถูกเรียกพร้อมกับอาเรย์อาร์กิวเมนต์ให้เขียนแต่ละองค์ประกอบในบรรทัดใหม่ แต่ละวัตถุที่กำหนดที่ไม่ใช่สตริงหรืออาร์เรย์จะถูกแปลงโดยการเรียกto_sใช้เมธอด หากถูกเรียกโดยไม่มีอาร์กิวเมนต์เอาต์พุตจะขึ้นบรรทัดใหม่เดียว

ทดลองเล็กน้อยกับคะแนนที่ระบุข้างต้นความแตกต่างที่ดูเหมือนจะเป็น:

  • เรียกว่ามีหลายอาร์กิวเมนต์printแยกพวกเขาโดย 'แยกเขตเอาท์พุท' $,(ซึ่งเริ่มต้นที่ไม่มีอะไร) ในขณะที่putsแยกพวกเขาโดยการขึ้นบรรทัดใหม่ putsใส่บรรทัดใหม่หลังจากอาร์กิวเมนต์สุดท้ายในขณะที่printไม่

    2.1.3 :001 > print 'hello', 'world'
    helloworld => nil 
    2.1.3 :002 > puts 'hello', 'world'
    hello
    world
     => nil
    2.1.3 :003 > $, = 'fanodd'
     => "fanodd" 
    2.1.3 :004 > print 'hello', 'world'
    hellofanoddworld => nil 
    2.1.3 :005 > puts 'hello', 'world'
    hello
    world
     => nil
  • putsปลดอาร์เรย์โดยอัตโนมัติในขณะที่printไม่:

    2.1.3: 001> พิมพ์ [1, [2, 3]], [4]
    [1, [2, 3]] [4] => ไม่มี 
    2.1.3: 002> ทำให้ [1, [2, 3]], [4]
    1
    2
    3
    4
     => ไม่มี
  • printโดยไม่มีการขัดแย้งพิมพ์$_(สิ่งสุดท้ายที่อ่านโดยgets) ในขณะที่putsพิมพ์ขึ้นบรรทัดใหม่:

    2.1.3 :001 > gets
    hello world
     => "hello world\n" 
    2.1.3 :002 > puts
    
     => nil 
    2.1.3 :003 > print
    hello world
     => nil
  • printเขียนตัวคั่นเร็กคอร์ดเอาต์พุต$\หลังจากสิ่งที่พิมพ์ขณะที่putsละเว้นตัวแปรนี้:

    mark@lunchbox:~$ irb
    2.1.3 :001 > $\ = 'MOOOOOOO!'
     => "MOOOOOOO!" 
    2.1.3 :002 > puts "Oink! Baa! Cluck! "
    Oink! Baa! Cluck! 
     => nil 
    2.1.3 :003 > print "Oink! Baa! Cluck! "
    Oink! Baa! Cluck! MOOOOOOO! => nil

4

putsโทรหาto_sอาร์กิวเมนต์แต่ละตัวและเพิ่มบรรทัดใหม่ให้กับแต่ละสตริงหากไม่ได้ลงท้ายด้วยบรรทัดใหม่ เพียงแค่การส่งออกในแต่ละข้อโต้แย้งโดยการเรียกของพวกเขาprintto_s

ตัวอย่างเช่น puts "one two":: one two

{บรรทัดใหม่}

puts "one two\n": one two

{new line} #puts จะไม่เพิ่มบรรทัดใหม่ในผลลัพธ์เนื่องจากสตริงจะลงท้ายด้วยบรรทัดใหม่

print "one two": one two

print "one two\n": one two

{บรรทัดใหม่}

และมีวิธีการส่งออกอื่น: p

สำหรับแต่ละอ็อบเจ็กต์เขียน obj.inspect โดยตรงแล้วตามด้วย newline ไปยังเอาต์พุตมาตรฐานของโปรแกรม

มันจะมีประโยชน์ในการส่งข้อความการดีบัก p "aa\n\t":aa\n\t


-1

หากคุณต้องการที่จะส่งออกอาร์เรย์ภายในสตริงโดยใช้putsคุณจะได้รับผลลัพธ์เช่นเดียวกับถ้าคุณกำลังใช้print:

puts "#{[0, 1, nil]}":
[0, 1, nil]

แต่ถ้าไม่ได้อยู่ภายในสตริงที่ยกมาแล้วใช่ putsความแตกต่างเพียงอย่างเดียวคือระหว่างบรรทัดใหม่เมื่อเราใช้


1
-1 ด้วยเหตุผลสองประการ ประการแรกการขาดความชัดเจน: ฉันไม่เข้าใจสิ่งที่เริ่มต้น "แต่ ... " ที่นี่มีจุดประสงค์เพื่อให้ติดตามและฉันไม่เข้าใจสิ่งที่ "ใช่" ในย่อหน้าสุดท้ายกำลังตอบกลับ ประการที่สองสำหรับการขาดความถูกต้อง: คุณบอกว่าใช้printfแทนputsรหัสตัวอย่างของคุณจะให้ผลลัพธ์เหมือนกัน แต่จริงๆแล้วมันไม่ได้ putsตัวแปรเพิ่มขึ้นบรรทัดใหม่ในตอนท้ายในขณะที่printfหนึ่งไม่ได้เช่นเดียวกับกรณีที่มีอาร์เรย์ไม่มีการสอดแทรกเข้าไปในสตริง (จำเป็นเช่นนั้นเนื่องจากการแก้ไขเกิดขึ้นเมื่อประเมินสตริงตามตัวอักษร)
Mark Amery

Aha! หลังจากอ่านคำตอบอื่น ๆ ฉันคิดว่าฉันเข้าใจ - คุณตั้งใจจะตอบกลับไปที่stackoverflow.com/a/14534145/1709587หรือไม่ ไม่ว่าในกรณีใดมันไม่ได้เป็นคำตอบที่แท้จริง
Mark Amery
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.