0

I am trying to build a traffic light simulator which requires that I print green for the first 8 seconds at 1 second intervals, yellow for the next 4 seconds at 1 second intervals and red for the last 8 seconds at 1 second intervals. How can I use time.h to implement this in C?

This is my attempt, but I only get an output that prints green nonstop at intervals which are not 1 second long.

// Traffic light simul`ator

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t start, end;
    double elapsed;
    time(&start);  /* start the timer */
    do {
        time(&end);
        elapsed = difftime(end, start);
        if (elapsed )
        {
            printf("green");
        }
    } while(elapsed < 9);
}   
AbdelAziz AbdelLatef
  • 3,650
  • 6
  • 24
  • 52
mikael
  • 3
  • 1
  • 6
  • Well, _no_ part of your code ever prints "yellow" or "red", so that's why it only prints "green". I believe it will print "green" for about 9 seconds, but it will print it as fast as it possibly can -- you'll probably see many screenfuls of "green"! The reason for that is that you never wait for 1 second after you print "green". One other problem is that you don't have a newline (`\n`) after "green". So the program loads up the terminal buffer with "greengreengreengreen..." and prints out a bunch (probably 4096 letters worth) every time it gets full. – Dave M. Nov 17 '19 at 22:32
  • 2
    I didn't write the "yellow" or "red" part because I couldn't get the "green" part to work. – mikael Nov 17 '19 at 22:34
  • Fair enough. You can make some progress by doing two things: first, put a `\n` at the end of your "green" string. And second, `sleep( 1 )` after you print "green". (`sleep()` is probably not exactly accurate, so if you want exactly one second, you'll have to do something else, but at least it'll get you closer to 9 copies of "green" instead of 29 bazillion copies!) – Dave M. Nov 17 '19 at 22:38
  • 1) Thanks for trying to make this a minimal example. That's greatly appreciated. 2) Have you tried printing the value of `elasped`? 3) Have you tried using `sleep()`? –  Nov 17 '19 at 22:49
  • To cause delays in your code waiting for a time , you should use an operating system function otherwise your program will negatively impact on performance of other running programs. This problem is sometimes called "tight loop". The OS function will know it can suspend your program's thread until the moment you are waiting for is reached. There is a cross-platform standard sleep [thrd_sleep](https://en.cppreference.com/w/c/thread/thrd_sleep) although some compilers might not be up to date with the standard – M.M Nov 17 '19 at 22:52
  • @ Chipster Nope I haven't tried printing the value of `elapsed`. But I did use `sleep()` after I tool a look @Engineer 's answer, and it seems to work well. – mikael Nov 17 '19 at 23:00
  • Suggest using the function: [setitimer](http://man7.org/linux/man-pages/man3/setitimer.3p.html) – user3629249 Nov 18 '19 at 00:37

3 Answers3

3

The following seems to work as intended:

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t start, end;
    double elapsed, prev_elapsed = 0.0;
    time(&start);  /* start the timer */
    do
    {
        time(&end);
        elapsed = difftime(end, start);
        if (elapsed >= prev_elapsed+1.0)
        {
            printf("green\n");
            prev_elapsed = elapsed;
        }
    } while(elapsed < 9.0);
}

Here we keep track of the 'current' elapsed time, and the time when the previous one-second tick was noted. When this 'current' elapsed differs from the "previous" elapsed we know that one second (or, more likely, slightly more) has gone by, and we print "green".

AbdelAziz AbdelLatef
  • 3,650
  • 6
  • 24
  • 52
0

Your code will just print "green" as fast as it can because if(elapsed) will always happen because the condition is always True. You can use difftime but will need to re-work your code a bit (I think it is adding maybe 2-3 lines). Is there a reason you can't just use sleep? It seems to be a simpler solution: print "green", call sleep(1), repeat 7 more times, move on to printing "yellow", and so on. Hope this helps!

Edit: if(elapsed) is True as long as the value elapsed is not equal to 0, and just because computers don't act instantaneously there will always be a non-zero time difference returned by difftime.

Engineer
  • 119
  • 3
  • Or sleep(1000) if on Windows. – Fredrik Nov 17 '19 at 22:43
  • 1
    @Engineer I tried what you said and used `sleep()` only. It seems to work well. Thank you. – mikael Nov 17 '19 at 23:02
  • @Engineer I actually miswrote `if(elapsed)`, I meant to write `if(elapsed == 1)`. It should work then, shouldn't it? – mikael Nov 17 '19 at 23:04
  • `elapsed == 1` does a float/double comparison. That doesn't always work out very well because of [the way floating point numbers work](https://stackoverflow.com/q/588004/10957435). It's better to use `>=`. –  Nov 17 '19 at 23:21
  • No because elapsed will probably never equal 1 EXACTLY. – Engineer Nov 17 '19 at 23:21
  • For these timing like codes, you shouldn't be asking "Is the time difference 1 second?", but you should be asking "Has 1 second elapsed yet?". If not, then the code does whatever, calculates a new elapsed value and then asks again. For example, if elapsed = 0.8578, your code continues, then the next iteration suppose elapsed = 1.02343 so you code says "Yep, I've waited 1 second..time to print" – Engineer Nov 17 '19 at 23:25
0

Okay, so I figured out what is going on here.

difftime() returns double. That means, fractional seconds can be returned. If they are (which they probably will be), then that means you have some value in elapsed, which means it will not evaluate to false--even though 1 full second has not yet passed.

If you want elapsed to be greater than 1, then just check for it:

if (elapsed >= 1)
{
    printf("green");
}

That should do the trick.

  • Yeah that works... I got that from @Bob Jarvis 's answer. Thank you. – mikael Nov 17 '19 at 23:14
  • You're welcome. Feel free to upvote any answers that helped you, and please mark your question as solved by selecting the check mark next to the answer that helped you the most. This accepts that answer, and lets future readers know what ultimately solved your problem. –  Nov 17 '19 at 23:17