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

StackOverflow https://stackoverflow.com/questions/43116

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

Для решения простых задач в Unix-средах попробуйте 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.

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

Редактировать:Ура, разъяснение!

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

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

#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 в nix, или 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 является папкой в текущем каталоге.Результирующий файл 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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top