使用nanosleep在C代码中利用小暂停的问题

问题描述

我是C初学者,正在尝试这种方式。

我想逐个字母地显示一个字符串,并且之间有微小的停顿。所以我的想法是在显示每个字符后使用睡眠或usleep稍作停顿,但我读到在自己的函数中使用nanosleep更有意义。因此,我将小暂停时间放在函数“ msleep”中以获取微秒的暂停时间。

我的字符串输出了3次。 一次进入main(),然后在一个函数(fancyOutput)中按字符进行一次do-while循环,最后在与printf相同的函数中再次进行检查,以检查是否处理正确。

我的问题:我希望中间输出可以逐个字符地工作,并以100/1000秒的间隔分开,但是我遇到的情况是在中断任何char之前需要很长的休息,然后在第二和第三行进行快速输出。看起来编译器“实现了我打算做的事情,并希望修改代码以提高效率”。所以我所有的停顿似乎都花了很长的时间。

也许您想起了电视连续剧“ x文件”中的标题-我想制作类似的东西。

可以肯定,有更好,更复杂的方法来归档我要尝试的内容,但是我想学习并了解正在发生的事情。有人可以帮我吗?

我正在使用基于gcc的基于Debian的发行版上的代码时钟。

#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
}

解决方法

您遇到缓冲区问题。 当您在没有\n(换行)的情况下使用printf时,C为buffering,以便逐块显示信息(以优化显示速度)。

然后,您需要向打印文件中添加\n或添加标准输出的刷新。

另一种解决方案是使用stderr,它没有缓冲区,但是stderr的意思是不输出错误:)

您也可以选中setvbuf来更改缓冲。

#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
}
,

因此,我尝试了将fflush(stdout);放置在循环中char输出之后的解决方案。它按预期工作。

总结那些有类似问题的人(猜想这也发生在usleep和类似的自制函数中): 正如我了解的那样,printf在stdout中“收集”数据,直到它“看到” \ n,这表示行的末尾。然后,printf“释放”标准输出。因此,在我的第一篇文章中,它“保留”了stdout中的每个字符,在每个字符之后暂停了一下,最后以一个快速输出释放了stdout。

因此,fflush(stdout);在每个字符通过空的stdout字符逐个字符输出之后。

希望它可以帮助其他人。