Come posso eseguire un programma esterno da C e analizzarne l'output?
-
09-06-2019 - |
Domanda
Ho un'utilità che genera un elenco di file richiesti da un gioco.Come posso eseguire quell'utilità all'interno di un programma C e catturarne l'output in modo da poter agire su di esso all'interno dello stesso programma?
AGGIORNAMENTO:Buona chiamata sulla mancanza di informazioni.L'utilità genera una serie di stringhe e dovrebbe essere completamente portabile su Mac/Windows/Linux.Tieni presente che sto cercando un modo programmatico per eseguire l'utilità e conservarne l'output (che va su stdout).
Soluzione
Per problemi semplici in ambienti Unix, prova popen()
.
Dalla pagina man:
La funzione popen() apre un processo creando una pipe, biforcandosi e invocando la shell.
Se usi la modalità di lettura questo è esattamente quello che hai chiesto.Non so se è implementato in Windows.
Per problemi più complicati è necessario cercare la comunicazione tra processi.
Altri suggerimenti
Come altri hanno sottolineato, popen()
è il modo più standard.E poiché nessuna risposta ha fornito un esempio utilizzando questo metodo, eccolo qui:
#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 è supportato su Windows, vedere qui:
http://msdn.microsoft.com/en-us/library/96ayss4b.aspx
Se vuoi che sia multipiattaforma, popen è la strada da percorrere.
Bene, supponendo che tu sia su una riga di comando in un ambiente Windows, puoi utilizzare pipe o reindirizzamenti della riga di comando.Ad esempio,
commandThatOutputs.exe > someFileToStoreResults.txt
O
commandThatOutputs.exe | yourProgramToProcessInput.exe
All'interno del tuo programma, potresti utilizzare le funzioni di input standard del C per leggere l'output degli altri programmi (scanf, ecc.): http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp .Potresti anche usare il file example e usare fscanf.Questo dovrebbe funzionare anche in Unix/Linux.
Questa è una domanda molto generica, potresti voler includere maggiori dettagli, ad esempio che tipo di output è (solo testo o un file binario?) e come vuoi elaborarlo.
Modificare:Evviva chiarimenti!
Reindirizzare STDOUT sembra essere problematico, ho dovuto farlo in .NET e mi ha dato ogni sorta di mal di testa.Sembra che il modo C corretto sia generare un processo figlio, ottenere un puntatore a un file e all'improvviso mi fa male la testa.
Quindi ecco un trucco che utilizza file temporanei.È semplice, ma dovrebbe funzionare.Funzionerà bene se la velocità non è un problema (l'accesso al disco è lento) o se è da buttare via.Se stai creando un programma aziendale, probabilmente è meglio esaminare il reindirizzamento STDOUT, utilizzando ciò che altre persone hanno consigliato.
#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.
}
Assicurati di controllare i permessi dei file:in questo momento questo semplicemente getterà il file nella stessa directory di un exe.Potresti voler esaminare l'utilizzo /tmp
in nix, o C:\Users\username\Local Settings\Temp
in Vista, o C:\Documents and Settings\username\Local Settings\Temp in 2K/XP
.Penso che la /tmp
funzionerà in OSX, ma non ne ho mai usato uno.
In Linux e OS X, popen()
è davvero la soluzione migliore, come ha sottolineato dmckee, poiché entrambi i sistemi operativi supportano quella chiamata.In Windows, questo dovrebbe aiutare: http://msdn.microsoft.com/en-us/library/ms682499.aspx
La documentazione di MSDN afferma che se utilizzata in un programma Windows, la funzione _Popen restituisce un puntatore di file non valido che fa sì che il programma interrompa la risposta indefinitamente._popen funziona correttamente in un'applicazione console.Per creare un'applicazione Windows che reindirizza input e output, vedere Creazione di un processo figlio con input e output reindirizzati in Windows SDK.
Puoi usare system()
come in:
system("ls song > song.txt");
Dove ls
è il nome del comando per elencare il contenuto della cartella song e song
è una cartella nella directory corrente.File risultante song.txt
verrà creato nella directory corrente.
//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;
}