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

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

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

8 ответов

Решение

Для простых проблем в среде Unix-ish попробуйте popen(),

Со страницы руководства:

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

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

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

Как уже отмечали другие, 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;
}

popen поддерживается в Windows, смотрите здесь:

http://msdn.microsoft.com/en-us/library/96ayss4b.aspx

Если вы хотите, чтобы он был кроссплатформенным, Popen - это путь.

Хорошо, если вы находитесь в командной строке в среде 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's 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 в никс, или C:\Users\username\Local Settings\Temp в Vista или C:\Documents and Settings\username\Local Settings\Temp in 2K/XP, я думаю /tmp будет работать в OSX, но я никогда не использовал его.

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

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

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

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

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

//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;
}
Другие вопросы по тегам