当前位置:   article > 正文

实现控制台上的进度条

控制台的进度

         通常,  控制台程序在执行一个漫长的任务时,需要实时显示当前进度信息, 本文演示了类似GUI进度条控件的实现.

由于需要实时更新进度条信息,并且是要在同一行显示,所以需要用到回车转义字符'\r'.


首先是进度条结构体的定义:

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <pthread.h>
  5. #include <time.h>
  6. #include <errno.h>
  7. #include <sys/select.h>
  8. #include <sys/time.h>
  9. #include <sys/types.h>
  10. #define bool unsigned char
  11. #define true 1
  12. #define false 0
  13. struct progress_bar_info {
  14.     const char *name;
  15.     bool interactive;
  16.     long init_length;
  17.     long step; //步长
  18.     long total_length;
  19.     int width;
  20.     char *buffer;
  21. };

接着是几个帮助函数, 主要是获取控制台屏幕大小:

  1. static int
  2. get_screen_width(void)
  3. {
  4. int screen_width = getenv("COLUMNS");
  5. return screen_width;
  6. }
  7. static int
  8. get_screen_height(void)
  9. {
  10. int screen_height = getenv("LINES");
  11. return screen_height;
  12. }

接下来是创建和显示进度条图形的函数:

  1. static void
  2. create_image(struct progress_bar_info *pbi, bool done)
  3. {
  4. char *p = pbi->buffer;
  5. pbi->init_length += pbi->step;
  6. long current_size = pbi->init_length;
  7. int percentage = 0;
  8. int i = 0;
  9. if (current_size >= pbi->total_length) {
  10. percentage = 100;
  11. strcpy(p, "100%");
  12. } else {
  13. percentage = 100.0 * current_size / pbi->total_length;
  14. sprintf (p, "%2d%% ", percentage);
  15. }
  16. p += 4;
  17. int progress_size = 10; //->
  18. *p++ = '[';
  19. int current_progress_size = progress_size * percentage/100;
  20. for (i = 0; i < progress_size; i++) {
  21. if (i < current_progress_size)
  22. *p++ = '>';
  23. else
  24. *p++ = ' ';
  25. }
  26. *p++ = ']';
  27. if (done)
  28. strcpy(p, " Done!\n");
  29. p = strchr(p, '\0'); //move to the end;
  30. }
  31. static void
  32. display_image(char *buf)
  33. {
  34. fprintf(stderr, "\r");//回车, 将光标设置到行的开头
  35. fprintf(stderr, "%s", buf);
  36. }

下面是创建进度条函数: 传入参数: 进度条初始长度和总长度

  1. void* progress_bar_create(int initial, int total)
  2. {
  3. struct progress_bar_info *pbi = (struct progress_bar_info*)malloc(sizeof(struct progress_bar_info));
  4. if (pbi == NULL)
  5. return NULL;
  6. if (initial > total)
  7. total = initial;
  8. pbi->init_length = initial;
  9. pbi->total_length = total;
  10. pbi->step = 2;
  11. pbi->width = get_screen_width() - 1; //dont't use the last screen column
  12. pbi->buffer = (char*)malloc(pbi->width + 100);
  13. create_image(pbi, false);
  14. display_image(pbi->buffer);
  15. return pbi;
  16. }

进度条更新:

  1. void progress_bar_update(void *progress_bar)
  2. {
  3. struct progress_bar_info *pbi = (struct progress_bar_info*)progress_bar;
  4. pbi->init_length += pbi->step;
  5. create_image (pbi, false);
  6. display_image (pbi->buffer);
  7. }

进度条完成:

  1. void progress_bar_finish(void *progress_bar)
  2. {
  3. struct progress_bar_info *pbi = (struct progress_bar_info*)progress_bar;
  4. create_image (pbi, true);
  5. display_image (pbi->buffer);
  6. free(pbi->buffer);
  7. }

下面是进度条测试代码:

  1. int mySleep(unsigned int sleepSecond)
  2. {
  3. struct timeval t_timeval;
  4. t_timeval.tv_sec = sleepSecond;
  5. t_timeval.tv_usec = 0;
  6. select( 0, NULL, NULL, NULL, &t_timeval );
  7. return 0;
  8. }
  9. void thread_func(void *data)
  10. {
  11. struct progress_bar_info *pbi = (struct progress_bar_info*)data;
  12. while (pbi->init_length < pbi->total_length) {
  13. progress_bar_update(pbi);
  14. mySleep(1);
  15. }
  16. progress_bar_finish(pbi);
  17. #if 0
  18. int i = 0;
  19. for (i = 0; i < 10; i++) {
  20. fprintf(stderr, "%d\r", i);
  21. // printf(stderr, "\r");
  22. mySleep(1);
  23. }
  24. fprintf(stderr, "\n");
  25. #endif
  26. }
  27. int main(void)
  28. {
  29. struct progress_bar_info *pbi = progress_bar_create(0, 100);
  30. pthread_t a_thread;
  31. pthread_create(&a_thread, NULL, thread_func, pbi);
  32. pthread_join(a_thread, NULL);
  33. return 0;
  34. }


转载于:https://my.oschina.net/fuyajun1983cn/blog/263955

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/264279
推荐阅读
相关标签
  

闽ICP备14008679号