Характер втечі "backspace" "\ b": несподівана поведінка?


101

Отже, я нарешті читаю K&R , і я дізнався щось на перших сторінках про те, що є символ втечі із зворотної області \b.

Тож я йду перевірити це, і є дуже дивна поведінка:

#include <stdio.h>

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

Вихід є

hello wodl

Хтось може це пояснити?

Відповіді:


145

Результат варіюватиметься залежно від того, на якому терміналі чи консольній програмі ви працюєте, але так, для більшості \b- це неруйнівна резервна область. Він переміщує курсор назад, але не стирає те, що там є.

Отже, для hello worlчастини, код виводить

привіт Worl
          ^

... (де ^показано, де знаходиться курсор) Потім він видає два \bсимволи, які переміщують курсор назад на два місця, не стираючи (на своєму терміналі):

привіт Worl
        ^

Зверніть увагу, що курсор зараз на r. Потім він виводить d, що перезаписує rта дає нам:

привіт водл
         ^

Нарешті, він виводить \n, що є неруйнівним новим рядком (знову ж таки, на більшості терміналів, включаючи, мабуть, і ваш), тому значення lзалишається незмінним і курсор переміщується на початок наступного рядка.


1
Якщо це не стирається, то чому "r" пішов?
— цезоїд

1
@cesoid: "Ваш результат буде залежати від того, на якому терміналі чи консольній програмі ви працюєте"
— TJ Crowder

Просто ваш приклад не відповідає результату, тому це не приклад можливого пояснення.
— цезоїд

5
@cesoid The 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");
привіт водл

^ <= вказівник на "друкуючу головку" у наступному рядку

Якщо курсор після частини 4 знаходиться на букві 'l', чи не слід його замінювати на '\ n'? (в результаті "привіт Wor")
— lucas_turci

@lucas_turci: річ у тому, що '\n'на екрані немає представництва. Те, що вже є, залишається тим самим; не замінюється пробілом або будь-яким іншим поданням символів.
— pmg

44

Якщо ви хочете руйнувати задній простір, вам знадобиться щось на кшталт

"\b \b"

тобто простору, простору та іншої.


Це все ще залишає космічний персонаж, чи не так?
— Pacerier

Ну, так, але подальший \bозначатиме, що наступний вихідний символ замінить його.
— Петро К.

1
Що робити, якщо немає наступного символу?
— Pacerier

Тоді це не має значення, чи не так?
— Петро К.

1
Хм. Якщо ваш пристрій не реалізує параметр "видалити останній символ" (наприклад, DEL / 0x7f), я наткнувся.
— Петро К.

8

Не надто важко пояснити ... Це як набрати текст hello worl, двічі натиснути клавішу зі стрілкою ліворуч, набрати dта натиснути клавішу зі стрілкою вниз.

Принаймні, саме так я вважаю, що ваш термінал перетинає \bі \nкоди.

Перенаправляйте вихід на файл, і я сподіваюся, що ви отримаєте щось інше цілком. Хоча вам, можливо, доведеться подивитися на байти файлу, щоб побачити різницю.

[редагувати]

Щоб трохи уточнити, це printfвипромінює послідовність байтів: hello worl^H^Hd^Jде ^Hсимвол ASCII № 8 і ^Jсимвол ASCII №10. Те, що ви бачите на екрані, залежить від того, як ваш термінал інтерпретує ці коди управління.


1

Використовуйте один зворотний простір після кожного символу printf("hello wor\bl\bd\n");


"привіт wod \ n"? Що це означає?
— Еліас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.