简体   繁体   English

如何从另一个程序运行程序并通过 c 或 c++ 中的 stdin 将数据传递给它?

[英]How do I run a program from another program and pass data to it via stdin in c or c++?

Say I have an .exe , lets say sum.exe .假设我有一个.exe ,让我们说sum.exe Now say the code for sum.exe is现在说sum.exe的代码是

void main ()
{
 int a,b;
 scanf ("%d%d", &a, &b);
 printf ("%d", a+b);
}

I wanted to know how I could run this program from another c/c++ program and pass input via stdin like they do in online compiler sites like ideone where I type the code in and provide the stdin data in a textbox and that data is accepted by the program using scanf or cin.我想知道如何从另一个 c/c++ 程序运行这个程序并通过 stdin 传递输入,就像他们在 ideone 等在线编译器站点中所做的那样,我在其中键入代码并在文本框中提供 stdin 数据,并且该数据被接受该程序使用 scanf 或 cin。 Also, I wanted to know if there was any way to read the output of this program from the original program that started it.另外,我想知道是否有任何方法可以从启动它的原始程序中读取该程序的输出。

In C on platforms whose name end with X (ie not Windows), the key components are:在名称以 X 结尾的平台(即不是 Windows)上的 C 中,关键组件是:

  1. pipe - Returns a pair of file descriptors, so that what's written to one can be read from the other. pipe - 返回一对文件描述符,以便可以从另一个读取写入其中的内容。

  2. fork - Forks the process to two, both keep running the same code. fork - 将进程fork为两个,两个都继续运行相同的代码。

  3. dup2 - Renumbers file descriptors. dup2 - 重新编号文件描述符。 With this, you can take one end of a pipe and turn it into stdin or stdout.有了这个,您可以将管道的一端转换为标准输入或标准输出。

  4. exec - Stop running the current program, start running another, in the same process. exec - 停止运行当前程序,在同一进程中开始运行另一个程序。

Combine them all, and you can get what you asked for.将它们全部结合起来,您就可以获得所需的东西。

The easiest way I know for doing this is by using the popen() function.我知道的最简单的方法是使用popen()函数。 It works in Windows and UNIX.它适用于 Windows 和 UNIX。 On the other way, popen() only allows unidirectional communication.另一方面, popen()只允许单向通信。

For example, to pass information to sum.exe (although you won't be able to read back the result), you can do this:例如,要将信息传递给sum.exe (虽然您将无法读回结果),您可以这样做:

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

int main()
{
    FILE *f;

    f = popen ("sum.exe", "w");
    if (!f)
    {
        perror ("popen");
        exit(1);
    }

    printf ("Sending 3 and 4 to sum.exe...\n");
    fprintf (f, "%d\n%d\n", 3, 4);

    pclose (f);
    return 0;
}

This is my solution and it worked:这是我的解决方案,它有效:

sum.cpp总和文件

#include "stdio.h"
int main (){
  int a,b;
  scanf ("%d%d", &a, &b);
  printf ("%d", a+b);
  return 0;
}

test.cpp测试.cpp

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

int main(){
  system("./sum.exe < data.txt");
  return 0;
}

data.txt数据.txt

3 4

Try this solution :)试试这个解决方案:)

It sounds like you're coming from a Windows environment, so this might not be the answer you are looking for, but from the command line you can use the pipe redirection operator '|'听起来您来自 Windows 环境,所以这可能不是您正在寻找的答案,但是从命令行您可以使用管道重定向运算符“|” to redirect the stdout of one program to the stdin of another.将一个程序的标准输出重定向到另一个程序的标准输入。 http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true

You're probably better off working in a bash shell, which you can get on Windows with cygwin http://cygwin.com/你可能最好在 bash shell 中工作,你可以在 Windows 上使用 cygwin http://cygwin.com/

Also, your example looks like a mix of C++ and C, and the declaration of main isn't exactly an accepted standard for either.此外,您的示例看起来像是 C++ 和 C 的混合体,并且 main 的声明并不完全是公认的标准。

How to do so is platform dependent.如何做到这一点取决于平台。

Under windows, Use CreatePipe and CreateProcess.在 windows 下,使用 CreatePipe 和 CreateProcess。 You can find example from MSDN : http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx您可以从 MSDN 找到示例: http : //msdn.microsoft.com/en-us/library/windows/desktop/ms682499 (v= vs.85).aspx

Under Linux/Unix, you can use dup() / dup2()在 Linux/Unix 下,您可以使用dup() / dup2()

One simple way to do so is to use a Terminal (like command prompt in windows) and use |一种简单的方法是使用终端(如 Windows 中的命令提示符)并使用 | to redirect input/output.重定向输入/输出。

Example:例子:

program1 | program2

This will redirect program1's output to program2's input.这会将程序 1 的输出重定向到程序 2 的输入。 To retrieve/input date, you can use temporary files, If you don't want to use temporary files, you will have to use pipe.要检索/输入日期,您可以使用临时文件,如果您不想使用临时文件,则必须使用管道。

For Windows, (use command prompt):对于 Windows,(使用命令提示符):

program1 <input >output 

For Linux, you can use tee utility, you can find detail instruction by typing man tee in linux terminal对于 Linux,您可以使用tee实用程序,您可以通过在 linux 终端中键入man tee来查看详细说明

How to do this (you have to check for errors ie. pipe()==-1 , dup()!=0 , etc, I'm not doing this in the following snippet).如何执行此操作(您必须检查错误,即pipe()==-1dup()!=0等,我不会在以下代码段中执行此操作)。

This code runs your program "sum", writes "2 3" to it, and than reads sum's output.此代码运行您的程序“sum”,向其写入“2 3”,然后读取 sum 的输出。 Next, it writes the output on the stdout.接下来,它将输出写入标准输出。

#include <iostream>
#include <sys/wait.h>
#include <unistd.h>

int main() {

    int parent_to_child[2], child_to_parent[2];
    pipe(parent_to_child);
    pipe(child_to_parent);

    char name[] = "sum";
    char *args[] = {name, NULL};
    switch (fork()) {

    case 0:
        // replace stdin with reading from parent
        close(fileno(stdin));
        dup(parent_to_child[0]);
        close(parent_to_child[0]);

        // replace stdout with writing to parent
        close(fileno(stdout));
        dup(child_to_parent[1]);
        close(child_to_parent[1]);

        close(parent_to_child[1]); // dont write on this pipe
        close(child_to_parent[0]); // dont read from this pipe

        execvp("./sum", args);
        break;

    default:
        char msg[] = "2 3\n";

        close(parent_to_child[0]); // dont read from this pipe
        close(child_to_parent[1]); // dont write on this pipe

        write(parent_to_child[1], msg, sizeof(msg));
        close(parent_to_child[1]);

        char res[64];
        wait(0);
        read(child_to_parent[0], res, 64);
        printf("%s", res);
        exit(0);
    }
}

I'm doing what @ugoren suggested in their answer :我正在做@ugoren在他们的回答中建议的事情:

  • Create two pipes for communication between processes创建两个管道用于进程之间的通信
  • Fork叉子
  • Replace stdin, and stdout with pipes' ends using dup使用dup用管道末端替换 stdin 和 stdout
  • Send the data through the pipe通过管道发送数据

Based on a few answers posted above and various tutorials/manuals, I just did this in Linux using pipe() and shell redirection.根据上面发布的一些答案和各种教程/手册,我只是在 Linux 中使用pipe()和 shell 重定向来完成此操作。 The strategy is to first create a pipe, call another program and redirect the output of the callee from stdout to one end of the pipe, and then read the other end of the pipe.策略是先创建一个管道,调用另一个程序并将被调用者的输出从stdout重定向到管道的一端,然后再读取管道的另一端。 As long as the callee writes to stdout there's no need to modify it.只要被调用者写入stdout ,就不需要修改它。

In my application, I needed to read a math expression input from the user, call a standalone calculator and retrieve its answer.在我的应用程序中,我需要读取用户输入的数学表达式,调用独立计算器并检索其答案。 Here's my simplified solution to demonstrate the redirection:这是我演示重定向的简化解决方案:

#include <string>
#include <unistd.h>
#include <sstream> 
#include <iostream> 

// this function is used to wait on the pipe input and clear input buffer after each read    
std::string pipeRead(int fd) { 
    char data[100];
    ssize_t size = 0;
    while (size == 0) {
        size = read(fd, data, 100);
    }
    std::string ret = data;
    return ret;
}

int main() {
    // create pipe
    int calculatorPipe[2];
    if(pipe(calculatorPipe) < 0) {
        exit(1);
    }
    
    std::string answer = "";
    std::stringstream call;

    // redirect calculator's output from stdout to one end of the pipe and execute
    // e.g. ./myCalculator 1+1 >&8
    call << "./myCalculator 1+1 >&" << calculatorPipe[1];
    system(call.str().c_str());

    // now read the other end of the pipe
    answer = pipeRead(calculatorPipe[0]);
    std::cout << "pipe data " << answer << "\n";

    return 0;
}

Obviously there are other solutions out there but this is what I can think of without modifying the callee program.显然还有其他解决方案,但这是我可以在不修改被调用程序的情况下想到的。 Things might be different in Windows though.不过,Windows 中的情况可能有所不同。

Some useful links:一些有用的链接:

https://www.geeksforgeeks.org/pipe-system-call/ https://www.geeksforgeeks.org/pipe-system-call/

https://www.gnu.org/software/bash/manual/html_node/Redirections.html https://www.gnu.org/software/bash/manual/html_node/Redirections.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM