Что делают \ t и \ b? - PullRequest
       28

Что делают \ t и \ b?

30 голосов
/ 28 декабря 2011

Я ожидаю эту простую строку кода

printf("foo\b\tbar\n");

заменить "o" на "\ t" и произвести следующий вывод

fo     bar

(при условии, что табуляция происходит каждые 8 ​​символов). Наоборот, я получаю

foo    bar

Кажется, что моя оболочка интерпретирует \ b как "переместить курсоры на одну позицию назад", а \ t как "переместить курсор к следующей позиции табуляции". Это поведение специфично для оболочки, в которой я запускаю код? Стоит ли ожидать разного поведения в разных системах?

Ответы [ 5 ]

32 голосов
/ 28 декабря 2011

Нет, это более или менее то, что они должны делать.

В C (и многих других языках) вы можете вставлять трудно видимые / набираемые символы, используя обозначение \:

  • \a оповещение / звонок
  • \b Забой / размазка
  • \n является новой строкой
  • \r возврат каретки (возврат к левому полю)
  • \t является вкладкой

Вы также можете указать восьмеричное значение любого символа с помощью \0 nnn или шестнадцатеричное значение любого символа с помощью \x nn .

  • EG: значение ASCII _ - восьмеричное 137, шестнадцатеричное 5f, поэтому его также можно ввести \0137 или \x5f, если на вашей клавиатуре не было клавиши _ или чего-то еще. Это более полезно для управляющих символов, таких как NUL (\0) и ESC (\033)

Как кто-то написал (затем удалил свой ответ, прежде чем я мог +1 +1), есть и некоторые менее часто используемые:

  • \f - это подача формы / новая страница (извлечение страницы из принтера)
  • \v - вертикальная вкладка (сдвинуться на одну строку вниз в том же столбце)

На экранах \f обычно работает так же, как \v, но на некоторых принтерах / телетайпах это будет перейти к следующей форме / листу бумаги.

30 голосов
/ 28 декабря 2011

Клавиши Backspace и Tab перемещают позицию курсора. Ни один из них не является «печатным» персонажем.

Ваш код говорит:

  1. печать "foo"
  2. переместить курсор назад на один пробел
  3. переместить курсор вперед к следующей вкладке
  4. вывод "бар".

Чтобы получить ожидаемый результат, вам нужно printf("foo\b \tbar"). Обратите внимание на дополнительный «пробел». Это говорит:

  1. вывод "foo"
  2. переместить курсор назад на один пробел
  3. выводит '' (это заменяет второе 'o').
  4. переместить курсор вперед к следующей вкладке
  5. вывод "бар".

В большинстве случаев нецелесообразно использовать вкладки и клавишу Backspace для форматирования вывода вашей программы. Научитесь использовать printf() спецификаторы форматирования. Рендеринг вкладок может сильно различаться в зависимости от того, как просматривается вывод.

Этот небольшой скрипт показывает один из способов изменить отображение вкладок вашего терминала. Протестировано на Ubuntu + gnome-терминал:

#!/bin/bash
tabs -8 
echo -e "\tnormal tabstop"
for x in `seq 2 10`; do
  tabs $x
  echo -e "\ttabstop=$x"
 done

tabs -8
echo -e "\tnormal tabstop"

Также см. man setterm и regtabs.

И если вы перенаправляете свои выходные данные или просто записываете в файл, вкладки довольно часто будут отображаться как меньше, чем стандартные 8 символов, особенно в «программирующих» редакторах и IDE.

Итак, другими словами:

printf("%-8s%s", "foo", "bar"); /* this will ALWAYS output "foo     bar" */
printf("foo\tbar"); /* who knows how this will be rendered */

ИМХО, вкладки вообще редко бывают подходящими для чего-либо. Исключением может быть генерация вывода для программы, для которой требуются входные файлы со значениями, разделенными табуляцией (аналогично значению, разделенному запятыми).

Backspace '\b' - это отдельная история ... ее никогда не следует использовать для создания текстового файла, поскольку он просто заставит текстовый редактор выплеснуть мусор. Но у него есть много приложений для написания интерактивных программ командной строки, которые не могут быть выполнены только с помощью строк формата. Если вам это сильно нужно, посмотрите «ncurses», что дает вам намного лучший контроль над тем, куда выводится ваш вывод на экране терминала. И, как правило, с 2011 года, а не с 1995 года, GUI-интерфейс обычно проще для высокоинтерактивных программ. Но опять же, есть исключения. Как написать сервер или консоль telnet для нового языка сценариев.

2 голосов
/ 28 декабря 2011

Стандарт C (на самом деле C99, я не в курсе) гласит:

Буквенные escape-последовательности, представляющие неграфические символы в наборе исполнительных символов, предназначены для выполнения действий на устройствах отображения следующим образом:

\b (возврат) Перемещение активной позиции на предыдущую позицию в текущей строке.[...]

\t (горизонтальная табуляция) Перемещает активную позицию в следующую горизонтальную позицию табуляции в текущей строке.[...]

Оба просто перемещают активную позицию, ни один не должен писать какой-либо символ над другим символом или над ним.Чтобы перезаписать пробел, вы можете попробовать: puts("foo\b \tbar");, но учтите, что на некоторых устройствах отображения - скажем, принтер с гирляндным колесом - o покажет прозрачное пространство.

1 голос
/ 28 декабря 2011

Это поведение зависит от терминала и определяется используемым вами эмулятором терминала (например, xterm) и семантикой терминала, которую он предоставляет.Поведение терминала было очень стабильным в течение последних 20 лет, и вы можете разумно полагаться на семантику \b.

0 голосов
/ 28 декабря 2011

\t является символом табуляции и делает именно то, что вы ожидаете, основываясь на действии \b - он переходит к следующей остановке табуляции, затем уменьшается и затем переходит к следующей остановке табуляции ( который в этом случае является той же самой табуляцией из-за \b.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...