2016-12-01 10 views
0

私は標準入力と出力で別のプログラムと通信する必要のあるプログラムを用意しています。パイプを使用して入力を送信し、指定されたファイルにその出力をリダイレクトして完了したら読み込み、正常に動作します。私は私のプログラムが少なくともWindowsとLinuxでいくらか働くようにしたいのでパイプとdup2を使用していません。popenが期待どおりに動作しない

私の問題は、データをストリームするためにパイプを使いたいということです。

私は、次のコードを試みた:私は何をすべきかに関係なく、私はちょうどファイルのうち、ヌルを得続けるしかし

#include <unistd.h> 
#include <stdio.h> 

int main() 
{ 
     int x; 
    FILE *p = popen("./test > tmp.datafile", "w"); 
    FILE *f = fopen("tmp.datafile", "r"); 

    for (int i = 0; i < 100; ++i) { 
     fprintf(p, "%d", i); 

     sleep(1); 
     x = fgetc(f); 
     printf("%c ", x); 
     fflush(0); 
    } 

    fclose(f); 
    pclose(p); 

    return 0; 
} 

:と一緒に

#include <stdio.h> 

int main() 
{ 
    while (!feof(stdin)) { 
     int x; 
     scanf("%d", &x); 
     printf("%x ", x); 
     fflush(0); 
    } 

    return 0; 
} 

を。テスト実行ファイルがフラッシュされる前にファイルを読み込もうとすると同時実行性の問題があると思われますが、これを修正する方法がわかりません。

cで標準ストリーム経由でプログラムと通信する方がいいですか?

+0

実は、あなたには、いくつかの[イベントループ]で[投票を(2)](http://man7.org/linux/man-pages/man2/poll.2.html)を使用する必要があります(HTTPS:/ /en.wikipedia.org/wiki/Event_loop)。 http://advancedlinuxprogramming.com/と[this](http://stackoverflow.com/a/20582916/841108)の回答をお読みください。 –

+0

私はファイルをポーリングすることは考えていませんでした。どのように似たようなWindowsのポーリングがLinuxにあるのか知っていますか?私は窓のpopenはほぼ同じですが、確かに投票についてはわかりません。 – LambdaBeta

+0

Windowsはまったくわかりませんが、[POCO](http://pocoproject.org/)や[Qt](http://qt.io/)や[GLIB](https:// developer.gnome.org/glib/stable/)(あるいは[libevent](http://libevent.org/)....)は、クロスプラットフォームであり、助けてください。 [名前付きパイプ](https://en.wikipedia。org/wiki/Named_pipe) –

答えて

3

fgetc()は、EOFに達した後は読み取りを行いません。これは、最初の読み取りで発生する可能性があります。

if(feof(f)) { 
    clearerr(f); 
    sleep(1); 
} else { 
    printf("%c ", x); 
} 

のようにすると、ビジーループで問題が解決されるはずです。

EOFに達した後にファイルが変更されるのを待つのが良いアイデアですが、システム固有の呼び出しが必要です。

他の競合状態に注意してください:popenを介して開始されたコマンドによってファイルが作成される前にfopenが発生することがあります。

while(!(f = fopen(..., "r")) 
    sleep(1); 

dup2()が使用できない場合にのみ使用する必要がある別のビジーループと全体的に良い解決策ではありません。

+0

十分に公正で、私は過去の最後を読んでいたという事実については考えていませんでした。私は今のところLinuxをサポートするつもりだと思って、後で '#ifdef'を追加してウィンドウをサポートしようとしています。これはfork、dup2、execlpの方がはるかに簡単です。 – LambdaBeta

0

コードの問題の1つは、./testのコールが入力を完了して値を読み取るのを待っているため、pの入力に空白を書き込んでいないことです。そのためstdout./testは空のままです。これを次のように修正してください。

fprintf(p, "%d\n", i); 

また、./testプログラム内でバッファされていない入出力機能を使用することを検討してください。 printfはバッファされたI/Oファミリの機能の一部であり、出力がファイルにすぐに書き込まれないことがあります。

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 

int main() 
{ 
    while (!feof(stdin)) { 
     int x; 
     char s; 
     scanf("%d", &x); 
     sprintf(&s, "%x", x); 
     write(STDOUT_FILENO, &s, 1); 
     fflush(stdout); 
    } 

    return 0; 
} 
関連する問題