Apesar de ser algo banal, a utilização de barras de progresso no terminal é bem diferente se comparado com o ambiente Web, pois a tela toda precisa ser atualizada 😮 invés de apenas um único elemento. Neste post vou detalhar a criação da barra de progresso abaixo utilizando linguagem C.

O código final ficará assim:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define DELAY 400
#define SIZE_BAR 60
void printHeader(){
printf("Loading...\n\n");
}
int calculatePercentage(int progressCount){
if(progressCount > 0){
return progressCount * 2;
}
return 0;
}
void printPercentage(int progressCount){
int percentage = calculatePercentage(progressCount);
int padLeft = SIZE_BAR - progressCount;
printf("%*s %d%%\n", padLeft, "\x1b[32m]\x1b[0m", percentage);
}
void printProgress(char progress[], int progressCount){
printf("%s", progress);
printPercentage(progressCount);
}
void barAppend(char bar[], int progressCount){
strcat(bar, ">");
}
void delay(){
usleep(DELAY * 1000);
}
void initBar(char bar[]){
system("clear");
printHeader();
printProgress(bar, 0);
delay();
}
int main(void){
char bar[SIZE_BAR - 1] = "\x1b[32m[\x1b[0m";
initBar(bar);
int i = 1;
//bar[0..9] alocaded start bar
while(i <= (SIZE_BAR - 10)){
system("clear");
printHeader();
barAppend(bar, i);
printProgress(bar, i);
delay();
i++;
}
return 0;
}
No cabeçalho do arquivo, realizamos a importação das bibliotecas necessárias e criamos 2 constantes:
- DELAY – Define o tempo atualização do progresso da barra em milissegundos;
- SIZE_BAR – Define o tamanho da barra em caracteres.

Na função main temos toda a organização da execução.

Linha 63 – Criamos uma string, em C representada por um array de char, de tamanho 60 (SIZE_BAR) que representará a nossa barra de progresso. Iniciamos ela com o primeiro caractere “[” de cor verde. A cor é definida através do padrão ANSI, com o código “Esc[32m” para demarcar o início e “Esc[0m” para indicar o final do texto colorido.
Para escrever estes códigos de cores, em especial para representar os símbolos, iremos utilizar a tabela ASCII. Neste caso o “Esc” corresponde ao valor hexadecimal “1b” o que resultaria em “\x1b[32m” e “\x1b[0m“. Note que o prefixo “\x” foi adicionado para indicar ao C que estes valores são hexadecimal.
Linha 65 – Executamos a função “initBar” responsável por iniciar a impressão da barra de progresso com valor 0 no terminal. Todas as demais chamadas de funções serão detalhadas mais abaixo.

Linha 67 – Criamos a variável “i” do tipo int que será responsável pelos incrementos da barra. Ela será o nosso contador do progresso.
Linha 70 – Executamos o laço While que será responsável por executar o incremento da barra e chamar as funções responsáveis por atualizar a tela. Na condição de execução, iremos contar de 1 até 50 e não até 60 (SIZE_BAR). Isso ocorre devido a adição do caractere “[” em verde no inicio da barra. Isso mesmo que você leu, a impressão de um símbolo já nos custou 1/6 da barra de progresso 😅.
Linha 72 – Executamos a função “system(“clear”)” responsável por limpar a tela do terminal. Estou executando no ambiente Linux, em Windows pode substituir o “clear” por “cls“.
Linha 74 – Executamos a função “printHeader” responsável por realizar a impressão do cabeçalho da tela.

Linha 76 – Executamos a função “barAppend” responsável por concatenar, no final da string “bar“, o caractere “>“. Este caractere representará o progresso da barra.

Linha 78 – Executamos a função “printProgress” responsável por imprimir a string “bar“, que representa a nossa barra, na tela. Além da representação do progresso, iremos imprimir também o percentual através da função “printPercentage“.

A função “printPercentage” recebe como parâmetro o contador do progresso e executa a função “calculatePercentage” para converter em %. Para imprimir “]” em verde que representa o fim da barra precisaremos executar um “padding-left“🙄, pois ela deverá ser estática na tela. Para isso iremos obter a diferença do total de caracteres da barra menos o “que foi impresso” (indicado através do contador de progresso). Esta diferença será utilizada como parâmetro “field width” na função “printf“. Aqui cabe uma ressalva, pois precisaremos adicionar um “*” junto com o formato de saída string resultado em “*s“.

Na função “calculatePercentage” iremos considerar a proporção 2 para 1, ou seja, a cada incremento do contador de progresso iremos multiplicá-lo por 2 por obter o valor em %. Este ajuste é necessário, pois o contador poderá variar de 1 a 50 o que representaria apenas 50%.

Linha 80 – Executamos a função “delay” responsável por gerar um atraso de 400 ms (DELAY) entre as impressões da barra na tela.

Estou deixando o código fonte também disponível no github para quem quiser brincar mais um pouco ; ]

Materiais de referência:
English version
Soon 😅