Sinisterly
[C] Loading Animation - Printable Version

+- Sinisterly (https://sinister.ly)
+-- Forum: Coding (https://sinister.ly/Forum-Coding)
+--- Forum: C, C++, & Obj-C (https://sinister.ly/Forum-C-C-Obj-C)
+--- Thread: [C] Loading Animation (/Thread-C-Loading-Animation)



[C] Loading Animation - ArkPhaze - 05-25-2014

A simple loader animation I wrote for Windows. Smile

[
Code:
cpp]#include <stdio.h> #include <stdlib.h> #include <windows.h> void print_progress(int percent) { const int mul = 2; // width factor percent = min(100, percent); // spinning animation static int spin_index = 0; char spinning[] = "_-\\|/-"; // bar filler int len = (percent * mul / 10) + 1; char *bar = malloc(len); memset(bar, '<', len - 1); bar[len - 1] = 0; // write display printf("%c Loading: [%*s] %*d%%\r", percent == 100 ? ' ' : spinning[spin_index], mul * 10, bar, 3, percent ); spin_index = (spin_index + 1) % strlen(spinning); free(bar); } int main() { printf("\nStarting Loader...\n"); for (int i = 10; i <= 100; i += 5) { print_progress(i); Sleep(150); } printf("\nDone...\n"); }

edit: Wow, ugly ass, and poor, syntax highlighting... Not to mention slow.

[Image: uNEtxbZ.gif]


RE: [C] Loading Animation - erpicci - 05-27-2014

How funny!
Would you consider this version I forked from your which can run both on Windows and GNU/Linux (and easily extendible to other OS)?

Code:
#include <stdio.h> #include <stdlib.h> #include <string.h> /* Wrapper for sleep function. */ #ifdef _WIN32 #include <windows.h> #define SLEEP(x) Sleep((x)) #elif __gnu_linux__ #include <unistd.h> #define SLEEP(x) usleep((x) * 1000) #else #error "OS not supported." #endif /** Update interval, in milliseconds. */ #define DELTA_T 150 /** Width factor. */ #define mul 2 /* Percentage loop values. */ #define start 10 /**< Starting value. */ #define end 100 /**< Ending value. */ #define step 5 /**< Increment. */ /** Progress bar is print. * @param[in] Current percentage */ void print_progress(unsigned int percent) { char *bar; char spinning[] = "_-\\|/-"; static int spin_index = 0; unsigned int len; /* Bar filler. */ if(percent > 100){ percent = 100; } len = (percent * mul / 10) + 1; bar = (char *) malloc(len); memset(bar, '<', len - 1); bar[len - 1] = 0; /* Write to display. */ fprintf(stderr, "%c Loading: [%*s] %3d%%\r", (percent == 100) ? ' ' : spinning[spin_index], mul * 10, bar, percent ); spin_index = (spin_index + 1) % strlen(spinning); free(bar); } /** Main. */ int main(void) { unsigned int i; printf("Starting Loader...\n"); for(i = start; i <= end; i += step){ print_progress(i); SLEEP(DELTA_T); } printf("\nDone...\n"); return 0; }

Also, could you check the Windows flag to be "_WIN32"? I don't own a Windows PC, so I cannot check myself...


RE: [C] Loading Animation - ArkPhaze - 06-12-2014

You'd do something like this:
Code:
#if defined( _WIN64 ) // Windows 64 bit code here #elif defined( _WIN32 ) // Windows 32 bit code here #else // Non-Windows code here #endif

Why did you change my original code to write to the standard error output stream though? I don't get that.
Code:
/* Write to display. */ fprintf(stderr, "%c Loading: [%*s] %3d%%\r", ... ...

A progress indicator is not any kind of error. Although I don't see the need for this to be cross platform. The usage of the function was just for demonstration, it's not part of the actual loader really, I just added some usage code in which works on Windows to demonstrate what it would look like, to anybody who compiles my code. The function itself otherwise, is already fine, and doesn't use any platform specific methods.


RE: [C] Loading Animation - erpicci - 06-12-2014

(06-12-2014, 01:54 AM)ArkPhaze Wrote: Why did you change my original code to write to the standard error output stream though? I don't get that.
When I used "stdout" insted of "stderr" it didn't work. This is what happened:
  • "Starting loader" was prompted
  • no animation was shown, and the console was in a pause-like state for some seconds (the time of the animation)
  • "Loading: [<<<<<<<<<<<<<<<<<<<<] 100%" was prompted
I think this is because stdout channel uses a buffer, so the animation string is (re-)written on it before being actually shown on the display; the stderr channel is not buffered so this does not happen. However I'm not sure at all and I'd like to know if you have any idea.

(06-12-2014, 01:54 AM)ArkPhaze Wrote: Although I don't see the need for this to be cross platform. The usage of the function was just for demonstration[...]
I don't see the need for this to be not cross platform. A GNU/Linux user who wanted to try this would have to edit the code (introducing mistakes).


RE: [C] Loading Animation - ArkPhaze - 06-22-2014

If it didn't work then you're doing something wrong, because stderr is WRONG. stdout is proper... Did you test this through a debugger or actually run the program?

Quote:I don't see the need for this to be not cross platform. A GNU/Linux user who wanted to try this would have to edit the code (introducing mistakes).

You have to re-write code anyways most of the time for things like this to be cross-platform. That's the reason why those defines even exist. I haven't tested how the carriage return works on a Unix system, I'd imagine it would be fine as long as the developers define the beginning of a line the same as in Windows or at least close enough to the same... The issue is the Sleep() function; being a Windows only function in this case.

What I REALLY MEANT about it not needing to be cross-platform was for the demo which uses Sleep() to slow the animation down. Everything else *should* already be cross platform, the only Windows specific function being used here is Sleep() and a cross platform alternative for the Sleep() function in this code is silly because as I said, it was only for demonstration purposes as to why it currently exists in the code. I don't know why you wrote a cross platform version to allow a Sleep() alternative for this reason, because in production code, you wouldn't use Sleep() to indicate progress, the progress would be determined by actual actions.

Hence why I said: "The usage of the function was just for demonstration" -- I was talking about Sleep() function in Windows here, which you've tried to make as a cross-platform function call. There's no real need IMO. They are going to replace Sleep() with something else that eats up CPU cycles anyways when they go to use this code, whether it's already a Windows system or not.


RE: [C] Loading Animation - erpicci - 06-22-2014

Sorry, I didn't see your point before.

(06-22-2014, 09:04 PM)ArkPhaze Wrote: If it didn't work then you're doing something wrong, because stderr is WRONG. stdout is proper... Did you test this through a debugger or actually run the program?
First I run it, using stdout; I saw it didn't work, so I tried through a debugger (gdb). Then I repeated using stderr.
Even through the debugger, the string is printed only at the end of the execution (when stdout is used).


(06-22-2014, 09:04 PM)ArkPhaze Wrote: I haven't tested how the carriage return works on a Unix system, I'd imagine it would be fine as long as the developers define the beginning of a line the same as in Windows or at least close enough to the same...
I think this is the case... otherwise the version using stderr wouldn't work at all, would it?


(06-22-2014, 09:04 PM)ArkPhaze Wrote: The issue is the Sleep() function; being a Windows only function in this case.[...]
I'm not sure: I tried to implement a CPU-eating function, without using "sleep" or any other thread/time function. Once again, it works using stderr but not with stdout.
That function is "compute the matrix product between A and B for 100 times, where A and B are both 100x100" (naive algorithm, no optimization, takes some milliseconds).

Now, I'm really curious to understand why this happens...


RE: [C] Loading Animation - ArkPhaze - 06-23-2014

I'm talking about running the program directly--the compiled binary, and not through any debugger.

Quote:otherwise the version using stderr wouldn't work at all, would it?

That's not the point, the point is that stderr is the standard error stream. Nothing but things related to errors should be there.

Are you testing on Linux or Windows? Are you certain that you have the correct multiplier since the time units between the two functions are not the same? You should be using nanosleep() too instead: http://linux.die.net/man/2/nanosleep

Should be x1,000,000 from microseconds to seconds, not 1000.


RE: [C] Loading Animation - erpicci - 06-23-2014

(06-23-2014, 02:12 AM)ArkPhaze Wrote: I'm talking about running the program directly--the compiled binary, and not through any debugger.
I run the program both directly and through a debugger.


(06-23-2014, 02:12 AM)ArkPhaze Wrote: That's not the point, the point is that stderr is the standard error stream. Nothing but things related to errors should be there.
I agree on this, I'm just saying that since the version printing on stderr "works", the problem should not be related to the carriage return.


(06-23-2014, 02:12 AM)ArkPhaze Wrote: Are you testing on Linux or Windows? Are you certain that you have the correct multiplier since the time units between the two functions are not the same? You should be using nanosleep() too instead: http://linux.die.net/man/2/nanosleep
Should be x1,000,000 from microseconds to seconds, not 1000.
GNU/Linux, Debian 7.0. I'm using usleep, passing 150,000 as parameter (150 milliseconds). I also tried other related functions, such as sleep and the nanosleep you suggested. Always same result.


But note that in this latest version, I completely removed the "sleep", using a time-consuming procedure instead, and getting the same behaviour:
Code:
#include <stdio.h> #include <stdlib.h> #include <string.h> /** Width factor. */ #define mul 2 /* Percentage loop values. */ #define start 10 /**< Starting value. */ #define end 100 /**< Ending value. */ #define step 5 /**< Increment. */ /** A time-consuming procedure. */ void CPU_eat(void) { int i, j, k, n, sum; int A[10000], B[10000], C[10000]; for(n = 0; n < 100; n++){ for(i = 0; i < 100; i++){ for(j = 0; j < 100; j++){ sum = 0; for(k = 0; k < 100; k++){ sum = A[i*10 + k] * B[k*10 + j]; } C[i, j] += sum; } } } } /** Progress bar is print. * @param[in] Current percentage */ void print_progress(unsigned int percent) { char *bar; char spinning[] = "_-\\|/-"; static int spin_index = 0; unsigned int len; /* Bar filler. */ if(percent > 100){ percent = 100; } len = (percent * mul / 10) + 1; bar = (char *) malloc(len); memset(bar, '<', len - 1); bar[len - 1] = 0; /* Write to display. */ fprintf(stdout, "%c Loading: [%*s] %3d%%\r", (percent == 100) ? ' ' : spinning[spin_index], mul * 10, bar, percent ); spin_index = (spin_index + 1) % strlen(spinning); free(bar); } /** Main. */ int main(void) { unsigned int i; printf("Starting Loader...\n"); for(i = start; i <= end; i += step){ print_progress(i); CPU_eat(); } printf("\nDone...\n"); return 0; }

Behaviour using stdout:
[Image: 6s4zk0.jpg]

Behaviour using stderr:
[Image: j835lw.jpg]


RE: [C] Loading Animation - bluedog.tar.gz - 06-23-2014

Looks pretty neat,
But why did you chose for "<" instead of ">"

For me it would make more sense:

Loading: [>>>>>>>>> ] 80%

Then

Loading:[ <<<<<<<] 80%



Its the same with swiping to unlock your phone, you swipe from left to right.
Same again with reading, from left to right.

I hope that helps Smile


RE: [C] Loading Animation - ArkPhaze - 06-24-2014

I wrote the code, it's easily changeable though. Smile