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

时间:2013-06-05 21:16:15

标签: c++

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

4 个答案:

答案 0 :(得分:3)

我建议你不要发明轮子并使用类似SPOJ Enginesee also的东西,它已具备所有必要的功能:安全沙盒,提供伪造的用户输入等等。

顺便说一下,我刚刚回忆起one more thing for automatic submission testing

答案 1 :(得分:0)

你的问题是相当开放的,但你可能想要研究的一件事是C ++系统命令。查看有关它的更多信息here

答案 2 :(得分:0)

假设您将在Linux或MacOS / X等POSIX-y操作系统上执行此操作,forkpty()将非常轻松地执行此操作...请参阅下面的示例,其中运行“ping 127.0.0.1”一个子进程并打印出ping进程的stdout输出,因为它是read()的。您可以使用相同文件描述符上的write()写入子进程的stdin。

在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] = '\0';  // ensure termination
            printf("Read from child process's stdout: [%s]\n", buf);
         }
         else if (numBytesRead == 0)
         {
            printf("Child process exited\n");
            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;
}

答案 3 :(得分:0)

这似乎很适合单元测试。写一些标题,为标题定义的函数编写单元测试,然后给学生提供标题和单元测试,并拒绝评估他们的工作,直到测试通过。为了进一步减少浪费你的时间,让他们用-Wall -Werror编译所有内容。

一旦测试通过,我会查看代码以确保他们没有做任何不好的事情只是为了让测试通过。

我见过的最适合C ++的单元测试框架是Google Test。它易于编写且易于运行。

另一方面,如果你关心的只是输入和输出,只需使用bash和pipe:

#!/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