C中的进度条用于任意长时间执行— CONSOLE

问题描述 投票:0回答:3

我尽了最大的努力不仅搜索stackOverflow,还搜索其他网站,但是找不到满足我需求的东西。我要的是能够显示进度条(例如,进度:#### .........)。我目前不在乎%。

现在是问题所在。我不能简单地执行0-100 for循环,因为我希望执行并跟踪的代码位于可在任意时间运行的while循环内(问题大小取决于用户的输入,因此不是恒定的)。

我曾想过要跟踪int变量中的迭代次数,并尝试以2、50或100取模,但是正如我所说的那样,迭代次数取决于用户输入,因此只能在具体条件。没有其他输出,但是进度条完成了,所以我做一个简单的printf('#');在while循环内,以及循环外的所有漂亮内容。

这也是个人喜好,但不介意是否包含在内,我希望进度条的长度为50个字符,因此100%执行= 50个'#'字符。

非常感谢您的帮助。

c progress
3个回答
2
投票

所以我很好地包装了代码,这就是我最终得到的结果。


我使用了oop的概念并模拟了ProgressBar的类。这是我为ProgressBar设计的代码:

struct tagProgressBarData
{
    unsigned long nMaxLen;
    unsigned long nCurLen;

    char FillChr;
    char EmptyChr;
    char LeftMargin;
    char RightMargin;
};
typedef struct tagProgressBarData PBD;

void InitProgressBar(PBD* p, unsigned long MaxLen, char Left, char Right, char Fill, char Empty);
void DrawProgressBar(PBD* p);

[跳转到InitProgressBar()DrawProgressBar()的定义之前,这是您应该使用我所做的方法的方式。这是一个例子:

int main()
{
    PBD data;

    /** You can chose other characters and change the length too! */
    InitProgressBar(&data, 50, '[', ']', '#', '.');

    /** Now we do something which takes some time. */
    /** Let's just calculate some random cubes. */

    /** The N you talked about. */
    unsigned int N;
    printf("How many numbers to compute: ");
    scanf("%u", &N);

    printf("Calculating the cubes of the first %u numbers.\n", N);
    DrawProgressBar(&data);

    for(unsigned int i = 1; i <= N; i++)
    {
        unsigned int CubeResult = i*i*i;

        unsigned long nProgress = ( ((unsigned long long)i) * data.nMaxLen) / N;
        if (nProgress != data.nCurLen)
        {
            data.nCurLen = nProgress;
            DrawProgressBar(&data);
        }
    }


    return 0;
}

现在,显示进度条的函数的定义:

void DrawProgressBar(PBD* p)
{
    /** Move to the beginning of the line. */
    printf("\r");

    /** Print the left margin char. */
    printf("%c", p->LeftMargin);

    /** Make sure that MaxLen >= CurLen */
    if (p->nMaxLen < p->nCurLen)
        p->nCurLen = p->nMaxLen;

    /** Print the progress with the Fill char. */
    for(unsigned long i = 0; i < p->nCurLen; i++)
        printf("%c", p->FillChr);

    /** Complete whats left with the Fill char. */
    for(unsigned long i = 0; i < p->nMaxLen - p->nCurLen; i++)
        printf("%c", p->EmptyChr);

    /** Print the right margin char. */
    printf("%c", p->RightMargin);
}

我还使用此功能使我的代码更紧凑:

void InitProgressBar(PBD* p, unsigned long MaxLen, char Left, char Right, char Fill, char Empty)
{
    p->nMaxLen = MaxLen;
    p->nCurLen = 0;

    p->LeftMargin = Left;
    p->RightMargin = Right;
    p->FillChr = Fill;
    p->EmptyChr = Empty;
}

如果要在进度条之前但在同一行(例如Progress: [######.............])上有一些文本,则必须将printf("\r");中的DrawProgressBar()替换为for循环,以便您准确地向后移动进度条的长度。

此外,您需要一些变量(假设为bDrawn),该变量将告诉您是否至少绘制了进度条一次,以便for循环不会将光标移到进度左侧的现有文本上酒吧。


0
投票

经过反复试验,我可能找到了解决方案,但想与某人进行检查。

假设这些变量(均为int类型:):

num_iterations = 0,MAX_PROGRESS = 100,BAR_LENGTH = 50,num_items = N

我在以下位置打印了'#'字符:

if ((iteration / BAR_LENGTH) % (MAX_PROGRESS * BAR_LENGTH * num_items) == 0)

并获得我想要的结果:

|<------------- Enumeration Complete ------------->|
|##################################################| COMPLETED

尽管它逐渐建立,但它不是形式

|<------------- Enumeration Complete ------------->|
|##################################................|

我可以用\ r或\ b做什么?


0
投票

我也已经做到了,但似乎非常依赖于项目数。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <time.h>

int MAX_PROGRESS = 100;
int BAR_LENGTH = 0;  // Length of Header
int num_items = 30;

void delay(int milliseconds) { 

  // Storing start time 
  clock_t start_time = clock(); 

  // looping till required time is not achieved 
  while (clock() < start_time + milliseconds); 
} 

void initialiseProgressBar(char left, char right, char fill) {

  printf("%c", left);
  for (int i = 0; i < BAR_LENGTH; i ++) {
    printf("%c", fill);
  }

  /** Print the right first (end of line) and then again the left (start of line)
   * as the \r will be placed over it and rewrite from there resulting in one
   * character less
   */
  printf("%c\r%c", right, left);
}

void drawProgressBar(char c) {

  // Print according to BAR_LENGTH
  for (int i = 0; i < 100; i ++) {
    double progress = (i / BAR_LENGTH) % (MAX_PROGRESS * BAR_LENGTH * num_items);
    if (progress == 0) {
      printf("%c", c);
      delay(25);
    }
    // Redraw the stdout stream to show progressing bar
    fflush(stdout);
  }
}

int main(int argc, char* argv[]) {

  // Header
  char* header = "|<------------- Progress Bar ------------->|\n";
  printf("%s", header);
  BAR_LENGTH = strlen(header) - 3; // Account for newline and right character characters

  initialiseProgressBar('[', ']', '.');
  drawProgressBar('#');

  // Footer -- TODO Find better way to finish this without hard coding
  printf("] COMPLETED\n");
  return 0;
}

假设您知道要计算的项目数(例如,对列表进行排序,计算不同的事物等),这应该派上用场了:)。

© www.soinside.com 2019 - 2024. All rights reserved.