อักขระหลีก "backspace" '\ b': พฤติกรรมที่ไม่คาดคิด?


102

ในที่สุดฉันก็อ่านK&Rและฉันได้เรียนรู้บางอย่างในสองสามหน้าแรกว่ามีอักขระหลีกย้อน\bกลับ

ดังนั้นฉันไปทดสอบดูและมีพฤติกรรมแปลก ๆ :

#include <stdio.h>

main ()
{
    printf("hello worl\b\bd\n");
}

ผลลัพธ์คือ

hello wodl

ใครช่วยอธิบายเรื่องนี้

คำตอบ:


147

ผลลัพธ์ของคุณจะแตกต่างกันไปขึ้นอยู่กับประเภทของโปรแกรมเทอร์มินัลหรือคอนโซลที่คุณใช้งานอยู่ แต่ใช่ส่วนใหญ่\bเป็นbackspace ที่ไม่ทำลาย มันเลื่อนเคอร์เซอร์ไปข้างหลัง แต่ไม่ได้ลบสิ่งที่อยู่ที่นั่น

ดังนั้นสำหรับhello worlส่วนนี้โค้ดจะแสดงผล

สวัสดี worl
          ^

... (ที่^แสดงว่าเคอร์เซอร์อยู่ที่ไหน) จากนั้นจะแสดง\bอักขระสองตัวซึ่งเลื่อนเคอร์เซอร์ไปข้างหลังสองตำแหน่งโดยไม่ต้องลบ (บนเทอร์มินัลของคุณ):

สวัสดี worl
        ^

สังเกตว่าตอนนี้เคอร์เซอร์อยู่ที่r. จากนั้นจะส่งออกdซึ่งเขียนทับrและให้เรา:

สวัสดี wodl
         ^

สุดท้ายผลลัพธ์จะออก\nมาซึ่งเป็นบรรทัดใหม่ที่ไม่ทำลายล้าง (อีกครั้งในเทอร์มินัลส่วนใหญ่รวมถึงของคุณด้วย) ดังนั้นจึงlไม่เปลี่ยนแปลงและเคอร์เซอร์จะถูกย้ายไปที่จุดเริ่มต้นของบรรทัดถัดไป


1
ถ้าไม่ลบแล้วทำไม "r" ถึงหายไป?
cesoid

1
@cesoid: "ผลลัพธ์ของคุณจะแตกต่างกันไปขึ้นอยู่กับประเภทของโปรแกรมเทอร์มินัลหรือคอนโซลที่คุณใช้"
TJ Crowder

เพียงแค่ว่าตัวอย่างของคุณไม่พอดีกับผลลัพธ์ดังนั้นจึงไม่ใช่ตัวอย่างของคำอธิบายที่เป็นไปได้
cesoid

5
@cesoid rจะถูกแทนที่ด้วยd. คำอธิบายยังพอดี
syockit

1
@cesoid: น่าสนใจเกี่ยวกับเทอร์มินัล ใน Windows เทอร์มินัลcmd.exeและcommand.comเทอร์มินัลมักจะไม่แทรก (คุณสามารถใช้ปุ่ม Ins เพื่อสลับพฤติกรรม) ฉันรู้สึกประหลาดใจที่พบว่า Gnome Terminal ในคอมพิวเตอร์หลัก * nix ของฉันมักจะแทรกอยู่เสมอดูเหมือนว่าจะไม่มีความต้องการในการสลับน้อยกว่ามากนักโดยอิงจากปุ่ม Ins ไม่เคยสังเกตเห็นมาก่อน เห็นได้ชัดว่าฉันแทบไม่ต้องการการพิมพ์ :-)
TJ Crowder

122
..........
^ <= ชี้ไปที่ "หัวพิมพ์"
            /* part1 */
            printf("hello worl");
สวัสดี worl
          ^ <= ชี้ไปที่ "หัวพิมพ์"
            /* part2 */
            printf("\b");
สวัสดี worl
         ^ <= ชี้ไปที่ "หัวพิมพ์"
            /* part3 */
            printf("\b");
สวัสดี worl
        ^ <= ชี้ไปที่ "หัวพิมพ์"
            /* part4 */
            printf("d\n");
สวัสดี wodl

^ <= ชี้ไปที่ "หัวพิมพ์" ในบรรทัดถัดไป

ถ้าเคอร์เซอร์หลังส่วนที่ 4 อยู่ที่ตัวอักษร 'l' ไม่ควรแทนที่ด้วย '\ n' หรือไม่? (ส่งผลให้ "สวัสดี wor")
lucas_turci

@lucas_turci: สิ่งนี้คือ'\n'ไม่มีการแสดงบนหน้าจอ สิ่งที่มีอยู่แล้วยังคงเหมือนเดิม ไม่ถูกแทนที่ด้วยช่องว่างหรือการแทนอักขระอื่นใด
59

45

หากคุณต้องการ backspace ที่ทำลายล้างคุณจะต้องมีสิ่งต่างๆเช่น

"\b \b"

เช่น backspace ช่องว่างและ backspace อื่น


นี่ยังทิ้งอักขระเว้นวรรคอยู่ใช่หรือไม่?
Pacerier

ใช่ แต่คำที่ตามมา\bจะหมายถึงอักขระเอาต์พุตถัดไปจะเขียนทับ
Peter K.

1
จะเกิดอะไรขึ้นถ้าไม่มีตัวละครที่ตามมา?
Pacerier

แล้วมันไม่สำคัญใช่มั้ย?
Peter K.

1
อืม. เว้นแต่อุปกรณ์ของคุณจะใช้ตัวเลือก "ลบอักขระสุดท้าย" (เช่น DEL / 0x7f) ฉันนิ่งงัน
Peter K.

8

ไม่ยากเกินไปที่จะอธิบาย ... เช่นการพิมพ์hello worlกดปุ่มลูกศรซ้ายสองครั้งพิมพ์dและกดปุ่มลูกศรลง

อย่างน้อยนั่นคือวิธีที่ฉันอนุมานว่าเทอร์มินัลของคุณเชื่อมต่อกับรหัส\bและ\n

เปลี่ยนเส้นทางผลลัพธ์ไปยังไฟล์และฉันพนันได้เลยว่าคุณจะได้อย่างอื่นทั้งหมด แม้ว่าคุณอาจต้องดูไบต์ของไฟล์เพื่อดูความแตกต่าง

[แก้ไข]

เพื่ออธิบายรายละเอียดเล็กน้อยสิ่งนี้printfจะแสดงลำดับของไบต์: hello worl^H^Hd^Jโดยที่^Hอักขระ ASCII # 8 ^Jคืออักขระ ASCII # 10 สิ่งที่คุณเห็นบนหน้าจอขึ้นอยู่กับว่าเครื่องของคุณตีความรหัสควบคุมเหล่านั้นอย่างไร


1

ใช้ backspace เดียวหลังอักขระแต่ละตัว printf("hello wor\bl\bd\n");


"สวัสดี wod \ n"? นั่นหมายความว่าอย่างไร?
Elias Hasle

ผู้ตอบเพียงต้องการแสดงให้เห็นว่าจะสร้างพฤติกรรมตามที่ OP คาดไว้อย่างไร
Yolomep
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.