Каталог статей
1. Понимание возврата каретки и перевода строки
В знакомом нам языке C символ новой строки может перейти к началу следующей строки, но на самом деле эта операция состоит из двух шагов: \r (возврат каретки) и \n (новая строка).
\rEnter — вернуться к началу этой строки
\nNewline — начать новую строку
2. Понимание буферизации строк
В памяти зарезервировано пространство для буферизации входных или выходных данных, и это зарезервированное пространство называется буфером. Давайте разберемся с концепцией буферизации строк на нескольких примерах кода.
1. Код 1 и 2 (понимают возврат каретки и перевод строки)
Код один:
1#include <stdio.h>
2 int main()
3 {
4 printf("hello world\n");
5 return 0;
6 }
Код два:
1#include <stdio.h>
2 int main()
3 {
4 printf("hello world\r");
5 return 0;
6 }
Нетрудно обнаружить, что \n можно распечатать, а \r распечатать нельзя, потому что режим отображения таков, что буфер обновления строки буферизуется построчно, без \n его нельзя обновить сразу.\r После возврата к началу строки она будет перезаписана, приглашение оболочки перезапишет ранее написанное «hello world». Если мы не добавим \r к «hello world», перезапись не будет выполнена, и приглашение оболочки запишет «hello world» наоборот
следующее:
2. Код три и четыре (понимание функций сна и функции промывания)
Буферизация строки — это своего рода стратегия очистки буфера. В режиме буферизации строки, когда во вводе и выводе встречается символ новой строки '\n', буфер будет обновлен. Ниже мы знаем три файла заголовков <unistd.h> функция
спать спатьs l ee p : функция сна в Linux, устройство находится в состоянии сна
usleepu s l ee p : То же, что и сон, единица измерения мс (т.е. 10-6м)
fflush fflushff l u s h : очистить буфер
Код 3:
1 #include <stdio.h>
2 #include <unistd.h>
3 int main()
4 {
5 printf("hello world");
6 sleep(3);
7 return 0;
8 }
Мы знаем, что операторы кода функции выполняются последовательно сверху вниз, но мы видим, что он засыпает на три секунды, а затем печатает «hello world»,Причина в том, что данные хранятся в буфере и не обновляются активно. Когда программа завершается, данные, хранящиеся в буфере, автоматически обновляются.Если мы хотим обновить заранее, мы можем вызвать fflush fflushff l u s h функция для очистки буфера
Код четыре:
1 #include <stdio.h>
2 #include <unistd.h>
3 int main()
4 {
5 printf("hello world");
6 fflush(stdout);
7 printf("\n");
8 sleep(3);
9 return 0;
10}
На этот раз «hello world» печатается напрямую, мы добавляем \n , чтобы избежать оболочки.Приглашение оболочки появляется после «hello world» .
3. Простой обратный отсчет
1. Отображение эффекта
С помощью вышеуказанной подготовительной работы мы можем понять принцип работы обратного отсчета и индикатора выполнения.Далее мы сначала дадим код и эффект, а затем поговорим о деталях.2. Код обратного отсчета
1 #include <stdio.h>
2 #include <unistd.h>
3 int main()
4 {
5 int cnt=10;
6 while(cnt>=0)
7 {
8 printf("%-2d\r",cnt);
9 fflush(stdout);
10 sleep(1);
11 cnt--;
12 }
13 printf("\n");
14 return 0;
15 }
3. Проведите анализ процесса
1. Определите переменную обратного отсчета cnt , пусть она постепенно уменьшается
2. Ядро состоит в том, чтобы использовать \r , чтобы вернуться к началу строки буфера для перезаписи, а затем fflush постоянно обновляет ее
3. Настройка формата при печати cnt= =10 , напечатать в буфер На самом деле это символ 1 и символ 0. Если мы не используем 2d% для настройки формата, а используем d% , то перезапись будет охватывать только первый символ 1 11 позиция, а второй символ0 00 , он остается в исходной позиции буфера, поэтому обратный отсчет станет следующим:
10->90->80->70->60->50->40->30->20->10->00,-2d%добавьте знак минус, чтобы убедиться, что он выровнен по левому краю
4, добавьте\nпосле обратного отсчета,оболочкине появится после обратного отсчета
4. Индикатор выполнения
1. Отображение эффекта
2. Штрих-код выполнения
makefile
1 processbar:processBar.c main.c
2 gcc -o $@ $^
3 .PHONY:clean
4 clean:
5 rm -f processbar
Заголовочный файл processBar.h
1 #pragma once
2 #include<stdio.h>
3
4 #define SIZE 102
5 #define BODY '='
6 #define TAIL '>'
7
8 extern void processbar(int rate);
9 extern void initbar();
.c файл processBar.c
1 #include "processBar.h"
2 #include <string.h>
3 #include <unistd.h>
4
5 #define LIGHT_GREEN "\033[1;32m" //亮绿色
6 #define NONE "\033[m" //截断
7
8 const char *lable="|/-\\";
9 char bar[SIZE];
10
11 void processbar(int rate)
12 {
13 if(rate<0 || rate > 100)
14 return;
15 //没有\n,就没有立即刷新,因为显示器模式是行刷新
16 printf(LIGHT_GREEN"[%-100s]"NONE"[%d%%][%c]\r",bar,rate,lable[rate%4]);
17 fflush(stdout);
18 bar[rate++]=BODY;
19 if(rate<100)
20 bar[rate]=TAIL;
21 }
22
23 void initbar()
24 {
25 memset(bar,'\0',sizeof(bar));
26 }
.c файл main.c
1 #include "processBar.h"
2 #include <unistd.h>
3
4 typedef void(*callback_t)(int);
5 void downLoad(callback_t cb)
6 {
7 initbar();
8 int total=1000; // 1000MB
9 int curr=0; //0MB
10 while(curr<=total)
11 {
12 // 进行某种下载任务
13 usleep(50000); //模拟下载花费时间
14 int rate=curr*100/total;//更新进度
15
16 cb(rate); //回调展示进度
17 //processbar(curr*100/total);
18
19 curr+=10; // 循环下载了一部分,更新进度
20 }
21 printf("\n");
22 }
23
24
25 int main()
26 {
27 printf("download 1:\n");
28 downLoad(processbar);
29 printf("download 2:\n");
30 downLoad(processbar);
31 printf("download 3:\n");
32 downLoad(processbar);
33 printf("download 4:\n");
34 downLoad(processbar);
35 return 0;
36 }
3. Проведите анализ процесса
стиль индикатора выполнения
Стиль индикатора выполнения:
основной стиль заключен в две квадратные скобки, а средняя => продвигается вперед. Например: [======>] Положение
квадратных скобок с правой стороны основного тела остается неизменным. , а средний элемент продолжает продвигаться вперед, например: [ => ]
Таким образом, мы определяем среднее тело = макрос как BODY , а заднюю сторону > макрос как TAIL
Процент индикатора выполнения:
отображать текущий прогресс загрузки, отображаемый в [rate%], скорость изменяется в зависимости от хода индикатора выполнения, а для печати % (экранирующий символ) требуется два %%
Символ вращения индикатора выполнения:
отображение стиля загрузки, вы можете использовать вращающийся символ, например стиль [], непрерывно вращать по часовой стрелке, а затем "| / - \" , обратите внимание, что \ также является escape-символом, поэтому требуются два символа \\ , Для этого мы определяем указатель метки , указывающий на константную строку const char * lable=" | / - \"
Цвет индикатора выполнения: ссылка на цвет языка C
Мы можем раскрасить индикатор выполнения в соответствии с нашими собственными предпочтениями, здесь мы находим справочную таблицу цветов
и определяем светло-зеленый макрос как #define LIGHT_GREEN Макрос в конце "\033[1;32m "
определяется как #define NONE "\033[m"
Метод реализации индикатора выполнения
Зарезервируйте размер индикатора выполнения как 100 = плюс 1 > плюс сохраните положение \0 и создайте массив столбцов со 102 единицами (определено как SIZE в макросе). Функция processbar() выводит индикатор прогресса с определенной скоростью, после \r возвращается в начало строки, fflush обновляет буфер, и при этом вставляет = в конец массива баров , а затем вставляет > , обратите внимание, что когда скорость равна 100, индикатор выполнения загружается, поэтому нет необходимости вставлять >
для имитации выполнения задачи загрузки и передавать функцию processbar() метода реализации в качестве параметра для имитации downLoad() функция загрузки , для этого мы определяем указатель на функцию типа processbar() и переименовываем его в callback_t . Мы определяем размер пакета загрузки как общую суммуитого , текущий прогресс - текущий текущийc u rr , поэтому скорость выполнения равнаrate=curr*100/total. Используйтеusleep, чтобы имитировать время загрузки, а затем верните обратно, чтобывызвать функцию processbar()для реализации индикатора выполнения Наконец, учитывая вторую загрузку,массив баров заполненочищатьмассив баровкаждый раз мы вызываемфункцию downLoad()