21

I am trying to use the backspace control character '\b' to erase trailing commas at the end of line. Although it works in cases where there is no other output to stdout, in case if there is another output after '\b', it becomes useless. Here is an example:

#include <iostream>

using namespace std;

int main()
{
    int a[] =  { 1, 3, 4, 5, 6, 32, 321, 9};
    for ( int i = 0; i < 8; i++) {
        cout << a[i] << "," ;
    }
    cout << "\b" ;
    //cout << endl;
    return 0;
}

In the above block of code, if the line is commented as seen, we get the desired result with no comma after the digit 9. However, if the line uncommented, the comma re-appears.

In my program, I do not want the comma to be there, but want an endline after 9. How do I do this ?

hytriutucx
  • 1,614
  • 6
  • 26
  • 37
  • 3
    The `'\b'` just moves the cursor one place back, you could overwrite the comma with a space to make it not show when the cursor moves to the next line. – Daniel Fischer Oct 07 '12 at 01:13

4 Answers4

36

The usual way of erasing the last character on the console is to use the sequence "\b \b". This moves the cursor back one space, then writes a space to erase the character, and backspaces again so that new writes start at the old position. Note that \b by itself only moves the cursor.

Of course, you could always avoid outputting the comma in the first place:

if(i > 0) cout << ",";
cout << a[i];
nneonneo
  • 171,345
  • 36
  • 312
  • 383
5

Or, if you're fond of C+11 hacks:

adjacent_difference(a.begin(), a.end(), ostream_iterator<int>(std::cout),
  [](int x, int)->int { return std::cout << ",", x; });
rici
  • 234,347
  • 28
  • 237
  • 341
  • Having trouble figuring this one out. I kind of get the idea, but what is it actually doing? Also, how do I use? – Andrew Feb 18 '17 at 16:04
  • http://en.cppreference.com/w/cpp/algorithm/adjacent_difference See the box labelled "equivalent operation". You use it with any iterable container `a` of objects of some type T for which `operator<<(std::ostream&, T)` is defined. – rici Feb 18 '17 at 16:52
  • @andrew: in the equivalent operation, think of `a-b` being replaced with f(a,b) where `f` is the lambda. – rici Feb 18 '17 at 16:57
  • I still don't follow. What does this code above *do*? Particularly the adjacent_difference (obviously) and the cout with a comma are most confusing. I know about begin/end calls and lambdas. – Andrew Feb 18 '17 at 18:12
  • 1
    @andew: it prints out the values of `a` with commas between (and only between) consecutive elements. If `a` has only one element, there is (therefore) no comma. If `a` has no elements, it does nothing. `cout` is *not* a statement, contrary to apparently popular belief; `cout << ',';` is an expression whose operator has been defined. The comma operator evaluates both arguments *in order* and then returns the second one; that can be done (as in this case) to evaluate the first argument for its side-effects only. – rici Feb 18 '17 at 18:23
  • 1
    @andrew... I suppose that I called this a hack four years ago precisely because of that use of the comma operator, which is kind of ugly (although it works fine). It would have been cleaner for the lambda to just do `std::cout << ',' << a;` but the contract with `adjacent_difference` is that the function needs to return something, and that something will be stored through the output iterator (the last argument to adjacent_difference), so I would have needed an equivalent to `/dev/null` to toss the meaningless return value into the bit bucket. I don't think there is such a thing in the std lib. – rici Feb 18 '17 at 18:24
2

Using backspace escape sequence leads to minor issue. If you want to print your array and you've defined it up front - its size is always non zero. Now imagine that you do not know size of your array, set, list or whatever you want to print and it might be zero. If you've already printed sth. before printing your stuff and you are supposed to print zero elements your backspace will devour something already printed.

Assume you are given pointer to memory location and number of elements to print and use this ...:

void printA(int *p, int count)
{
    std::cout << "elements = [";

    for (int i = 0; i < count; i++)
    {
        std::cout << p[i] << ",";
    }

    std::cout << "\b]\n";
}

...to print:

int tab[] = { 1, 2, 3, 4, 5, 6 };

printA(tab, 4);
printA(tab, 0); // <-- a problem

You end up with:

elements = [1,2,3,4]
elements = ]

In this particular case your opening bracket is 'eaten'. Better not print comma after element and delete last one since your loop may execute zero times and there is no comma to delete. Instead print comma before - yes before each element - but skip first loop iteration - like this:

void printB(int *p, int count)
{
    std::cout << "elements = [";

    for (int i = 0; i < count; i++)
    {
        if (i != 0) std::cout << ',';
        std::cout << p[i];
    }

    std::cout << "]\n";
}

Now this code:

printB(tab, 4);
printB(tab, 0);

generates this:

elements = [1,2,3,4]
elements = []

With backspace esc. seq. you just never know what you might delete.

working example

Artur
  • 7,038
  • 2
  • 25
  • 39
-1

yeah the \b will only move the curse so when you end the line it just moves it back to the end of the line. so to actually erase the last part have a space after \b to actually erase the last comma. example: cout<<"\b ";