tags:

views:

1364

answers:

6

How would I print a spinning curser in a utility that runs in a terminal using standard C?

I'm looking for something that prints: \ | / - over and over in the same position on the screen?

Thanks

+9  A: 

You could use the backspace character (\b) like this:

printf("processing... |");
fflush(stdout);
// do something
printf("\b/");
fflush(stdout);
// do some more
printf("\b-");
fflush(stdout);

etc. You need the fflush(stdout) because normally stdout is buffered until you output a newline.

Greg Hewgill
+1  A: 

I've done that, long ago. There are two ways.

  1. Use a library like ncurses to give you control over the terminal. This works well if you want to do a lot of this kind of stuff. If you just one this in one little spot, it's obviously overkill.

  2. Print a control character.

First you print "/", then 0x08 (backspace), then "-", then 0x08, then "\"....

The backspace character moves the cursor position back one space, but leaves the current character there until you overwrite it. Get the timing right (so it doesn't spin to fast or slow) and you're golden.

MBCook
There is no need to use 0x08, the C standard supplies '\b' for a backspace, and this will work independently of the character set. 0x08 assumes ASCII.
Chris Young
@Chris Young: I saw that in the other posts after I made mine. I haven't had to do this for so long, I didn't remember what it was. I looked at an ASCII table to find the number, but the table didn't have the shortcut.
MBCook
A: 

There is no truly "standard" way to do this, since the C Standard Library (http://members.aol.com/wantondeb/) does not provide functions to do raw terminal/console output.

In DOS/Windows console, the standard-ish way to do it is with conio.h, while under Unix/Linux the accepted library for this purpose is ncurses (ncurses basically encapsulates the control-character behavior that MBCook describes, in a terminal-independent way).

Dan
+3  A: 

Here's some example code. Call advance_cursor() every once in a while while the task completes.

#include <stdio.h>

void advance_cursor() {
  static int pos=0;
  char cursor[4]={'/','-','\\','|'};
  printf("%c\b", cursor[pos]);
  fflush(stdout);
  pos = (pos+1) % 4;
}

int main(int argc, char **argv) {
  int i;
  for (i=0; i<100; i++) {
    advance_cursor();
    usleep(100000);
  }
  printf("\n");
  return 0;
}
zzamboni
+1  A: 

You can also use \r:

#include <stdio.h>
#include <unistd.h>

void
advance_spinner() {
    static char bars[] = { '/', '-', '\\', '|' };
    static int nbars = sizeof(bars) / sizeof(char);
    static int pos = 0;

    printf("%c\r", bars[pos]);
    fflush(stdout);
    pos = (pos + 1) % nbars;
}

int
main() {
    while (1) {
        advance_spinner();
        usleep(300);
    }

    return 0;
}
lazy1
A: 

zzamboni: You made a typo in your code. usleep(100000); is supposed to be sleep(100000);

;) lol

edit: WHY IS EVERYBODY TYPING USLEEP?

wowaname
sleep() and usleep() are different. I'll leave the difference as an exercise for you to find out. You'll notice that as you develop more experience the number of "lol"s you use will decline.
ssg
My compiler does not accept usleep. Stop getting on to me for absolutely nothing.
wowaname