For years I would occasionally run across a program that would display a little ASCII art rotating bar to show it was working and each time I wondered how it was writing to what I assumed was standard out, but replacing previously written characters. Not sure what I’m talking about? It’s best to just show a video since I’m not sure there’s a name for it.
Part of the problem is that I didn’t know what it was called so it made searching for it quite difficult. Of course, this type of effect can be achieved with Curses, but there’s no need to bring in a big library for something that’s so simple. Well, it all comes down to \x08
. That’s the C escape code for the backspace ASCII character (like hitting the backspace key on your keyboard); or if you prefer, \b
will work just fine too. It does as its name implies, writes a backspace which removes the previous character from the stream it’s written to. In this case, we can use it to print out a character, wait a little bit, backspace that character, and then print another in it’s place and so on to achieve the effect above.
Here’s a little C program to do just that put into the form of a nice function that would be useful in a real program. It would probably be better to put it in its own thread while the main thread does the work (or vice versa), but you get the point from the example below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include <unistd.h>
void step(void);
int main(void) {
printf("Doing something really hard... ");
while(1) {
step();
usleep(200 * 1000);
}
return 0;
}
void step(void) {
static int step;
if(step < 3) {
step++;
} else {
step = 0;
}
printf("\b");
switch(step) {
case 0:
printf("-");
break;
case 1:
printf("/");
break;
case 2:
printf("|");
break;
case 3:
printf("\\");
break;
}
fflush(stdout);
}
We can also display a progress bar.
Compile the following with -std=c99
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <unistd.h>
void step(void);
int main(void) {
for(int i=0; i<=100; i++) {
step();
usleep(200 * 1000);
}
return 0;
}
void step(void) {
static int pos = 0;
for(int i=0; i<106; i++) {
printf("\b");
}
printf("[");
for(int i=0; i<100; i++) {
if(i < pos) {
printf("#");
} else {
printf(" ");
}
}
printf("] %d%%", pos);
fflush(stdout);
pos++;
}
Simple. I just wish someone would have told me about it before!