Comment puis-je exécuter un programme externe à partir de C et analyser sa sortie ?

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

  •  09-06-2019
  •  | 
  •  

Question

J'ai un utilitaire qui affiche une liste de fichiers requis par un jeu.Comment puis-je exécuter cet utilitaire dans un programme C et récupérer sa sortie afin de pouvoir agir dessus dans le même programme ?

MISE À JOUR:Bon appel au manque d'informations.L'utilitaire crache une série de chaînes, et celle-ci est censée être entièrement portable sur Mac/Windows/Linux.Veuillez noter que je recherche un moyen programmatique d'exécuter l'utilitaire et de conserver sa sortie (qui va vers la sortie standard).

Était-ce utile?

La solution

Pour des problèmes simples dans les environnements Unix, essayez popen().

Depuis la page de manuel :

La fonction popen() ouvre un processus en créant un tube, en forçant et en appelant le shell.

Si vous utilisez le mode lecture, c'est exactement ce que vous avez demandé.Je ne sais pas s'il est implémenté sous Windows.

Pour des problèmes plus complexes, vous souhaitez rechercher la communication inter-processus.

Autres conseils

Comme d'autres l'ont souligné, popen() est la manière la plus standard.Et comme aucune réponse n'a fourni d'exemple utilisant cette méthode, le voici :

#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 est pris en charge sous Windows, voir ici :

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

Si vous voulez que ce soit multiplateforme, popen est la voie à suivre.

Eh bien, en supposant que vous êtes sur une ligne de commande dans un environnement Windows, vous pouvez utiliser des canaux ou des redirections de ligne de commande.Par exemple,

commandThatOutputs.exe > someFileToStoreResults.txt

ou

commandThatOutputs.exe | yourProgramToProcessInput.exe

Dans votre programme, vous pouvez utiliser les fonctions d'entrée standard C pour lire la sortie des autres programmes (scanf, etc.) : http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp .Vous pouvez également utiliser l'exemple de fichier et utiliser fscanf.Cela devrait également fonctionner sous Unix/Linux.

Il s'agit d'une question très générique, vous souhaiterez peut-être inclure plus de détails, comme de quel type de sortie il s'agit (juste du texte ou un fichier binaire ?) et comment vous souhaitez le traiter.

Modifier:Hourra clarification!

La redirection de STDOUT semble problématique, j'ai dû le faire en .NET et cela m'a donné toutes sortes de maux de tête.Il semble que la bonne méthode C soit de générer un processus enfant, d'obtenir un pointeur de fichier, et tout d'un coup, j'ai mal à la tête.

Voici donc un hack qui utilise des fichiers temporaires.C'est simple, mais ça devrait fonctionner.Cela fonctionnera bien si la vitesse n'est pas un problème (l'accès au disque est lent) ou s'il est jetable.Si vous créez un programme d'entreprise, il est probablement préférable d'examiner la redirection STDOUT, en utilisant ce que d'autres personnes ont recommandé.

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

Assurez-vous de vérifier les autorisations de vos fichiers :pour le moment, cela va simplement jeter le fichier dans le même répertoire qu'un exe.Vous voudrez peut-être envisager d'utiliser /tmp en rien, ou C:\Users\username\Local Settings\Temp sous Vista, ou C:\Documents and Settings\username\Local Settings\Temp in 2K/XP.Je pense que le /tmp fonctionnera sous OSX, mais je n'en ai jamais utilisé.

Sous Linux et OS X, popen() est vraiment votre meilleur pari, comme l'a souligné dmckee, puisque les deux systèmes d'exploitation prennent en charge cet appel.Sous Windows, cela devrait aider : http://msdn.microsoft.com/en-us/library/ms682499.aspx

La documentation MSDN indique que si elle est utilisée dans un programme Windows, la fonction _popen renvoie un pointeur de fichiers non valide qui entraîne une réponse indéfiniment au programme._popen fonctionne correctement dans une application console.Pour créer une application Windows qui redirige les entrées et les sorties, consultez Création d'un processus enfant avec des entrées et des sorties redirigées dans le SDK Windows.

Vous pouvez utiliser system() un péché:

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

ls est le nom de la commande permettant de lister le contenu du dossier chanson et song est un dossier dans le répertoire courant.Fichier résultant song.txt sera créé dans le répertoire courant.

//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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top