Can't understand the output of C++ string with special characters

This comes down to your terminal. We can see easily from a platform that doesn't render the control character '\b' in any special way that it's present in the string at the expected location:

Screenshot of some "raw"-ish output via Coliru

So, why doesn't it "erase" the 2?

If we open up cmd.exe and type in A, B, Ctrl+H then we see the B is immediately erased. This would seem to disprove the notion that cmd.exe handles backspace "non-destructively" as many consoles do.

But it doesn't disprove it! This seems to be a special handling for keystrokes, presumably tied into how the actual backspace character works. After all, you want the backspace character to actually erase things, rather than just moving the cursor.

cmd.exe treats the control character differently when found in output not generated by the keyboard: in a non-destructive fashion. So it moves the cursor backwards then the next character "overwrites" the would-be erased character.

But in group 4, you have a newline, so the next character goes on the next line and is not in the right place to erase anything.

We can reproduce this without C++, by constructing a special file then instructing cmd.exe to print it:

"Working"

Screenshot of non-reproducing file contents Screenshot of non-reproduced problem

"Not working"

Screenshot of reproducing file contents Screenshot of reproduced problem

(You can insert the special character ASCII 08 in Notepad++, using the "Edit"/"Character Panel" menu item.)

My conclusion is not to rely on control codes for such "tricks": if you want to remove a character from a string, actually do so; if you want to create a GUI, either actually do so, or simulate one with a clever library like ncurses.


What the console is showing is the correct output, that is

Group 4 output:
012
56789

You are mistaken to expect

Group 4 output:
01
56789

What \b character does is move the cursor one character back, it does not delete it. So what has happened is the cursor is moved back to 2 but the character is still there.

012
  ^

The next character \n is not a printable character but a control character and it just moves the cursor to the next line so it doesn't overwrite that character which was already printed.

If you do this instead:

//This is group 4
numString[3] = '\b';
numString[4] = 'X';
cout << "Group 4 output:\n" << numString << endl;

Now \b moves to 2 but the next character 'X' immediately overwrites it yielding the following result as expected.

Group 4 output:
01X56789

Another demonstration is even if you add another backspace:

numString[3] = '\b';
numString[4] = '\b';
numString[5] = '\n';

The cursor is now at 1

012
 ^

Now it encounters the \n (new line) as next character and it simply moves the cursor to the next line so 1 and 2 are never overwritten as they were already printed and remains now in the previous line.

The output hence now is, as expected:

Group 4 output:
012
6789

See also this and that