Как запустить программу из другой программы и передать ей данные через стандартный ввод в c или c++?

Скажем, у меня есть exe, скажем, sum.exe. Теперь скажем, что код для sum.exe

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

Я хотел знать, как я могу запустить эту программу из другой программы c/c++ и передать ввод через стандартный ввод, как это делается на сайтах онлайн-компиляторов, таких как ideone, где я набираю код и предоставляю данные стандартного ввода в текстовом поле, и эти данные принимаются программа с помощью scanf или cin. Кроме того, я хотел знать, есть ли способ прочитать вывод этой программы из исходной программы, которая ее запустила.


person Shehzan    schedule 20.01.2014    source источник
comment
Вы смотрели на трубы и как они работают?   -  person cup    schedule 20.01.2014
comment
dup2, скорее всего, приведет вас туда, куда вы хотите. идти. Удачи.   -  person WhozCraig    schedule 20.01.2014
comment
Вы можете делать все, что могли бы сделать из командной строки, используя std::system, включая перенаправление ввода и вывода.   -  person Hulk    schedule 20.01.2014


Ответы (6)


Как это сделать, зависит от платформы.

Под окнами используйте CreatePipe и CreateProcess. Вы можете найти пример из MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx

В Linux/Unix вы можете использовать dup() / dup2()

Один простой способ сделать это — использовать Терминал (например, командную строку в Windows) и использовать | для перенаправления ввода/вывода.

Пример:

program1 | program2

Это перенаправит вывод программы1 на ввод программы2. Чтобы получить/ввести дату, вы можете использовать временные файлы. Если вы не хотите использовать временные файлы, вам придется использовать канал.

Для Windows (используйте командную строку):

program1 <input >output 

Для Linux вы можете использовать утилиту tee, вы можете найти подробную инструкцию, набрав man tee в терминале linux.

person wacky6    schedule 20.01.2014

В C на платформах, имена которых заканчиваются на X (т. е. не Windows), ключевыми компонентами являются:

  1. pipe — возвращает пару файловых дескрипторов, так что то, что написано в одном, может быть прочитано из другого.

  2. fork — разветвляет процесс на два, оба продолжают выполнять один и тот же код.

  3. dup2 — Перенумеровывает файловые дескрипторы. При этом вы можете взять один конец канала и превратить его в стандартный ввод или стандартный вывод.

  4. exec - Прекратить выполнение текущей программы, запустить другую в том же процессе.

Объедините их все, и вы получите то, о чем просили.

person ugoren    schedule 20.01.2014
comment
Вы, вероятно, имели в виду В Linux ключевые компоненты. - person Lundin; 20.01.2014
comment
@Lundin, вы, вероятно, имели в виду В средах POSIX ...;) - person Shahbaz; 20.01.2014
comment
@Shahbaz Поскольку никто, кроме людей * nix, похоже, не заботится о POSIX, это, по сути, одно и то же. - person Lundin; 20.01.2014
comment
@Lundin, я не хочу спорить. Просто сообщаю вам, что *nix — это не просто Linux. В любом случае, я просто сказал это для развлечения, забудьте об этом. - person Shahbaz; 20.01.2014
comment
@Shahbaz GNU не Unix? :) - person Lundin; 20.01.2014
comment
@Lundin, QNX - это не Linux? - person Shahbaz; 20.01.2014
comment
Неважно, перечисленные здесь функции не существуют в языке C. - person Lundin; 20.01.2014

Самый простой известный мне способ сделать это — использовать функцию popen(). Он работает в Windows и UNIX. С другой стороны, popen() разрешает только однонаправленную связь.

Например, чтобы передать информацию в 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;
}
person mcleod_ideafix    schedule 20.01.2014

Это мое решение, и оно сработало:

сумма.cpp

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

test.cpp

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

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

данные.txt

3 4

Попробуйте это решение :)

person Alessandro    schedule 15.11.2016

Похоже, вы пришли из среды Windows, так что это может быть не тот ответ, который вы ищете, но из командной строки вы можете использовать оператор перенаправления канала '|' для перенаправления stdout одной программы на stdin другой. http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true

Вам, вероятно, лучше работать в оболочке bash, которую вы можете получить в Windows с помощью cygwin http://cygwin.com/

Кроме того, ваш пример выглядит как смесь C++ и C, и объявление main не является общепринятым стандартом ни для одного из них.

person Spearman    schedule 20.01.2014

Как это сделать (вы должны проверить наличие ошибок, т.е. pipe()==-1, dup()!=0 и т. д., я не делаю этого в следующем фрагменте).

Этот код запускает сумму вашей программы, записывает в нее 2 3, а затем считывает вывод суммы. Затем он записывает вывод на стандартный вывод.

#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);
    }
}

Я делаю то, что @ugoren предложил в их ответе:

  • Создайте два канала для связи между процессами
  • Вилка
  • Замените stdin и stdout на концы каналов, используя dup
  • Отправить данные через канал
person Marek    schedule 20.02.2021