2

I'm trying to reproduce from code from Ivor Horton's Beginning C. I couldn't get the results that the code is expecting so I wrote a smaller program with the specific code that I'm having a problem with.

Please see the first for loop. It should print out two random numbers. If I comment out the second for loop which creates an approximate 5 second delay and the subsequent printf("\rHello) I will see the two random numbers. However if I uncomment the second for loop and the subsequent printf, I will never see the two random numbers, only the output Hello, even though the for loop delays the printf("\rHello") for 5 seconds. I thought I would be able to see the two random numbers for at least 4 seconds or so before they are overwritten by the printf("\rHello"). Can anybody tell me what is going on here?

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>

int main(void) {
    clock_t wait_start = 0;
    time_t seed = 0;
    unsigned int digits = 2;
    unsigned int seconds = 5;
  
    wait_start = clock();
    srand((unsigned int) time(&seed));
    for (unsigned int i = 1; i <= digits; ++i)
        printf("%u ", rand() % 10);
  
    // printf("%Lf\n", ((long double)clock()) / CLOCKS_PER_SEC);
    for (; clock() - wait_start < seconds * CLOCKS_PER_SEC; )
        ;
    // printf("%Lf\n", ((long double)clock()) / CLOCKS_PER_SEC);
    printf("\rHello");
    return 0;
}

The suggested answer is good, if you know what you're looking for. The title of my question is very straight forward literal explanation of what is happening in my code. A beginner may not search for "flush" and "stdout buffer". I didn't search for that and didn't find this solution to my question. It is complementary to the solution to this question to give more understanding to the beginner. The solution to my question gave a straight-forward solution to my question, and then it was followed with more information giving insight as to why I need to use fflush.

Bucephalus
  • 291
  • 1
  • 2
  • 9
  • yep, that did it, thanks @user3121023 – Bucephalus Sep 04 '21 at 11:54
  • 3
    Does this answer your question? [What are the rules of automatic stdout buffer flushing in C?](https://stackoverflow.com/questions/39536212/what-are-the-rules-of-automatic-stdout-buffer-flushing-in-c) – Yun Sep 04 '21 at 12:08
  • 1
    Yes, that does give me more insight @Yun . It prompted me to do another experiment where i replaced the `fflush(stoud)` with `printf("\n")` and I got a successful result in being able to see the two random numbers output before "Hello" was output 5 seconds later, be it printed on the line after now. Thanks for the pointer to more information. – Bucephalus Sep 04 '21 at 12:17

1 Answers1

1

The reason the random digits do not appear is you do not flush the stdout stream to the terminal and since you did not output a trailing newline, it is pending in the stream buffer because stdout is usually line buffered by default when attached to a terminal.

Note also that waiting for 5 seconds with a busy loop asking for elapsed CPU time is wasteful. You should instead use a sleep() system call or the equivalent call on the target system (probably _sleep() on Microsoft legacy systems).

Here is a modified version:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

#if defined _WIN32 || defined _WIN64
#include <windows.h>
#else
#include <unistd.h>
#endif

int main(void) {
    int digits = 2;
    int seconds = 5;
  
    srand((unsigned int)time(NULL));
    for (int i = 0; i < digits; i++) {
        printf("%d ", rand() % 10);
    }
    fflush(stdout);

#if defined _WIN32 || defined _WIN64
    Sleep(seconds * 1000UL);
#else
    sleep(seconds);
#endif
    printf("\rHello\n");
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Yeah you're right @chqrlie and it's good to know that about busy waiting. However this code was from chapter 4 on loops and I think it was trying to demonstrate an abstruse way of employing a for loop. Good answer to my question by the way. Thankyou. – Bucephalus Sep 04 '21 at 12:53
  • 1
    Standard output is commonly initially line buffered if connected to a terminal, but the requirement in the C standard is just that it not be fully buffered. It is allowed to be unbuffered. – Eric Postpischil Sep 04 '21 at 13:06
  • @EricPostpischil: yes, I should have been more precise. I wonder how one can test portably if input or output is pending in a stream? – chqrlie Sep 04 '21 at 14:23
  • @chqrlie [Perhaps `_WIN32`](https://stackoverflow.com/a/8249232/2505965)? (See: [*Predefined macros*](https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros)) – Oka Sep 04 '21 at 16:02
  • @chqrlie 64-bit systems should define that macro (as well as the more specific `_WIN64`). – Oka Sep 04 '21 at 16:09
  • @Oka: OK I'll use both and forget about 16-bit Windows :) – chqrlie Sep 04 '21 at 16:13