Управляющий символ «backspace» '\ b': неожиданное поведение?


101

Так что я , наконец , чтение через K & R , и я узнал кое - что в течение первых нескольких страниц, что есть экранирующий символ забой, \b.

Итак, я иду проверить это, и есть очень странное поведение:

#include <stdio.h>

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

На выходе

hello wodl

Кто-нибудь может это объяснить?

Ответы:


145

Ваш результат будет зависеть от того, в каком терминале или консольной программе вы работаете, но да, в большинстве случаев\b это неразрушающий backspace. Он перемещает курсор назад, но не стирает то, что там есть.

Итак, со hello worlстороны, код выводит

привет Ворл
          ^

... (где ^показано, где находится курсор) Затем он выводит два \bсимвола, которые перемещают курсор назад на два места без стирания (на вашем терминале):

привет Ворл
        ^

Обратите внимание, что теперь курсор находится на r. Затем он выводит d, который перезаписывает rи дает нам:

привет, водл
         ^

Наконец, он выводит \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");
привет Ворл
          ^ <= указатель на "печатающую головку"
            /* part2 */
            printf("\b");
привет Ворл
         ^ <= указатель на "печатающую головку"
            /* part3 */
            printf("\b");
привет Ворл
        ^ <= указатель на "печатающую головку"
            /* part4 */
            printf("d\n");
привет, водл

^ <= указатель на «печатающую головку» на следующей строке

Если курсор после части 4 находится на букве «l», не следует ли его заменить на «\ n»? (в результате
получается

@lucas_turci: дело в том, что у '\n'него нет изображения на экране. То, что уже есть, остается неизменным; не заменяется пробелом или любым другим символьным представлением.
pmg 06

44

Если вам нужен деструктивный backspace, вам понадобится что-то вроде

"\b \b"

т.е. пробел, пробел и еще один пробел.


Это все еще оставляет пробел, не так ли?
Pacerier

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

1
Что делать, если нет следующего символа?
Pacerier

Тогда это не имеет значения, правда?
Питер К.

1
Хм. Если на вашем устройстве не реализована опция «удалить последний символ» (например, DEL / 0x7f), я в тупике.
Питер К.

8

Нетрудно объяснить ... Это похоже на набор текста hello worl, двойное нажатие клавиши со стрелкой влево, набор текста dи нажатие клавиши со стрелкой вниз.

По крайней мере, как я заключаю ваш терминал interpeting \bи \nкоды.

Перенаправьте вывод в файл, и я уверен, вы получите что-то совершенно другое. Хотя вам, возможно, придется взглянуть на байты файла, чтобы увидеть разницу.

[редактировать]

Чтобы уточнить немного, это printfиспускает последовательность байтов:, hello worl^H^Hd^Jгде ^H- символ ASCII # 8 и ^Jявляется символом ASCII # 10. То, что вы видите на экране, зависит от того, как ваш терминал интерпретирует эти управляющие коды.


1

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


"привет, вод \ п"? Что это значит?
Элиас
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.