How to Build a Real‑Time Linux Progress Bar in C Using \r and Buffer Flushing
This tutorial explains the difference between \r and \n, the role of line buffering in C, and shows step‑by‑step code—including a countdown and a full‑screen progress bar—using printf, fflush, sleep/usleep, and multi‑file project structure on Linux.
Introduction
Learn how to write a simple progress‑bar program for Linux terminals using C. The tutorial starts with a brief demonstration of the final output and outlines the two key concepts needed: control characters (\r, \n) and line buffering.
Understanding \r and \n
In C, characters are divided into printable characters and control characters. \r (carriage return) moves the cursor to the beginning of the current line, while \n (newline) moves the cursor to the next line. Typical line‑break behavior in text editors is actually a combination of both.
Line Buffering
Standard output is buffered. Functions like printf write to a buffer, which is flushed automatically when a newline is encountered (line‑buffered mode) or when the program terminates. The tutorial provides three code examples to illustrate the effect of buffering:
#include <stdio.h>
int main(){
printf("hello xxx");
sleep(3);
return 0;
}Result: the cursor stays at the line start and the string is not shown until the program exits.
#include <stdio.h>
int main(){
printf("hello xxx
");
sleep(3);
return 0;
}Result: the string appears immediately because the newline triggers a buffer flush.
#include <stdio.h>
int main(){
printf("hello xxx\r");
sleep(3);
return 0;
}Result: the string is not visible; the cursor remains at the start of the line and the shell prompt overwrites the output after the program ends.
Answers and Extensions
Code executes sequentially; printf runs before sleep. The output is hidden because it stays in the buffer until the program exits.
Adding \n forces a line‑buffer flush, so the text appears before the sleep. \r returns the cursor to the line start; without an explicit flush the buffered text is overwritten by the shell prompt.
Using fflush(stdout) after printf forces the buffer to display the text immediately, even when \r is used.
Countdown Example
A simple countdown demonstrates the same principles: each iteration prints a number with \r, calls fflush(stdout), then sleeps for one second.
#include <stdio.h>
#include <unistd.h>
int main(){
int i = 10;
for(; i >= 0; i--){
printf("%2d\r", i);
fflush(stdout);
sleep(1);
}
printf("
");
return 0;
}Progress Bar Implementation
The final progress bar combines three files ( proc.h, proc.c, main.c) and a makefile. The bar consists of 100 slots filled with ‘=’, a moving ‘>’, a percentage display, and a rotating cursor (| / - \). The implementation uses \r to return to the line start and fflush (or usleep for finer timing) to update the display.
#pragma once
#include <stdio.h>
extern void process(); #include "proc.h"
#include <string.h>
#include <unistd.h>
#define SIZE 102
#define STYLE '='
#define FLAG '>'
void process(){
const char* str = "|/-\\";
char bar[SIZE];
memset(bar, '\0', sizeof(bar));
int i = 0;
while(i <= 100){
printf("[%-100s][%d%%][%c]\r", bar, i, str[i % 4]);
fflush(stdout);
bar[i++] = STYLE;
if(i != 100) bar[i] = FLAG;
usleep(100000);
}
printf("
");
} #include "proc.h"
int main(){
process();
return 0;
}The makefile lists the dependencies so that make builds the three‑file program correctly.
Result
Running the compiled program shows a continuously updating bar like [========>] [15%] [\], with the cursor rotating and the percentage increasing until completion.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
