使用此 C 程序模拟打字

作者:Jim Hall

我最近创建了一个视频演示,展示如何在命令行上完成一些工作,但是当我尝试录制视频时,我不断遇到问题。我不是那种可以一边在键盘上打字一边谈论它的人。我很快意识到我需要一种模拟打字的方法,这样我就可以创建一个“预制”演示,以便在我的视频中进行解说。

在搜索一番后,我没有在我的发行版中找到可以模拟打字的命令。我并不感到惊讶;这不是人们需要做的常见事情。所以,我编写了自己的程序来完成这项工作。

编写一个模拟打字的程序并不像最初看起来那么困难。我需要我的程序像 echo 命令一样工作,它可以显示作为命令行参数给出的输出。我添加了命令行选项,以便我可以设置程序“打字”每个字母之间的延迟,以及空格和换行符的额外延迟。该程序基本上对给定字符串中的每个字符执行以下操作

  1. 插入延迟。
  2. 打印字符。
  3. 刷新输出缓冲区,使其显示在屏幕上。

首先,我需要一种模拟打字延迟的方法,例如某人打字缓慢,或在键入下一个单词或按 Enter 键之前暂停。用于创建延迟的 C 函数是 usleep(useconds_t usec)。您可以使用 usleep() 以及您希望程序暂停的微秒数。因此,如果您想等待一秒钟,您可以使用 usleep(1000000)

以微秒为单位工作意味着我需要输入太多的零,所以我编写了一个名为 msleep(int millisec) 的简单包装器,它以毫秒为单位执行相同的操作


int
msleep (int millisec)
{
  useconds_t usec;
  int ret;


  /* wrapper to usleep() but values in milliseconds instead */


  usec = (useconds_t) millisec *1000;
  ret = usleep (usec);
  return (ret);
}

接下来,我需要在每次延迟后将字符推送到屏幕。通常,您可以使用 putchar(int char) 将单个字符发送到标准输出(例如屏幕),但在发送换行符之前,您实际上看不到输出。为了解决这个问题,您需要手动刷新输出缓冲区。C 函数 fflush(FILE *stream) 将为您刷新输出流。如果您在每个 fflush() 之前放置一个 delay(),则看起来好像有人在键入每个字符之间稍微停顿了一下。

这是我编写的一个简单的函数来模拟打字。echodelay() 函数接受描述打印字符、空格和换行符之前的延迟的参数。最后一个参数是要打印的字符串。该函数循环遍历字符串并在打印每个字符之前暂停,然后刷新输出缓冲区。效果是每个字符似乎一次出现一个,就像有人在键盘上打字一样


void
echodelay (int chdelay, int spdelay, int nldelay, char *string)
{
  int pos = 0;


  /* add a delay between printing each character in the string,
     depending on the character */


  do
    {
      switch (string[pos])
        {
        case '\0':             /* new line */
          msleep (nldelay);
          break;
        case ' ':              /* space */
          msleep (spdelay);
          break;
        default:               /* character */
          msleep (chdelay);
          break;
        }


      putchar (string[pos]);
      fflush (stdout);
    }
  while (string[pos++] != '\0');
}

有了这个函数,编写一个父 main() 函数来解析命令行,设置不同的延迟,并调用 echodelay() 函数来生成具有适当延迟的输出,这是一个简单的过程


/* echodelay.c */


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


void echodelay (int chdelay, int spdelay, int nldelay,
 ↪char *string);
int msleep (int millisec);
int atoipos (char *string);


int
main (int argc, char **argv)
{
  int opt;
  int chdelay = 0, spdelay = 0, nldelay = 0;


  /* parse command line */


  while ((opt = getopt (argc, argv, "c:s:n:")) != -1)
    {
      switch (opt)
        {
        case 'c':              /* -c nnn */
          chdelay = atoipos (optarg);
          break;
        case 's':              /* -s nnn */
          spdelay = atoipos (optarg);
          break;
        case 'n':              /* -n nnn */
          nldelay = atoipos (optarg);
          break;
        default:               /* unrecognized option */
          fprintf (stderr, "Usage: echodelay [-c millisec]
           ↪[-s millisec] [-n millisec] [text..]\n");
          exit (1);
          break;
        }
    }


  /* pass all remaining options as text to echodelay() */


  for (opt = optind; opt < argc; opt++)
    {
      echodelay (chdelay, spdelay, nldelay, argv[opt]);
      putchar (' ');
    }


  putchar ('\n');


  exit (0);
}


void
echodelay (int chdelay, int spdelay, int nldelay, char *string)
{
...
}


int
msleep (int millisec)
{
...
}


int
atoipos (char *string)
{
  int val;

  /* wrapper to atoi() but always a positive return value */


  val = atoi (string);


  if (val < 0)
    {
      val = 0;
    }


  return (val);
}

并像这样编译它


gcc -Wall -o echodelay echodelay.c

在 shell 脚本中,我有命令来打印“提示符”,然后模拟在执行命令之前键入命令——例如,此命令用于在您的 /tmp 目录中生成一个随机大小的文件


echo -n 'prompt$'
echodelay -c 500 -s 1000 -n 2000 'ls -lh /tmp'
ls -lh /tmp

这是一个相当简单的 C 程序来模拟打字。我快速编写它来完成一项工作,但它可以作为在我解说操作视频时模拟打字的解决方案。这样,当我想描述它时,我不需要考虑我正在打字的内容。如果您需要为类似的任务模拟打字,我希望您发现此程序有用。

Jim Hall 是一位开源软件倡导者和开发人员,可能最出名的是 FreeDOS 的创始人。Jim 在 GNOME 等开源软件项目的可用性测试中也非常活跃。在工作中,Jim 是 Hallmentum 的 CEO,Hallmentum 是一家 IT 执行咨询公司,帮助 CIO 和 IT 领导者进行战略规划和组织发展。

加载 Disqus 评论