web-dev-qa-db-fra.com

Que font \ t et \ b?

J'attends cette simple ligne de code

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

pour remplacer "o" par "\ t" et produire la sortie suivante

fo     bar

(en supposant que la tabulation se produit tous les 8 caractères). Au contraire je reçois

foo    bar

Il semble que mon shell interprète\b comme "déplace les curseurs d’une position" et\t comme "déplace le curseur à la tabulation suivante". Ce comportement est-il spécifique au shell dans lequel j'exécute le code? Devrais-je m'attendre à un comportement différent sur des systèmes différents?

30
cimere

Backspace et tab permettent de déplacer la position du curseur. Ni est vraiment un caractère "imprimable".

Votre code dit:

  1. imprimer "foo"
  2. recule le curseur d'une case
  3. déplace le curseur vers le prochain tabstop
  4. sortie "bar".

Pour obtenir le résultat attendu, vous avez besoin de printf("foo\b \tbar"). Notez le 'espace' supplémentaire. Ça dit:

  1. sortie "foo"
  2. recule le curseur d'une case
  3. affiche un '' (remplace le second 'o').
  4. déplace le curseur vers le prochain tabstop
  5. sortie "bar".

La plupart du temps, il est inapproprié d'utiliser des tabulations et des espaces arrière pour formater la sortie de votre programme. Apprenez à utiliser printf() spécificateurs de formatage. Le rendu des onglets peut varier considérablement en fonction de l'affichage de la sortie.

Ce petit script montre un moyen de modifier le rendu des onglets de votre terminal. Testé sur Ubuntu + gnome-terminal:

#!/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"

Regarde aussi man setterm et regtabs.

Et si vous redirigez votre sortie ou écrivez simplement dans un fichier, les onglets seront généralement affichés avec un nombre de caractères inférieur au caractère standard de 8 caractères, en particulier dans les éditeurs de "programmation" et les IDE.

Donc en d'autres termes:

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

IMHO, les onglets en général sont rarement appropriés pour quoi que ce soit. Une exception peut être la génération de sortie pour un programme nécessitant des fichiers d'entrée de valeurs séparées par des tabulations (similaire à la valeur séparée par des virgules).

Retour arrière '\b' est une histoire différente ... il ne devrait jamais être utilisé pour créer un fichier texte, car un éditeur de texte cracherait des ordures. Mais il a de nombreuses applications dans l’écriture de programmes interactifs en ligne de commande qui ne peuvent pas être accomplies avec des chaînes de formatage seules. Si vous en avez souvent besoin, jetez un œil à "ncurses", qui vous donne un bien meilleur contrôle de l’affichage de votre sortie sur l’écran du terminal. Et typiquement, puisqu'il s'agit de 2011 et non de 1995, une interface graphique est généralement plus facile à gérer pour les programmes hautement interactifs. Mais encore une fois, il y a des exceptions. C'est comme écrire un serveur telnet ou une console pour un nouveau langage de script.

30
Brian McFarland

Non, c'est plus ou moins ce qu'ils sont censés faire.

En C (et dans de nombreuses autres langues), vous pouvez insérer des caractères difficiles à voir/taper à l'aide de la notation \:

  • \a Est alert/bell
  • \b Est backspace/rubout
  • \n Est une nouvelle ligne
  • \r Est un retour chariot (retour à la marge de gauche)
  • \t Est l'onglet

Vous pouvez également spécifier la valeur octale de n'importe quel caractère à l'aide de \0nnn, ou la valeur hexadécimale de tout caractère à l'aide de \xnn.

  • EG: la valeur ASCII de _ Est 137 octal, 5f hex, de sorte qu'elle peut également être saisie \0137 Ou \x5f, Si votre clavier n'a pas t avoir une clé _ ou quelque chose. Ceci est plus utile pour les caractères de contrôle comme NUL (\0) Et ESC (\033)

En tant que personne a posté (puis supprimé sa réponse avant que je puisse la +1), il existe également des réponses moins fréquemment utilisées:

  • \f Est un formulaire/une nouvelle page (page éjectée de l'imprimante)
  • \v Est un onglet vertical (déplacez vers le bas d'une ligne, sur la même colonne)

Sur les écrans, \f Fonctionne généralement de la même manière que \v, Mais sur certaines imprimantes/télétypes, il ira jusqu'au formulaire/à la feuille de papier suivante.

33
BRPocock

La norme C (en fait C99, je ne suis pas à jour) dit:

Les séquences d'échappement alphabétiques représentant des caractères non graphiques dans le jeu de caractères d'exécution sont destinées à générer des actions sur les dispositifs d'affichage, comme suit:

\b(backspace) Déplace la position active à la position précédente sur la ligne en cours. [...]

\t(onglet horizontal) Déplace la position active vers la prochaine position de tabulation horizontale sur la ligne en cours. [...]

Les deux ne font que déplacer la position active, ni sont supposés écrire aucun caractère sur ou sur un autre caractère. Pour écraser avec un espace, vous pouvez essayer: puts("foo\b \tbar"); mais notez que sur certains périphériques d'affichage - disons une imprimante à marguerite - le o affichera l'espace transparent.

2
CB Bailey

Ce comportement est spécifique au terminal et spécifié par l’émulateur de terminal que vous utilisez (par exemple, xterm) et la sémantique du terminal qu’il fournit. Le comportement terminal est très stable depuis 20 ans et vous pouvez raisonnablement vous fier à la sémantique de \b.

1
thiton

\t Est le caractère de tabulation et fait exactement ce que vous anticipez en vous basant sur l'action de \b - il passe à la tabulation suivante, puis est décrémenté, puis passe à la suivante. tab stop (qui est dans ce cas le même tab stop, à cause du \b.

0
Jonathan Rich