Incorrect input validation
Your code allows someone to enter the time "24:60:60", and your program will accept it. I also see that the clock is meant to display times from 01:00:00 to 24:59:59, but it will also accept 0 as the hour. To ensure you only accept inputs for times that you would display, write:
if (h < 1 || h > 24 || m >= 60 || s >= 60)
...
Although it's rather more common that a 24-hour clock goes from 00:00:00 to 23:59:59.
Proper error reporting
When you encounter an error, the proper thing to do is to print an error message to stderr
, and then exit the program with a non-zero exit code, preferrably EXIT_FAILURE
.
Sleep(1000)
does not sleep exactly 1 second
The Sleep()
function might not sleep the exact amount of time you specify, and even if it did, printing the time and clearing the screen also takes some time. So most likely, your clock would run a little slow. To make it work correctly, you want to check what the actual time is, and right before calling Sleep()
, determine how much you need to sleep until a second has elapsed. The most portable way to get some idea of the current time is to use the clock()
function. Your loop should look like this:
clock_t next_time = clock();
while (1) {
/* Print clock */
...
clock_t current_time = clock();
next_time += CLOCKS_PER_SEC;
clock_t difference = next_time - current_time;
Sleep(difference * 1000 / CLOCKS_PER_SEC);
}
Note that while clock()
might work in practice, it's also not guaranteed to run as fast as the "wall time". Platform-dependent functions that you could use are GetSystemTime()
for Windows, and gettimeofday()
or clock_gettime()
for Linux and macOS. The principle is the same though.
Avoid calling system()
unnecessarily
system()
will cause a new shell process to be created, and then that shell will parse and execute the command you give it. This is quite inefficient for something simple as clearing the screen, and is also not platform independent (on most other operating systems, you would have to use "clear"
instead of "cls"
as the command).
There are more efficient ways to clear the screen, for example using ANSI escape codes, but there is an even simpler alternative: never go to the next line, just overwrite the current line. You can do this by using \r
in the format string, which will move the cursor back to the start of the line. I suggest just writing:
printf("\rClock: %02d:%02d:%02d", h, m, s);
fflush(stdout);
The fflush()
command is necessary to ensure the line is written to the screen immediately, as normally output to stdout
is line-buffered.
Making it more platform independent
Unfortunately, there is no standard C function to sleep for a given amount of time. On Windows, you have to use Sleep()
, on most other operating systems you have to use the POSIX nanosleep()
function. See this StackOverflow post for some suggestions to make your program compile for multiple operating systems.