Как я могу запустить внешнюю программу с C и проанализировать ее вывод?

У меня есть утилита, которая выводит список файлов, необходимых для игры. Как я могу запустить эту утилиту в программе C и получить ее выход, чтобы я мог действовать на нее в рамках одной и той же программы?

ОБНОВЛЕНИЕ: Хороший призыв к отсутствию информации. Утилита выплескивает ряд строк, и это должно быть полностью переносимым в Mac/Windows/Linux. Обратите внимание: я ищу программный способ выполнения утилиты и сохранения ее вывода (который идет на стандартный вывод).

Ответ 1

Для простых задач в средах Unix-ish popen().

На странице man:

Функция popen() открывает процесс, создавая канал, разворачивая и вызывая оболочку.

Если вы используете режим чтения, это именно то, о чем вы просили. Я не знаю, реализована ли она в Windows.

Для более сложных проблем вы хотите найти взаимосвязь между процессами.

Ответ 2

Как уже отмечалось, popen() является наиболее стандартным способом. И так как ни один ответ не предоставил пример использования этого метода, вот оно:

#include <stdio.h>

#define BUFSIZE 128

int parse_output(void) {
    char *cmd = "ls -l";    

    char buf[BUFSIZE];
    FILE *fp;

    if ((fp = popen(cmd, "r")) == NULL) {
        printf("Error opening pipe!\n");
        return -1;
    }

    while (fgets(buf, BUFSIZE, fp) != NULL) {
        // Do whatever you want here...
        printf("OUTPUT: %s", buf);
    }

    if(pclose(fp))  {
        printf("Command not found or exited with error status\n");
        return -1;
    }

    return 0;
}

Пример вывода:

OUTPUT: total 16
OUTPUT: -rwxr-xr-x 1 14077 14077 8832 Oct 19 04:32 a.out
OUTPUT: -rw-r--r-- 1 14077 14077 1549 Oct 19 04:32 main.c

Ответ 4

Ну, предположим, что вы находитесь в командной строке в среде Windows, вы можете использовать перенаправления каналов или командной строки. Например,

commandThatOutputs.exe > someFileToStoreResults.txt

или

commandThatOutputs.exe | yourProgramToProcessInput.exe

В вашей программе вы можете использовать стандартные функции ввода C для чтения других выходных программ (scanf и т.д.): http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp, Вы также можете использовать пример файла и использовать fscanf. Это также должно работать в Unix/Linux.

Это очень общий вопрос, вы можете включить более подробную информацию, например, какой тип вывода (просто текст или двоичный файл?) и как вы хотите его обрабатывать.

Изменить: разъяснение ура!

Перенаправление STDOUT выглядит бесполезным, мне приходилось делать это в .NET, и это давало мне всевозможные головные боли. Похоже, что правильный способ C - порождать дочерний процесс, получить указатель на файл, и внезапно у меня болит голова.

Таким образом, есть взлома, в котором используются временные файлы. Это просто, но это должно сработать. Это будет хорошо работать, если скорость не является проблемой (удар по диску медленный), или если он выбрасывается. Если вы строите корпоративную программу, просмотр перенаправления STDOUT, вероятно, лучше всего, используя то, что рекомендовали другие люди.

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

int main(int argc, char* argv[])
{
    FILE * fptr;                    // file holder
    char c;                         // char buffer


    system("dir >> temp.txt");      // call dir and put it contents in a temp using redirects.
    fptr = fopen("temp.txt", "r");  // open said file for reading.
                                    // oh, and check for fptr being NULL.
    while(1){
        c = fgetc(fptr);
        if(c!= EOF)
            printf("%c", c);        // do what you need to.
        else
            break;                  // exit when you hit the end of the file.
    }
    fclose(fptr);                   // don't call this is fptr is NULL.  
    remove("temp.txt");             // clean up

    getchar();                      // stop so I can see if it worked.
}

Обязательно проверьте права доступа к файлам: прямо сейчас это просто выкинет файл в том же каталоге, что и exe. Возможно, вы захотите изучить /tmp в nix или C:\Users\username\Local Settings\Temp в Vista или C:\Documents and Settings\username\Local Settings\Temp in 2K/XP. Я думаю, что /tmp будет работать в OSX, но я никогда не использовал его.

Ответ 5

В Linux и OS X popen() на самом деле это ваш лучший выбор, как отметил dmckee, поскольку обе ОС поддерживают этот вызов. В Windows это должно помочь: http://msdn.microsoft.com/en-us/library/ms682499.aspx

Ответ 6

Документация MSDN Если используется в программе Windows, функция _popen возвращает недопустимый указатель файла, который заставляет программу перестать отвечать на неопределенное время. _popen работает правильно в консольном приложении. Чтобы создать приложение Windows, которое перенаправляет ввод и вывод, см. "Создание дочернего процесса с перенаправленными входами и выходами в SDK Windows".

Ответ 7

Вы можете использовать system() как в:

system("ls song > song.txt");

где ls - это имя команды для перечисления содержимого песни в папке, а song - это папка в текущем каталоге. Результирующий файл song.txt будет создан в текущем каталоге.

Ответ 8

//execute external process and read exactly binary or text output
//can read image from Zip file for example
string run(const char* cmd){
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[262144];
    string data;
    string result;
    int dist=0;
    int size;
    //TIME_START
    while(!feof(pipe)) {
        size=(int)fread(buffer,1,262144, pipe); //cout<<buffer<<" size="<<size<<endl;
        data.resize(data.size()+size);
        memcpy(&data[dist],buffer,size);
        dist+=size;
    }
    //TIME_PRINT_
    pclose(pipe);
    return data;
}