Pergunta

Eu tenho um utilitário que mostra uma lista de arquivos necessários para um jogo.Como posso executar esse utilitário dentro de um programa C e pegue a saída para que eu possa agir sobre ele dentro do mesmo programa?

ATUALIZAÇÃO:Boa chamada sobre a falta de informações.O utilitário cospe fora uma série de cadeias de caracteres, e isto é suposto ser completo portátil através de Mac/Windows/Linux.Por favor note, eu estou procurando uma forma programática para executar o utilitário e manter a sua saída (que vai para stdout).

Foi útil?

Solução

Para problemas simples em Unix-ish ambientes de tentar popen().

A partir da página de man:

O popen() função abre um processo através da criação de um pipe, bifurcar-se e invocar a shell.

Se você usar o modo de leitura é exatamente o que você pediu.Eu não sei se ele é implementado no Windows.

Para problemas mais complicados que você deseja procurar inter-processo de comunicação.

Outras dicas

Como outros já apontaram, popen() é mais a forma padrão.E uma vez que nenhuma resposta desde um exemplo usando este método, aqui vai:

#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 é suportado no Windows, veja aqui:

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

Se você quer ser multi-plataforma, popen é o caminho a percorrer.

Bem, supondo que você está em uma linha de comando em um ambiente windows, você pode usar tubos ou linha de comando redireciona.Por exemplo,

commandThatOutputs.exe > someFileToStoreResults.txt

ou

commandThatOutputs.exe | yourProgramToProcessInput.exe

Dentro de seu programa, você pode usar o padrão de C funções de entrada para ler os outros programas de saída (scanf, etc.): http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp .Você também pode usar o arquivo de exemplo e usar fscanf.Isso também deve funcionar no Linux/Unix.

Esta é uma pergunta muito genérica, você pode querer incluir mais detalhes como o tipo de saída é (apenas texto, ou um arquivo binário?) e como você deseja processar.

Editar:Hooray esclarecimento!

Redirecionando STDOUT parece ser problemático, tive de fazê-lo em .NET, e ele me deu todos os tipos de dores de cabeça.Parece que o bom C forma é gerar um processo filho, obter um ponteiro de arquivo, e, de repente, minha cabeça dói.

Então aqui está um hack que utiliza arquivos temporários.É simples, mas deve funcionar.Isso vai funcionar bem se a velocidade não é um problema (bater o disco é lento), ou se é de jogar fora.Se você estiver criando um programa enterprise, olhando para o STDOUT o redirecionamento é provavelmente o melhor, usando o que as outras pessoas recomendada.

#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.
}

Certifique-se de verificar suas permissões de arquivo:agora isso vai simplesmente jogar o arquivo no mesmo diretório como um exe.Você pode querer olhar para usar /tmp na nix, ou C:\Users\username\Local Settings\Temp no Vista, ou C:\Documents and Settings\username\Local Settings\Temp in 2K/XP.Eu acho que o /tmp irá trabalhar no OSX, mas eu nunca usei um.

No Linux e mac OS X, popen() realmente é a sua melhor aposta, como dmckee apontado, uma vez que ambos os sistemas operacionais, suporte a essa chamada.No Windows, o que deve ajudar: http://msdn.microsoft.com/en-us/library/ms682499.aspx

Documentação do MSDN diz Se usado em um programa do Windows, o _popen função retorna um erro de ponteiro de arquivo que faz com que o programa parar de responder indefinidamente._popen funciona corretamente em um aplicativo de console.Para criar um aplicativo do Windows que redireciona a entrada e saída, consulte Criar um Processo Filho com Redirecionado de Entrada e Saída no SDK do Windows.

Você pode usar system() como em:

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

onde ls é o nome do comando para listar o conteúdo da pasta música e song é uma pasta no diretório atual.Arquivo resultante song.txt será criado no diretório atual.

//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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top