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

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

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

см. также stackoverflow.com/questions/125828/…

rogerdpack 26.09.2012 02:30

Если вам нужен stderr, вы также можете перенаправить, например, call is nonexistent-name 2> & 1

Vic 10.04.2013 07:11

Это не дубликат; связанный вопрос - Специфичный для C++, а этот вопрос - о C.

Kyle Strand 23.03.2016 01:21

Я голосую за то, чтобы снова открыть этот вопрос, поскольку это не дубликат, он касается C, а не C++

hassan 20.06.2017 12:51

см. также stackoverflow.com/questions/9405985/…

Ammo Goettsch 03.09.2017 18:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
71
5
72 174
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Ответ принят как подходящий

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

На странице руководства:

The popen() function opens a process by creating a pipe, forking and invoking the shell.

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

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

Было бы неплохо привести несколько примеров того, как правильно использовать popen().

Alexej Magura 29.07.2013 23:29

Я добавил ссылку на страницу руководства Open Group для функции, которая включает пример. По сути, popen дает вам указатель на файл, очень похожий на fopen. Просто он позволяет вам писать в стандартный ввод или читать из стандартного вывода программы вместо взаимодействия с файлом на диске. Это философия UNIX "все - файл" в действии. Некоторые реализации расширяют стандарт, разрешая двунаправленную связь.

dmckee --- ex-moderator kitten 30.07.2013 05:09
Это ответ indicates that popen is available on Windows.
Jonathon Reinhart 25.06.2015 22:17

Для решения, использующего дескрипторы необработанных файлов (например, если вам нужен асинхронный ввод-вывод), см. stackoverflow.com/questions/9405985/…

Ammo Goettsch 03.09.2017 18:36

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

c должен быть int, потому что fgetc возвращает int, а не char.

Spikatrix 31.03.2016 12:03

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

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

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

Если вы хотите, чтобы он был кроссплатформенным, используйте popen.

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

//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;
}

На каком это языке? Конечно, не C (string.resize?)

ugoren 30.07.2013 11:51

похоже на C++ :(

gideon 26.09.2016 15:53

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

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

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

что, если я хочу перенаправить вывод других программ в файл? не команда ОС

Amine Da. 17.04.2016 04:30

Нет, это очень плохой способ. Делайте это правильно, используя каналы, не оставляя временные файлы по всей файловой системе.

Owl 05.10.2018 17:55

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

Разве if (pclose(fp)) не должен быть if (pclose(fp) == -1)?

Spikatrix 31.03.2016 12:03

@CoolGuy: зависит от того, что вы хотите. pclose() возвращает -1, если произошла ошибка при получении статуса выхода команды, в противном случае он возвращает сам статус выхода. Поскольку команды традиционно устанавливают статус выхода 0 для индикации успеха, проверяя if (pclose(fp)), мы проверяем наличие ошибок либо в pclose(), либо в команде.

MestreLion 01.04.2016 01:48

Большое спасибо за этот пример, он передает вывод другой программы на вывод текущей программы. Спасибо!

Joe 30.03.2019 03:20

Другие вопросы по теме