View difference between Paste ID: RhZdBCUb and
SHOW: | | - or go back to the newest paste.
1-
1+
#include <stdio.h>
2
#include <string.h>
3
4
/* Only for the sleep, the progress bar code itself is standard C */
5
#include <unistd.h>
6
7
typedef enum
8
{
9
    false=0,
10
    true=!false
11
} bool;
12
13
typedef struct
14
{
15
    /* Start delimiter (e.g. [ )*/
16
    char StartDelimiter;
17
    /* End Delimiter (e.g. ] )*/
18
    char EndDelimiter;
19
    /* Central block (e.g. = )*/
20
    char Block;
21
    /* Last blocks, rotated at each refresh (typical value: - | / - \ | / ) */
22
    char LastBlocks[10];
23
    /* Used positions of LastBlocks */
24
    size_t LastBlocksSize;
25
    /* LastBlocks index to be used next time */
26
    size_t LastBlockIndex;
27
    /* Width of the progress bar (in characters) */
28
    unsigned int Width;
29
    /* Maximum value of the progress bar */
30
    double Max;
31
    /* True if we have to print also the percentage of the operation */
32
    bool PrintPercentage;
33
    /* True if the bar must be redrawn;
34
       note that this must be just set to false before the first call, the function then will change it by itself.  */
35
    bool Update;
36
} ProgressBarSettings;
37
38
/* Prints/updates the progress bar */
39
void PrintProgressBar(double Pos, ProgressBarSettings * Settings);
40
/* Inits the settings of the progress bar to the default values */
41
void DefaultProgressBar(ProgressBarSettings * Settings);
42
43
int main()
44
{
45
    int i;
46
    /* Init the bar settings */
47
    ProgressBarSettings pbs;
48
    DefaultProgressBar(&pbs);
49
    pbs.Max=400;
50
    pbs.Width=60;
51
    printf("Progress: ");
52
    /* Show the empty bar */
53
    PrintProgressBar(0,&pbs);
54
    for(i=0;i<=pbs.Max;i++)
55
    {
56
        /* Wait 25 msec */
57
        usleep(25000);
58
        /* Update the progress bar */
59
        PrintProgressBar(i,&pbs);
60
    }
61
    puts(" Done");
62
    return 0;
63
}
64
65
/* Inits the settings of the progress bar to the default values */
66
void DefaultProgressBar(ProgressBarSettings * Settings)
67
{
68
    const char * defaultLastBlocks="-\\|/-\\|/";
69
    Settings->StartDelimiter='[';
70
    Settings->EndDelimiter=']';
71
    Settings->Block='=';
72
    strncpy(Settings->LastBlocks, defaultLastBlocks, sizeof(Settings->LastBlocks));
73
    Settings->LastBlocksSize=strlen(defaultLastBlocks);
74
    if(Settings->LastBlocksSize>sizeof(Settings->LastBlocks))
75
        Settings->LastBlocksSize=sizeof(Settings->LastBlocks);
76
    Settings->LastBlockIndex=0;
77
    Settings->PrintPercentage=true;
78
    Settings->Update=false;
79
    Settings->Max=100;
80
    Settings->Width=40;
81
}
82
83
/* Prints/updates the progress bar */
84
void PrintProgressBar(double Pos, ProgressBarSettings * Settings)
85
{
86
    /* Blocks to print */
87
    unsigned int printBlocks=(unsigned int)(Settings->Width*Pos/Settings->Max);
88
    /* Counter */
89
    unsigned int counter;
90
    /* If we are updating an existing bar...*/
91
    if(Settings->Update)
92
    {
93
        /* ... we get back to its first character to rewrite it... */
94
        for(counter=Settings->Width+2+(Settings->PrintPercentage?5:0);counter;counter--)
95
            putchar('\b');
96
    }
97
    else
98
        Settings->Update=true; /* next time we'll be updating it */
99
    /* Print the first delimiter */
100
    putchar(Settings->StartDelimiter);
101
    /* Reset the counter */
102
    counter=Settings->Width;
103
    /* Print all the blocks except the last; in the meantime, we decrement the counter, so in the end we'll have
104
       the number of spaces to fill the bar */ 
105
    for(;printBlocks>1;printBlocks--,counter--)
106
        putchar(Settings->Block);
107
    /* Print the last block; if the operation ended, use the normal block, otherwise the one for the last block */
108
    putchar((Settings->Max==Pos)?Settings->Block:Settings->LastBlocks[Settings->LastBlockIndex]);
109
    /* At the next update we'll use the next last block */
110
    Settings->LastBlockIndex=(Settings->LastBlockIndex+1)%Settings->LastBlocksSize;
111
    /* Another block was printed, decrement the counter */ 
112
    counter--;
113
    /* Fill the rest of the bar with spaces */
114
    for(;counter;counter--)
115
        putchar(' ');
116
    /* Print the end delimiter */
117
    putchar(Settings->EndDelimiter);
118
    /* If asked, print also the percentage */
119
    if(Settings->PrintPercentage)
120
        printf(" %3d%%",(int)(100*Pos/Settings->Max));
121
    /* Flush the output buffer */
122
    fflush(stdout);
123
};