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

problems utilitizing small pauses in c code using nanosleep

我是 C 初学者,正在尝试这个和那个。

我想逐个字母地显示一个字符串,中间有微小的停顿。所以我的想法是在显示每个字符后使用 sleep 或 usleep 暂停一下,但我读到在你自己的函数中使用 nanosleep 更有意义。所以我把我的小暂停放在函数“msleep”中以获得微秒暂停。

我输出了我的字符串 3 次。 一旦进入 main(),然后在函数 (fancyOutput) 中逐个 char 的 do-while-loop 中,最终在同一个函数中再次使用 printf 来检查它是否被正确处理。

我的问题:我预计,中间输出会一个字符一个字符地工作,并以 100/1000 秒的间隔分隔,但我遇到的是在 chowing 任何字符之前有一个很长的间隔,然后如果第二行和三。看起来编译器“意识到我打算做什么,并希望修改代码以提高效率”。所以我所有的停顿似乎都集中在一个长时间的休息中。

也许你还记得电视剧“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]=='[=10=]'));
    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 是 显示,以便逐块显示信息(以优化显示速度)。

然后你需要添加一个 \n 到你的 printf 或添加一个 stdout 的刷新。

另一种解决方案是使用 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]=='[=10=]'));
    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-output 之后的解决方案。它按预期工作。

为有类似问题的人总结(猜测这也发生在 usleep 和类似的 self-made 函数中): 据我了解,printf 在 stdout 中“收集”数据,直到它“看到”\n,这表示一行结束。然后 printf“释放”标准输出。因此,在我最初的 post 中,它“保留”了 stdout 中的每个字符,在每个字符后暂停并最终在一个快速输出中释放了 stdout。

因此 fflush(stdout); 在每个字符输出后通过逐个字符清空标准输出字符。

希望对大家有帮助。