Spinner progress bar. Can't find the bug.

Surprisingly, this is a beginner project that I am completely unable to find a good example of or anything really. I am going back to school after some years off and I'm doing little things to get back into coding. I couldn't find anything like this as a beginner exercise so here is where I am. If you run it, you'll see that the end of the bar doesn't show at first. I don't see where my error is. If I uncomment the arrow and take out the spinner, it works perfectly. For some reason the spinner makes the end bracket not show the first run of the spinner. Help!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  #include <iostream>
#include <unistd.h>

using namespace std;

void spin();

int main()
{
    int width = 14;
    int pos;
    int spaces;
    int x;
    
    for(pos = 0; pos <= width; pos++)
    {
        spaces = width-pos;
        cout << "   [";
        for(x = 0; x <= pos; x++)
        {
            if(x < pos)
            {
                cout << "=";
            }
            else if(x == pos)
            {
                spin();
                //cout << ">";
            }
        }
        for(int i = spaces; i > 0; i--)
           {
               cout << " ";
           }
        cout << "]\r";
        //fflush(stdout);
        sleep(1);
    }
    cout << "\nDone!";
    return 0;
}

void spin()
{
      char spinner[] = {'/', '-', '\\', '|'};
    for(int i = 0; i < sizeof(spinner); i++)
    {
        cout << spinner[i];
        fflush(stdout);
        sleep(1);
        cout << "\b";
    }
}
Line 35 isn't reached until after spin has been running for a minimum of 4 seconds. Output the indicator "container" before filling it.

You might find this interesting:
https://gist.github.com/cire3791/6338578

A quick fix would be to add the following line of code at line 14:
1
2
   cout << "                  ]\r";
    // ... 


(Multiline to force preservation of whitespace.)
Last edited on
That was helpful. Thank you! I thought it was something like that. I'll mess with it some more to make it a little cleaner. Thanks again!
You're waiting for the first "spin" call to return before you print the end of the bar.

The solution is to print the end of it, putting something like
1
2
3
4
for(pos = 0; pos <= width; pos++) {
  std::cout << " ";
}
std::cout << "]\r";

At line 14.

Some things:

Your code is very nearly idiomatic C. Some things can be changed to make your program shorter. In particular, most of the loops can be replaced with the fill constructor of std::string, and most variable declarations can be brought into inner scopes. C++ doesn't require that variable declarations are placed anywhere special, and so they should be given as narrow a scope as possible.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# include <thread>
# include <chrono>
# include <iostream>

auto constexpr delay{std::chrono::milliseconds{40}};
void spin() {
  char spinner[] = {'/', '-', '\\', '|'};
  for(std::size_t i = 0; i < sizeof(spinner); i++) {
    std::cout << spinner[i] << std::flush;
    std::this_thread::sleep_for(delay);
    std::cout << "\b";
  }
}

int main() {
  int constexpr width = 20;
  std::cout <<"[" << std::string(width, ' ') << "]\r";
  for(int pos = 0; pos <= width; pos++) {
    std::cout << "[" + std::string(pos, '=');
    spin();
    std::cout << std::string(width - pos, ' ') << "]\r";
  }
}
Last edited on
Thank you for the suggestions and advice! I haven't touched C++ in many years. It seems I have much to study up on before class starts in January.
Topic archived. No new replies allowed.