C から外部プログラムを実行し、その出力を解析するにはどうすればよいですか?
-
09-06-2019 - |
質問
ゲームに必要なファイルのリストを出力するユーティリティを持っています。C プログラム内でそのユーティリティを実行し、その出力を取得して、同じプログラム内で操作できるようにするにはどうすればよいですか?
アップデート:情報不足については良い判断です。このユーティリティは一連の文字列を吐き出します。これは Mac/Windows/Linux 間で完全に移植可能であると考えられています。ユーティリティを実行し、その出力 (stdout に出力される) を保持するプログラム的な方法を探していることに注意してください。
解決
Unix っぽい環境での単純な問題については、次のことを試してください。 popen()
.
マニュアルページから:
Popen() 関数は、パイプを作成し、フォークしてシェルを呼び出してプロセスを開きます。
読み取りモードを使用する場合、これはまさにあなたが求めていたものです。Windows に実装されているかどうかはわかりません。
より複雑な問題については、プロセス間通信を調べる必要があります。
他のヒント
他の人も指摘しているように、 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;
}
Popen は Windows でサポートされています。ここを参照してください。
http://msdn.microsoft.com/en-us/library/96ayss4b.aspx
クロスプラットフォームにしたい場合は、popen が最適です。
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
ニックスで、または C:\Users\username\Local Settings\Temp
Vista の場合、または C:\Documents and Settings\username\Local Settings\Temp in 2K/XP
. 。私は思います /tmp
OSXでも動作しますが、私は使ったことはありません。
Linux と OS X では、 popen()
dmckee が指摘したように、両方の OS がその呼び出しをサポートしているため、実際にはこれが最善の策です。Windows では、これは次の点に役立ちます。 http://msdn.microsoft.com/en-us/library/ms682499.aspx
MSDNドキュメントによると、Windowsプログラムで使用された場合、_Popen関数は無効なファイルポインターを返し、プログラムが無期限に応答するのを停止します。_popen はコンソール アプリケーションで適切に動作します。入力と出力をリダイレクトする Windows アプリケーションを作成するには、「Windows SDK でリダイレクトされた入力と出力を持つ子プロセスを作成する」を参照してください。
使用できます system()
次のように:
system("ls song > song.txt");
どこ ls
フォルダーソングの内容を一覧表示するコマンド名です。 song
は現在のディレクトリ内のフォルダーです。結果のファイル song.txt
カレントディレクトリに作成されます。
//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;
}