How can I run an external program from C and parse its output?

后端 未结 8 971
死守一世寂寞
死守一世寂寞 2020-11-22 04:18

I\'ve got a utility that outputs a list of files required by a game. How can I run that utility within a C program and grab its output so I can act on it within the same pr

相关标签:
8条回答
  • 2020-11-22 04:21

    For simple problems in Unix-ish environments try popen().

    From the man page:

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

    If you use the read mode this is exactly what you asked for. I don't know if it is implemented in Windows.

    For more complicated problems you want to look up inter-process communication.

    0 讨论(0)
  • 2020-11-22 04:27

    popen is supported on Windows, see here:

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

    If you want it to be cross-platform, popen is the way to go.

    0 讨论(0)
  • 2020-11-22 04:30

    Well, assuming you're on a command line in a windows environment, you can use pipes or command line redirects. For instance,

    commandThatOutputs.exe > someFileToStoreResults.txt
    

    or

    commandThatOutputs.exe | yourProgramToProcessInput.exe
    

    Within your program, you could use the C standard input functions to read the other programs output (scanf, etc.): http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp . You could also use the file example and use fscanf. This should also work in Unix/Linux.

    This is a very generic question, you may want to include more details, like what type of output it is (just text, or a binary file?) and how you want to process it.

    Edit: Hooray clarification!

    Redirecting STDOUT looks to be troublesome, I've had to do it in .NET, and it gave me all sorts of headaches. It looks like the proper C way is to spawn a child process, get a file pointer, and all of a sudden my head hurts.

    So heres a hack that uses temporary files. It's simple, but it should work. This will work well if speed isn't an issue (hitting the disk is slow), or if it's throw-away. If you're building an enterprise program, looking into the STDOUT redirection is probably best, using what other people recommended.

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

    Make sure to check your file permissions: right now this will simply throw the file in the same directory as an exe. You might want to look into using /tmp in nix, or C:\Users\username\Local Settings\Temp in Vista, or C:\Documents and Settings\username\Local Settings\Temp in 2K/XP. I think the /tmp will work in OSX, but I've never used one.

    0 讨论(0)
  • 2020-11-22 04:34

    As others have pointed out, popen() is the most standard way. And since no answer provided an example using this method, here it goes:

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

    Sample output:

    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
    
    0 讨论(0)
  • 2020-11-22 04:39

    In Linux and OS X, popen() really is your best bet, as dmckee pointed out, since both OSs support that call. In Windows, this should help: http://msdn.microsoft.com/en-us/library/ms682499.aspx

    0 讨论(0)
  • 2020-11-22 04:40

    MSDN documentation says If used in a Windows program, the _popen function returns an invalid file pointer that causes the program to stop responding indefinitely. _popen works properly in a console application. To create a Windows application that redirects input and output, see Creating a Child Process with Redirected Input and Output in the Windows SDK.

    0 讨论(0)
提交回复
热议问题