Le caractère d'échappement «retour arrière» '\ b': comportement inattendu?

101

Donc , je suis enfin la lecture par K & R , et j'appris quelque chose dans les premières pages, qu'il ya un caractère d'échappement backspace, \b.

Je vais donc le tester, et il y a un comportement très étrange:

#include <stdio.h>

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

La sortie est

hello wodl

Quelqu'un peut-il expliquer cela?

Piste de l'Oregon
la source

Réponses:

145

Votre résultat variera en fonction du type de terminal ou de programme de console sur lequel vous vous trouvez, mais oui, la plupart \bsont un retour arrière non destructif . Il déplace le curseur vers l'arrière, mais n'efface pas ce qu'il y a.

Donc pour la hello worlpartie, le code sort

bonjour le monde
          ^

... (où ^montre où se trouve le curseur) Ensuite, il sort deux \bcaractères qui déplace le curseur de deux places vers l'arrière sans effacer (sur votre terminal):

bonjour le monde
        ^

Notez que le curseur est maintenant sur le r. Ensuite, il sort d, ce qui écrase le ret nous donne:

bonjour wodl
         ^

Enfin, il sort \n, qui est une nouvelle ligne non destructive (encore une fois, sur la plupart des terminaux, y compris apparemment le vôtre), de sorte que le lreste inchangé et le curseur est déplacé au début de la ligne suivante.

TJ Crowder
la source
1
S'il ne s'efface pas, pourquoi le «r» a-t-il disparu?
cesoid
1
@cesoid: "Votre résultat variera en fonction du type de terminal ou de programme de console sur lequel vous vous trouvez"
TJ Crowder
C'est juste que votre exemple ne correspond pas à la sortie, donc ce n'est pas un exemple d'explication possible.
cesoid
5
@cesoid Le rest remplacé par d. L'explication est toujours valable.
syockit
1
@cesoid: Intéressant pour le terminal. Dans Windows, les terminaux cmd.exeet command.comne s’insèrent pas toujours (vous pouvez utiliser la touche Ins pour changer le comportement). J'ai été surpris de constater que Gnome Terminal sur mon ordinateur principal * nix insère toujours, ne semble même pas avoir une préférence pour cela et encore moins basculer en fonction de la touche Ins. Jamais remarqué cela auparavant. De toute évidence, je ne veux presque jamais de dactylographie. :-)
TJ Crowder
122
..........
^ <= pointeur vers "tête d'impression"
            /* part1 */
            printf("hello worl");
bonjour le monde
          ^ <= pointeur vers "tête d'impression"
            /* part2 */
            printf("\b");
bonjour le monde
         ^ <= pointeur vers "tête d'impression"
            /* part3 */
            printf("\b");
bonjour le monde
        ^ <= pointeur vers "tête d'impression"
            /* part4 */
            printf("d\n");
bonjour wodl

^ <= pointeur vers "tête d'impression" sur la ligne suivante
pmg
la source
Si le curseur après la partie 4 est à la lettre «l», ne devrait-il pas être remplacé par le «\ n»? (résultant en "hello wor")
lucas_turci
@lucas_turci: le fait est que le '\n'n'a pas de représentation à l'écran. Ce qui est déjà là reste le même; pas remplacé par un espace ou toute autre représentation de caractère.
pmg
44

Si vous voulez un retour arrière destructeur, vous aurez besoin de quelque chose comme

"\b \b"

c'est-à-dire un retour arrière, un espace et un autre retour arrière.

Peter K.
la source
Cela laisse toujours le caractère d'espace, n'est-ce pas?
Pacerier
Eh bien, oui, mais le suivant \bsignifiera que le prochain caractère de sortie l'écrasera.
Peter K.
1
Et s'il n'y a pas de personnage suivant?
Pacerier
Alors ça n'a pas d'importance, n'est-ce pas?
Peter K.
1
Hmm. À moins que votre appareil n'implémente une option «supprimer le dernier caractère» (par exemple DEL / 0x7f), je suis perplexe.
Peter K.
8

Pas trop difficile à expliquer ... C'est comme taper hello worl, dappuyer deux fois sur la touche fléchée gauche, taper et appuyer sur la touche fléchée bas.

Du moins, c'est ainsi que j'en déduis que votre terminal interpelle les codes \bet \n.

Redirigez la sortie vers un fichier et je parie que vous obtenez tout autre chose. Bien que vous deviez peut-être regarder les octets du fichier pour voir la différence.

[Éditer]

Pour élaborer un peu, cela printfémet une séquence d'octets:, hello worl^H^Hd^J^Hest le caractère ASCII # 8 et ^Jest le caractère ASCII # 10. Ce que vous voyez sur votre écran dépend de la façon dont votre terminal interprète ces codes de contrôle.

Nemo
la source
1

Utilisez un seul retour arrière après chaque caractère printf("hello wor\bl\bd\n");

Dorothée
la source
"bonjour wod \ n"? Qu'est-ce que ça veut dire?
Elias Hasle