编写一个程序来运行另一个已编写的程序

writing a program to run another written program

本文关键字:程序 运行 另一个 一个      更新时间:2023-10-16

我将从我的用例开始。我是一名教师,我有学生为我编写非常简单的c++控制台程序。我想通过为他们的整个应用程序编写测试工具来自动分级他们的程序。当他们使用cin请求输入时,我想提供它。当他们使用cout时,我希望能够解析他们的输出以获得正确的功能。我很确定我上大学的时候我的老师给我们做过这个。做这件事的好方法是什么?是否有比解析输出更好的方法来验证他们的代码?我应该解析它们的实际代码并寻找函数声明吗?谢谢。

我建议你不要发明轮子,使用像SPOJ引擎这样的东西,也看到它已经拥有所有必要的功能:安全沙箱,提供伪造的用户输入等等。

顺便说一下,我刚刚想起了关于自动提交测试的另一件事

您的问题相当开放,但是您可能想要研究的一件事是c++系统命令。点击这里查看更多信息

假设您要在posix操作系统(如Linux或MacOS/X)上执行此操作,那么forkpy()将非常容易地完成此操作…请参阅下面的示例,该示例在子进程中运行"ping 127.0.0.1",并在读取()时打印ping进程的stdout输出。您可以在同一文件描述符上使用write()向子进程的stdin写入。

在Windows下也可以使用类似的技术,但按照传统,在Windows上要困难和尴尬10倍。如果你需要这样做,请告诉我。

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#if defined(__linux__)
# include <pty.h>     // for forkpty() on Linux
#else
# include <util.h>    // for forkpty() on MacOS/X
#endif
int main(int argc, char ** argv)
{
   int fd;
   pid_t pid = forkpty(&fd, NULL, NULL, NULL);
   if (pid > 0)
   {
      // We're running in the parent process.  We can now write to the child process
      // (and read from it) via (fd).
      while(1)
      {
         char buf[4096];
         int numBytesRead = read(fd, buf, sizeof(buf)-1);
         if (numBytesRead > 0)
         {
            buf[numBytesRead] = '';  // ensure termination
            printf("Read from child process's stdout: [%s]n", buf);
         }
         else if (numBytesRead == 0)
         {
            printf("Child process exitedn");
            break;
         }
         else {perror("read"); break;}
      }
   }
   else if (pid == 0)
   {
      // We're running in the child process.
      // Turn off the echo, we don't want to see that back on stdout
      struct termios tios;
      if (tcgetattr(STDIN_FILENO, &tios) >= 0)
      {
         tios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
         tios.c_oflag &= ~(ONLCR); /* also turn off NL to CR/NL mapping on output */
         (void) tcsetattr(STDIN_FILENO, TCSANOW, &tios);
      }
      char * const argv[] = {"/sbin/ping", "-c", "5", "127.0.0.1", NULL};  // Replace /sbin/ping with your favorite program to run instead
      if (execvp(argv[0], argv) < 0) perror("execvp");
   }
   else if (pid < 0) perror("forkpty");
   return 0;
}

这似乎是单元测试的一个很好的用途。写一些头文件,为头文件定义的函数写单元测试,然后把头文件和单元测试交给学生,直到测试通过才给他们的作业打分。为了进一步减少浪费你的时间,让他们用-Wall -Werror编译所有的东西。

一旦测试通过了,我就会检查代码以确保它们没有为了让测试通过而做任何坏事。

我所见过的最好的c++单元测试框架是Google Test。它易于编写,易于运行。

另一方面,如果您只关心输入和输出,则只需使用bash和管道:

#!/bin/bash
for executable in * ; do
    if cat input.txt | $executable | diff - expected-output.txt > /dev/null ; then
        echo $executable passes
    else
        echo $executable fails
    fi
done