Итак, я немного поиграл с разными строками, и, насколько я могу судить, консоль Windows следует следующим правилам:
- После обычного символа,
\b
перемещает курсор на одну позицию влево. (Это именно то, что вы ожидаете.)
- После того, как
\t
переместил курсор n позиций вправо, a \b
переместит курсор n позиции влево. (Я не уверен, что это то, чего я ожидал, но это имеет смысл.)
- После того, как
\b
переместил курсор * на 1016 * n позиций влево, секунда \b
переместит курсор на n позиций влево. (Это явно не предполагаемое поведение. Я не решаюсь использовать термин «ошибка», потому что я не знаю, было ли у них когда-либо намерение поддержать случай двух последовательных \b
с, но это явно не «особенность» ».)
- Я не до конца понимаю взаимодействие с символами новой строки. Достаточно сказать, что в некоторых случаях
\b
способен перейти к предыдущей строке, в то время как в большинстве случаев это не так; и что \n
ранее в том же операторе printf
может сильно повлиять на взаимодействие \b
с \t
, даже «на расстоянии» (так сказать).
Итак, в вашем примере f\t\b\bg\n
, f
печатает f
и перемещает курсор на одну позицию вправо; \t
печатает семь пробелов и перемещает курсор на семь позиций вправо (до следующей позиции табуляции); первый \b
ничего не печатает и перемещает курсор на семь позиций влево (отмена \t
); вторая \b
ничего не печатает и перемещает курсор еще на семь позиций влево (если вы не шутите, на предыдущей строке ); g
печатает g
(в предыдущей строке) и предположительно перемещает курсор на одну позицию вправо; и \n
перемещает курсор назад к исходной строке.
Теперь есть два небольших различия между тем, что вы наблюдали, и тем, что я наблюдал. Во-первых, я заметил g
в конце предыдущей строки (чтобы увидеть его, прокрутите вправо):
$ gcc -Wall -Wextra tmp.c -o tmp.exe && ./tmp.exe
tmp.c: In function 'main':
tmp.c:3:14: warning: unused parameter 'argc' [-Wunused-parameter]
tmp.c:3:26: warning: unused parameter 'argv' [-Wunused-parameter] g
f
что вы, очевидно, не сделали; это я приписываю тому факту, что я запускал это с консоли, тогда как вы запускали его через Visual Studio, поэтому у вас просто не было предыдущей строки для печати g
. Во-вторых, вы наблюдали Press any key to continue.
сразу после * f
(то есть, как в Visual Studio можно сказать, что консольное приложение закончилось), тогда как я заметил, что если я добавлю что-нибудь еще в конец строка, например, если моя строка была f\t\b\bg\nh\n
, то это что-то большее переписало f
. (Точно так же, если я прикрепил ; echo h
к концу команды Bash.) То есть, в то время как в моем тестировании \n
переместил курсор в начало исходной строки, в вашем тестировании Visual Studio каким-то образом знал, что напечатайте Press any key to continue.
после f
в строке. Но я не слишком одержим этим; Я действительно не знаю, как Visual Studio решает, где печатать Press any key to continue.
, и вполне возможно, что он использует что-то более сложное (или более "изощренное"), чем просто положение курсора.
Для полноты вот несколько примеров строк, которые, на мой взгляд, демонстрируют приведенные выше выводы:
printf console output
----------------------------------------------
"A\bB\n" B
"A\b\bB\n" B [see note 1]
"AB\bC\n" AC
"AB\b\bC\n" CB
"AB\b\b\bC\n" CB [see note 1]
"A\t\bB\n" AB
"A\t\t\b\bB\n" B [see note 2]
"A\tBB\t\b\bC\n" A C BB [see note 3]
Примечания:
- Избыток
\b
с, в этих случаях не перемещается на предыдущую строку.
- Первый
\t
перемещает семь пробелов; второй \t
двигается восемь; каждый \b
движется по восемь. Таким образом, B
заканчивается перезаписью A
.
- Второй
\t
перемещает только шесть пробелов, поэтому каждый \b
перемещается на шесть, и C
странным образом заканчивается в середине A
и BB
.