Search code examples
cgccnanotime

problems utilitizing small pauses in c code using nanosleep


I am a C beginner and trying this and that.

I want to display a string letter by letter with tiny pauses in between. So my idea was a small pause using sleep or usleep after displaying each char but I read that using nanosleep in your own function makes more sense. So I put my little pauses in a function "msleep" to get microseconds pauses.

I output my string 3 times. Once in the main(), then in a do-while-loop in a function (fancyOutput) char by char, and eventually in the same function with printf again to check, if it was handled over correctly.

My problem: I expected, that the middle output would work char by char and separated by 100/1000 seconds breaks, but what I experience is a long break before chowing any char and then a fast output if line two and three. It looks like the compiler "realized what I am planning to do and wants to modify the code to be more efficient." So all my pauses seemed to be combined in one long break.

Maybe you remeber the captions in the tv series "x files" - something like that I want to produce.

For sure there are better and more sophisticated ways to archieve what I am going to try but I want to learn and understand what is going on. Can someone help me with that?

I am using codeclocks on a debian-based distro with gcc.

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

int msleep(long tms);
void fancyOutput(char inputToOutput[]);

int msleep(long tms)
{
    struct timespec ts;
    int ret;

    if (tms < 0)
    {
    return -1;
    }

    ts.tv_sec = tms / 1000;
    ts.tv_nsec = (tms % 1000) * 1000000;

    do
    {
    // printf("sleeping for %d", ret);
    ret = nanosleep(&ts, &ts);
    }
    while (ret);

    return ret;
}

void fancyOutput(char inputToOutput[])
{
    int counter = 0;
    do
    {
        printf("%c", inputToOutput[counter]);
        msleep(100);
        ++counter;
    }
    while (!(inputToOutput[counter]=='\0'));
    printf("\n");

    printf("%s\n", inputToOutput); // only check, if string was properly handled over to function
}

char output[] = "This string shall appear char by char in the console.";

void main(void)
{
    printf("%s\n", output); // only check, if string was properly set and initialized
    fancyOutput(output); // here the function above is called to output the string char by cchar with tiny pauses between
}

Solution

  • You are getting problem with buffer. When you use printf with no \n (new line) C is buffering the display in order to display information block by block (to optimize displaying speed).

    Then you need to either add a \n to your printf or add a flush of the stdout.

    An other solution will be to use stderr, which got no buffer, but stderr is meant for error not output :)

    You can also check setvbuf in order to change the buffering.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int msleep(long tms);
    void fancyOutput(char inputToOutput[]);
    
    int msleep(long tms)
    {
        struct timespec ts;
        int ret;
    
        if (tms < 0)
        {
        return -1;
        }
    
        ts.tv_sec = tms / 1000;
        ts.tv_nsec = (tms % 1000) * 1000000;
    
        do
        {
        // printf("sleeping for %d", ret);
        ret = nanosleep(&ts, &ts);
        }
        while (ret);
    
        return ret;
    }
    
    void fancyOutput(char inputToOutput[])
    {
        int counter = 0;
        do
        {
            printf("%c", inputToOutput[counter]);
            flush(stdout);
            msleep(100);
            ++counter;
        }
        while (!(inputToOutput[counter]=='\0'));
        printf("\n");
    
        printf("%s\n", inputToOutput); // only check, if string was properly handled over to function
    }
    
    char output[] = "This string shall appear char by char in the console.";
    
    void main(void)
    {
        printf("%s\n", output); // only check, if string was properly set and initialized
        fancyOutput(output); // here the function above is called to output the string char by cchar with tiny pauses between
    }