[Linux] Crear un subprograma de barra de progreso
Directorio de artículos
\n y \r caracteres en lenguaje C
Hay dos tipos de caracteres en lenguaje C:
- Caracteres visualizables
- personajes de control
Los caracteres visualizables son caracteres como el carácter a, y los caracteres de control son caracteres de control como \n.
Para que podamos hacer la barra de progreso, sólo debemos prestar atención a dos personajes de control:
- \r – realizar la operación de retorno de carro
- \n: realizar operaciones de avance de línea y retorno de carro
Explicación: \n en sí mismo es un carácter de nueva línea, pero el lenguaje C lo analiza en una nueva línea más un retorno de carro.
Para comprender mejor el papel de los caracteres \r y \n, necesitamos hacer algunas pruebas. Para facilitar la compilación, cree un archivo MAKE. El contenido del archivo es el siguiente:
mytest:test.c
gcc -o mytest test.c
.PHONY:clean
clean:
rm -f mytest
Primero ejecute el siguiente código:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world");
sleep(3);
fflush(stdout);
return 0;
}
ilustrar:
- fflush(stdout) actualiza el búfer de salida estándar para facilitar la observación del fenómeno.
- dormir es la función de suspensión del sistema Linux.
Los resultados de la ejecución son los siguientes:
hello world
Después de imprimir , el programa duerme y el "cursor" está en la siguiente posición en la misma línea.
Una vez finalizada la hibernación, la impresión comenzará desde la posición del cursor, por lo que la [qxm@aliyun-centos review]$
línea de comando se imprimirá inmediatamente después hello world
.
Luego ejecute el siguiente código:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world\n");
sleep(3);
return 0;
}
Los resultados de la ejecución son los siguientes:
Dado que el lenguaje C analiza \n en un avance de línea seguido de un retorno de carro, el programa se suspenderá hello world
después y el "cursor" irá al principio de la siguiente línea.
Una vez finalizada la hibernación, la impresión comenzará desde la posición del cursor, por lo que [qxm@aliyun-centos review]$
la línea de comando se imprime al comienzo de la siguiente línea.
Finalmente ejecute el siguiente código:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world\n");
sleep(3);
return 0;
}
ilustrar:
- fflush(stdout) actualiza el búfer de salida estándar para facilitar la observación del fenómeno.
- dormir es la función de suspensión del sistema Linux.
Los resultados de la ejecución son los siguientes:
Dado que \r es un retorno de carro, el programa se suspenderá hello world
después y el "cursor" volverá al principio de la línea.
Una vez finalizada la hibernación, la impresión comenzará desde la posición del cursor, por lo que la línea de comando sobrescribirá [qxm@aliyun-centos review]$
la original .hello world
Estrategia de actualización del búfer
En el sistema Linux, el lenguaje C primero almacenará los caracteres que se imprimirán en el búfer. Solo cuando los caracteres en el búfer se actualicen en la pantalla se podrán ver en la pantalla. La situación de actualización del búfer es la siguiente:
- Al encontrar \n, todos los caracteres antes de \n aparecerán en la pantalla.
- El búfer se vacía automáticamente cuando finaliza el programa.
Para la prueba del buffer, ejecutamos el siguiente código:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world\r");
sleep(3);
return 0;
}
Los resultados de la ejecución son los siguientes:
Debido a que el búfer no se vacía, no se imprime nada mientras el programa está inactivo.
Después de ejecutar el programa, el búfer se actualiza e hello world
imprime automáticamente.Sin embargo, dado que el retorno de carro \r devuelve el "cursor" al principio de la línea, la impresión del símbolo del sistema sobrescribe la impresión anterior.
Luego ejecute el siguiente código:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world\n");
sleep(3);
return 0;
}
Los resultados de la ejecución son los siguientes:
Debido a un encuentro\nLos datos en el búfer se actualizaron antes de dormir.
Después de que el programa hiberna, la línea de comando comienza a imprimir desde la posición del cursor.
Escribir código de barras de progreso
Cree los siguientes archivos para formar la estructura del código:
- myproc.h: la declaración que contiene el código de barras de progreso
- myproc.c: implementación del código de barras de progreso de guardado
- main.c – llamar al código de barras de progreso
La estructura principal del archivo myproc.h es la siguiente:
#pragma once
#include <stdio.h>
extern void process();
La estructura principal del archivo myproc.c es la siguiente:
#include "myproc.h"
void process()
{
//...
}
La estructura principal del archivo main.c es la siguiente:
#include "myproc.h"
int main()
{
process();
return 0;
}
Al mismo tiempo, cree un archivo MAKE y escriba el siguiente contenido dentro del archivo MAKE:
myproc:myproc.c main.c
gcc -o myproc myproc.c main.c
.PHONY:clean
clean:
rm -f myproc
Después de establecer la estructura del código, escriba el siguiente código para que actúe como una barra de progreso gráfica:
#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");
}
Primero cree una cadena para guardar el buf de la barra de progreso gráfica que se imprimirá, inicialícelo y luego imprima el buf alineado a la izquierda e imprímalo con una longitud de 100 caracteres.
Cada vez que se completa la impresión, el retorno de carro sobrescribe la impresión anterior y el búfer se actualiza para que la impresión se muestre en la pantalla y se utiliza una función de suspensión para cargar el progreso.
El efecto de impresión es el siguiente:
Además de la barra de progreso gráfica, también se debe configurar una visualización de progreso digital, por lo que es necesario modificar la impresión, de la siguiente manera:
printf("[%-100s][%d%%]\r", buf, i);
Aumente el porcentaje de progreso de la impresión a medida que se muestra el progreso de la digitalización, %% se escapará a % y se imprimirá en la pantalla.
El efecto de impresión es el siguiente:
Finalmente, se agrega un cursor giratorio para indicar que la barra de progreso se está ejecutando continuamente, por lo que es necesario modificar la impresión, el código final es el siguiente:
#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");
}
Se agrega una cadena de cursor para guardar el estilo del cursor giratorio, donde \\ se escapará a \, debido a que se imprimen 4 caracteres en un bucle en el cursor giratorio, por lo que la cadena de estilo se genera en módulo 4.
El resultado final de la demostración de la barra de progreso es el siguiente: