O caractere de escape “backspace” '\ b': comportamento inesperado?


101

Finalmente estou lendo K&R e aprendi algo nas primeiras páginas, que existe um caractere de escape de retrocesso \b,.

Então, vou testá-lo e há um comportamento muito estranho:

#include <stdio.h>

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

A saída é

hello wodl

Alguém pode explicar isso?

Respostas:


145

Seu resultado irá variar dependendo do tipo de terminal ou programa de console em que você estiver, mas sim, na maioria \bé um backspace não destrutivo . Ele move o cursor para trás, mas não apaga o que está lá.

Então, para a hello worlparte, as saídas de código

olá mundo
          ^

... (onde ^mostra onde o cursor está) Em seguida, ele produz dois \bcaracteres que movem o cursor dois lugares para trás sem apagar (em seu terminal):

olá mundo
        ^

Observe que o cursor está agora no r. Em seguida, ele produz d, que substitui o re nos dá:

olá wodl
         ^

Finalmente, ele produz \n, que é uma nova linha não destrutiva (novamente, na maioria dos terminais, incluindo aparentemente o seu), de forma que o lpermanece inalterado e o cursor é movido para o início da próxima linha.


1
Se não apagar, por que o "r" desapareceu?
— cesóide

1
@cesoid: "Seu resultado irá variar dependendo do tipo de terminal ou programa de console em que você estiver"
— TJ Crowder

Acontece que seu exemplo não se ajusta à saída, portanto, não é um exemplo de uma explicação possível.
— cesóide

5
@cesoid O ré substituído por d. A explicação ainda se encaixa.
— syockit de

1
@cesoid: Interessante sobre o terminal. No Windows, os terminais cmd.exee command.comnem sempre são inseridos (você pode usar a tecla Ins para alternar o comportamento). Fiquei surpreso ao descobrir que o Terminal Gnome no meu computador * nix principal sempre insere, nem parece ter uma preferência por isso, muito menos alternar com base na chave Ins. Nunca percebi isso antes. É claro que quase nunca quero datilografia. :-)
— TJ Crowder

122
..........
^ <= ponteiro para "cabeça de impressão"
            /* part1 */
            printf("hello worl");
olá mundo
          ^ <= ponteiro para "cabeça de impressão"
            /* part2 */
            printf("\b");
olá mundo
         ^ <= ponteiro para "cabeça de impressão"
            /* part3 */
            printf("\b");
olá mundo
        ^ <= ponteiro para "cabeça de impressão"
            /* part4 */
            printf("d\n");
olá wodl

^ <= ponteiro para "cabeça de impressão" na próxima linha

Se o cursor após a parte 4 estiver na letra 'l', ele não deveria ser substituído pelo '\ n'? (resultando em "hello wor")
— lucas_turci

@lucas_turci: o problema é que o '\n'não tem representação na tela. O que já está lá permanece o mesmo; não substituído por um espaço ou qualquer outra representação de caractere.
— pmg

44

Se você quiser um retrocesso destrutivo, você precisará de algo como

"\b \b"

ou seja, um backspace, um espaço e outro backspace.


Isso ainda deixa o personagem de espaço não é?
— Pacerier

Bem, sim, mas o subsequente \bsignificará que o próximo caractere de saída o substituirá.
— Peter K.

1
E se não houver nenhum personagem subsequente?
— Pacerier de

Então não importa, não é?
— Peter K.

1
Hmm. A menos que seu dispositivo implemente uma opção "excluir último caractere" (por exemplo, DEL / 0x7f), estou perplexo.
— Peter K.

8

Não é muito difícil de explicar ... Isso é como digitar hello worl, pressionar a tecla de seta para a esquerda duas vezes, digitar de pressionar a tecla de seta para baixo.

Pelo menos, é assim que deduzo que seu terminal está interpretando os códigos \be \n.

Redirecione a saída para um arquivo e aposto que você obterá algo totalmente diferente. Embora você possa ter que olhar os bytes do arquivo para ver a diferença.

[editar]

Para elaborar um pouco, isso printfemite uma sequência de bytes:, hello worl^H^Hd^Jonde ^Hé o caractere ASCII # 8 e ^Jé o caractere ASCII # 10. O que você vê em sua tela depende de como seu terminal interpreta esses códigos de controle.


1

Use um único backspace após cada caractere printf("hello wor\bl\bd\n");


"olá wod \ n"? O que isso significa?
— Elias Hasle
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.