The "backspace" escape character '\b': unexpected behavior?
Asked Answered
R

5

126

So I'm finally reading through K&R, and I learned something within the first few pages, that there is a backspace escape character, \b.

So I go to test it out, and there is some very odd behavior:

#include <stdio.h>

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

The output is

hello wodl

Can anyone explain this?

Rascal answered 22/7, 2011 at 16:7 Comment(0)
M
183

Your result will vary depending on what kind of terminal or console program you're on, but yes, on most \b is a nondestructive backspace. It moves the cursor backward, but doesn't erase what's there.

So for the hello worl part, the code outputs

hello worl
          ^

...(where ^ shows where the cursor is) Then it outputs two \b characters which moves the cursor backward two places without erasing (on your terminal):

hello worl
        ^

Note the cursor is now on the r. Then it outputs d, which overwrites the r and gives us:

hello wodl
         ^

Finally, it outputs \n, which is a non-destructive newline (again, on most terminals, including apparently yours), so the l is left unchanged and the cursor is moved to the beginning of the next line.

Mert answered 22/7, 2011 at 16:12 Comment(6)
If it doesn't erase then why is the "r" gone?Rigidify
@cesoid: "Your result will vary depending on what kind of terminal or console program you're on"Mert
It's just that your example doesn't fit the output, so it isn't an example of a possible explanation.Rigidify
@Rigidify The r is replaced with d. The explanation still fits.Trevortrevorr
@Trevortrevorr Thanks. I didn't realize the cursor was "on" the character. I'm always thinking of word processors where they show it "between" characters (or terminal windows where it always inserts rather than overwrites). The edited explanation makes this clear.Rigidify
@cesoid: Interesting about the terminal. In Windows, the cmd.exe and command.com terminals don't always insert (you can use the Ins key to toggle the behavior). I was surprised to find that Gnome Terminal on my main *nix computer always inserts, doesn't even seem to have a preference for it much less toggle based on the Ins key. Never noticed that before. Clearly I almost never want typeover. :-)Mert
H
130
..........
^ <= pointer to "print head"
            /* part1 */
            printf("hello worl");
hello worl
          ^ <= pointer to "print head"
            /* part2 */
            printf("\b");
hello worl
         ^ <= pointer to "print head"
            /* part3 */
            printf("\b");
hello worl
        ^ <= pointer to "print head"
            /* part4 */
            printf("d\n");
hello wodl

^ <= pointer to "print head" on the next line
Handcuff answered 22/7, 2011 at 16:13 Comment(2)
If the cursor after part 4 is at the 'l' letter, shouldn't it be replaced by the '\n'? (resulting in "hello wor")Pokey
@lucas_turci: the thing is that the '\n' does not have a representation on screen. What is already there stays the same; not replaced by a space or any other character representation.Handcuff
B
50

If you want a destructive backspace, you'll need something like

"\b \b"

i.e. a backspace, a space, and another backspace.

Brewhouse answered 22/7, 2011 at 16:31 Comment(8)
This still leaves the space character there isn't it?Pisistratus
Well, yes, but the subsequent \b will mean the next output character will overwrite it.Brewhouse
What if there is no subsequent character?Pisistratus
Then it doesn't matter, does it?Brewhouse
It doesn't matter if it's simply "display to screen". But what if there's a device that reads in your character display? Then there would be one extra character. How do we remove the last character?Pisistratus
Hmm. Unless your device implements a "delete last character" option (e.g. DEL / 0x7f) , I'm stumped.Brewhouse
You can delete a character with a backspace and by printing the ascii character 0x7f, like so: printf("\b%c\b", 0x7f). But that doesn't always work for me. It depends on the terminal. Sometimes, the terminal outputs a funny character.Upstage
@RestlessC0bra : files are a whole other level of pain. See this question and the answers there.Brewhouse
C
8

Not too hard to explain... This is like typing hello worl, hitting the left-arrow key twice, typing d, and hitting the down-arrow key.

At least, that is how I infer your terminal is interpeting the \b and \n codes.

Redirect the output to a file and I bet you get something else entirely. Although you may have to look at the file's bytes to see the difference.

[edit]

To elaborate a bit, this printf emits a sequence of bytes: hello worl^H^Hd^J, where ^H is ASCII character #8 and ^J is ASCII character #10. What you see on your screen depends on how your terminal interprets those control codes.

Cider answered 22/7, 2011 at 16:10 Comment(0)
S
2

Use a single backspace after each character printf("hello wor\bl\bd\n");

Schist answered 27/11, 2011 at 2:4 Comment(2)
"hello wod\n"? What does that mean?Gutta
The answerer just wants to show how to produce the behavior the OP expected.Undershrub

© 2022 - 2024 — McMap. All rights reserved.