[Linux] Teach you step by step how to make a progress bar applet

[Linux] Make a progress bar applet

\n and \r characters in C language

There are two types of characters in C language:

  • Displayable characters
  • control characters

The displayable characters are characters such as character a, and the control characters are control characters such as \n.

For us to make the progress bar, we only need to pay attention to two control characters:

  • \r – perform carriage return operation
  • \n – perform line feed and carriage return operations

Explanation: \n itself is a newline character, but the C language itself parses it into a newline plus a carriage return.

In order to better understand the role of the characters \r and \n, we need to do some tests. In order to facilitate compilation, create a makefile file. The file content is as follows:

mytest:test.c
	gcc -o mytest test.c
.PHONY:clean
clean:
	rm -f mytest

First execute the following code:

#include <stdio.h>
#include <unistd.h>
int main()
{
    
    
	printf("hello world");
    sleep(3);
    fflush(stdout);
	return 0;
}

illustrate:

  • fflush(stdout) refreshes the standard output buffer to facilitate observation of the phenomenon.
  • sleep is the sleep function of Linux system.

The execution results are as follows:

image-20230730125207629

hello worldAfter printing , the program sleeps and the "cursor" is at the next position on the same line.

image-20230730125310098

After hibernation ends, printing will start from the cursor position, so the command [qxm@aliyun-centos review]$line prompt will be printed immediately after hello worldit.

Then execute the following code:

#include <stdio.h>
#include <unistd.h>
int main()
{
    
    
    printf("hello world\n"); 
    sleep(3);
    return 0;
}

The execution results are as follows:

image-20230730125541374

Since \n is parsed by the C language into a line feed followed by a carriage return, the program will sleep hello worldafter and the "cursor" will go to the beginning of the next line.

image-20230730123307921

After hibernation ends, printing will start from the cursor position, so [qxm@aliyun-centos review]$the command line prompt is printed at the beginning of the next line.

Finally execute the following code:

#include <stdio.h>
#include <unistd.h>
int main()
{
    
    
    printf("hello world\n"); 
    sleep(3);
    return 0;
}

illustrate:

  • fflush(stdout) refreshes the standard output buffer to facilitate observation of the phenomenon.
  • sleep is the sleep function of Linux system.

The execution results are as follows:

image-20230730130940986

Since \r is a carriage return, the program will sleep hello worldafter and the "cursor" will return to the beginning of the line.

image-20230730123307921

After hibernation ends, printing will start from the cursor position, so the command line prompt will overwrite [qxm@aliyun-centos review]$the original one .hello world

image-20230730131108150

Buffer refresh strategy

Under the Linux system, the C language will first store the characters to be printed in the buffer. Only when the characters in the buffer are refreshed to the screen can they be seen on the screen. The buffer refresh situation is as follows:

  • When encountering \n, all characters before \n will be flushed to the screen.
  • The buffer is automatically flushed when the program ends.

For the buffer test, we execute the following code:

#include <stdio.h>
#include <unistd.h>
int main()
{
    
    
	printf("hello world\r");
  	sleep(3);
	return 0;
}

The execution results are as follows:

image-20230730132019107

Because the buffer is not flushed, nothing is printed while the program sleeps.

image-20230730133131040

After the program is executed, the buffer is automatically refreshed and hello worldprinted. However, since the \r carriage return returns the "cursor" to the beginning of the line, the printing of the command prompt overwrites the previous printing.

Then execute the following code:

#include <stdio.h>
#include <unistd.h>
int main()
{
    
    
	printf("hello world\n");
  	sleep(3);
	return 0;
}

The execution results are as follows:

image-20230730132354920

Due to encounter\nThe data in the buffer was refreshed before sleeping.

image-20230730132526954

After the program hibernates, the command line prompt starts printing from the cursor position.

Write progress bar code

Create the following files to form the code structure:

  • myproc.h – the declaration that holds the progress bar code
  • myproc.c – Implementation of saving progress bar code
  • main.c – calling progress bar code

The core structure in the myproc.h file is as follows:

#pragma once 
#include <stdio.h>
extern void process();

The core structure in the myproc.c file is as follows:

#include "myproc.h"
void process()
{
    
    
  //...
}

The core structure in the main.c file is as follows:

#include "myproc.h" 
int main()
{
    
    
  process();
  return 0;
}

At the same time, create a makefile file and write the following content inside the makefile file:

myproc:myproc.c main.c
	gcc -o myproc myproc.c main.c
.PHONY:clean
clean:
	rm -f myproc

After establishing the code structure, write the following code to act as a graphical progress bar:

#include "myproc.h"
#include <string.h>
#include <unistd.h>

#define STYLE '='
#define ARROW '>'
#define SIZE 101

void process()
{
    
    
  char buf[SIZE];
  memset(buf, 0 , SIZE);
  int i = 0;
  while(i <= 100)
  {
    
    
    printf("[%-100s]\r", buf);
    fflush(stdout);
    buf[i++] = STYLE;
    if(i != 100 )buf[i] = ARROW;
    usleep(100000);
  }
  printf("\n");
}

First create a string to save the graphical progress bar buf to be printed, initialize it, and then print the buf left-aligned and print with a length of 100 characters when printing.

Each time printing is completed, the carriage return overwrites the previous printing, and the buffer is refreshed so that the printing is displayed on the screen, and a sleep function is used to load the progress.

The printing effect is as follows:

111

In addition to the graphical progress bar, a digital progress display must also be set, so the printing needs to be modified, as follows:

printf("[%-100s][%d%%]\r", buf, i);

Increase the printing progress percentage as the digitization progress display, %% will be escaped into a % and printed on the screen.

The printing effect is as follows:

222

Finally, a rotating cursor is added to indicate that the progress bar is continuously executing, so the printing needs to be modified, and the final code is as follows:

#include "myproc.h"
#include <string.h>
#include <unistd.h>

#define STYLE '='
#define ARROW '>'
#define SIZE 101

void process()
{
    
    
  const char* cursor = "|/-\\";
  char buf[SIZE];
  memset(buf, 0 , SIZE);
  int i = 0;
  while(i <= 100)
  {
    
    
    printf("[%-100s][%d%%][%c]\r", buf, i, cursor[i%4]);
    fflush(stdout);
    buf[i++] = STYLE;
    if(i != 100 )buf[i] = ARROW;
    usleep(100000);
  }
  printf("\n");
}

A cursor string is added to save the style of the rotating cursor, where \\ will be escaped into a \, because 4 characters are printed cyclically in the rotating cursor, so the style string is output modulo 4.

The final demonstration result of the progress bar is as follows:

333

Guess you like

Origin blog.csdn.net/csdn_myhome/article/details/132080072