C++ 编写程序以运行另一个已编写的程序

C++ 编写程序以运行另一个已编写的程序,c++,C++,我将从我的用例开始。我是一名教师,我有学生为我写的简单的C++控制台程序。我想通过为他们的整个应用程序编写一个测试工具来自动对他们的程序进行分级。当他们使用cin请求输入时,我想给出它。当他们使用cout时,我希望能够解析他们的输出以获得正确的功能。我敢肯定,在我上大学的时候,我的老师为我们做到了这一点。做这件事的好方法是什么?有没有比解析输出更好的方法来验证他们的代码?我应该解析它们的实际代码并查找函数声明吗?谢谢。 你的问题是相当开放的,但是有一件事你可能想研究的是C++系统命令。查看有关它

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

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

我建议您不要发明轮子,而使用类似的东西,它已经具备了所有必要的功能,如:安全沙箱、提供伪造用户输入等等


顺便说一句,我刚刚回忆起,

假设您将在POSIX-y操作系统(如Linux或MacOS/X)上执行此操作,forkpty()将非常轻松地执行此操作。。。请参见下面的示例,该示例在子进程中运行“ping 127.0.0.1”,并在ping进程读取()时打印出其标准输出。可以在同一文件描述符上使用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] = '\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;
}
#包括
#包括
#包括
#如果已定义(\uuuu linux\uuuuu)
#在Linux上包含//for forkpty()
#否则
#包括//用于MacOS/X上的forkpty()
#恩迪夫
int main(int argc,字符**argv)
{
int-fd;
pid\u t pid=forkpty(&fd,NULL,NULL,NULL);
如果(pid>0)
{
//我们正在父进程中运行。现在可以写入子进程
//(并从中读取)通过(fd)。
而(1)
{
char-buf[4096];
int numBytesRead=read(fd,buf,sizeof(buf)-1);
如果(numBytesRead>0)
{
buf[numBytesRead]='\0';//确保终止
printf(“从子进程的标准输出读取:[%s]\n”,buf);
}
否则如果(numBytesRead==0)
{
printf(“子进程已退出\n”);
打破
}
否则{perror(“read”);break;}
}
}
否则如果(pid==0)
{
//我们正在子进程中运行。
//关掉回音,我们不想在stdout上看到
结构termios tios;
如果(tcgetattr(标准文件号和tios)>=0)
{
tios.c|lflag&=~(ECHO | ECHO | ECHOK | ECHONL);
tios.c_of lag&=~(ONLCR);/*还关闭输出上的NL到CR/NL映射*/
(无效)tcsetattr(标准文件号、TCSANOW和tios);
}
char*const argv[]={/sbin/ping“,“-c”,“5”,“127.0.0.1”,NULL};//用您最喜欢的程序替换/sbin/ping以运行
if(execvp(argv[0],argv)<0)peror(“execvp”);
}
如果(pid<0)perror(“forkpty”);
返回0;
}

这似乎是单元测试的一个很好的用途。编写一些标题,为标题定义的函数编写单元测试,然后将标题和单元测试交给学生,在测试通过之前拒绝给他们的作业评分。为了进一步减少浪费您的时间,让他们使用
-Wall-Werror
编译所有内容

一旦测试通过,我会仔细检查代码,确保他们没有为了通过测试而做任何坏事

<>我见过的C++的最好的单元测试框架是。它易于编写和运行

另一方面,如果您只关心输入和输出,那么只需使用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

bash可能是最简单的方法。如果您坚持使用C/C++,那么首先您需要管道文件描述符,以便您可以通过自己的函数向其0(输入)和1(输出)文件描述符提供数据。请不要仅根据此自动过程的结果对其进行评分。这是您的工作和专业职责,因此请您亲自完成:)我们在这里讨论的程序有多少?此外,基于代码质量和可读性的注释与真实世界中正确的功能同样重要。对他们的标识符名称的直接反馈对于那些不理解变量(如A.)、B、C、FF、GJ等变量和函数的学生来说是非常有用的。一个好的程序不适合。所以你知道足够的C++来教,但不足以做这样的程序。陛下好的,没有人知道任何事情,但我希望老师能想出一些想法,并就具体问题寻求指导。