• 締切済み

パイプってどうやって使うの?

1つ目のプログラムの出力を2つ目のプログラムで受け取りたいのですが、どうすればいいですか? -- 1 -- #include <stdio.h> #include <windows.h> int main(void){     int a=0;     while(1){         fprintf(stdout,"%d\n",a++);         Sleep(1000);     }     return 0; } これを2のプログラムで受け取ります。 #include <stdio.h> int main(void){     char str[128];     while(1){         if(fgets(str,sizeof(str),stdin)==NULL)             break;     printf("%s",str);     }     return 0; } これをコマンドプロンプトで 1 | 2 と入力してみましたが、何も表示されません・・。 個別に実行すると正常に動作します。 環境はXPです。どうしたら受け渡しが出来るのでしょうか?

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.7

ところで, 2 の方が「入力に依存せずに終了する」(例えば while ループじゃなくて「1回読み込んだから終了」) 場合に, コマンドプロンプトまで戻らないような感じもするんだけど気のせいかなぁ? UNIX なら SIGPIPE で止まるところが止まっていない感じ. Vista でそんな風になったんだけど, 何か間違えたのかなぁ....

noname#208124
noname#208124
回答No.6

XPのcommand.comとcmd.exeでもそんな実装にはなっていないことを補足させてもらいます setvbufかfflushだけで問題有りません >コマンドプロンプトで1|2とやってパイプラインを動かしたままにして、タスクマネージャーで「実行中のアプリケーション」や「実行中のタスク」を見てみましょう。 2.exeが存在することを実際に確認しました >「本当に2が起動されないままなのか確かめたい」のなら「2の先頭に、無条件に何かを表示するprintfを入れてみる」と良いでしょう。 1.exeがループ中に2.exeから出力されることを実際に確認しました

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

蛇足: #4 では「command.com ではそのようにパイプを実装してる」と書いたものの, 試してみたら (少なくとも) Vista では command.com でもまともなパイプの動作をしてるよ.... ということで, その部分は無視してほしい.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

XP では試してないけど Vista なら #1 でちゃんと動く. 少なくとも Vista では実際に試した結果だから間違いない. 確かに command.com ではそのようにパイプを実装してるけど>#2, MS-DOS や 16ビットの Windows ならいざ知らずカーネルオブジェクトとしてパイプが存在する 32ビット Windows で (しかも 32ビット Windows のコマンドシェルである cmd.exe で) そんなしょぼい実装をするかねぇ. いくら Microsoft といえど.

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

少なくとも「コマンドプロンプト」が動くようなwindowsであれば、 まともなパイプが使えるようになってます。 たとえば、unixにあるようなyesコマンドとheadコマンドを組み合わせて yes|head としてもちゃんと終了します。 ですので、#1のTacosanさんの見るように バッファにたまってるだけの話だと思います。

  • chie65535
  • ベストアンサー率43% (8514/19356)
回答No.2

>これをコマンドプロンプトで >1 | 2 >と入力してみましたが、何も表示されません・・。 そりゃそうです。 Windowsのコマンドプロンプトでは「1」が正常終了しない限り「2」は実行されません。 言い換えれば「2が実行されるのは、1が正常終了したときだけ」です。 コマンドプロンプトで 1|2 とやってパイプラインを動かしたままにして、タスクマネージャーで「実行中のアプリケーション」や「実行中のタスク」を見てみましょう。 アプリケーションやタスクには「1.exe」はありますが「2.exe」は無い筈です。 ご質問のパターンでは「1は強制終了して止めるしかない」ので 1|2 のパイプラインを実行した場合「2が起動される事は永遠に無い」です。 パイプラインを実行する環境がUNIXやLinuxなどのシェル(shやcsh)であれば、シェルがマルチプロセス起動に対応しているので 1|2 とパイプで繋ぐと1と2は同時に起動され、1の中から呼ぶSleepやシステムコールにより2に制御が移り、1と2が交互に動作し、正しく表示されます。 しかし、Windowsのコマンドプロンプトでは「1」が正常終了しない限り「2」は実行されませんので 1|2 とパイプで繋ぐと1だけ起動し、永久ループします。 1を止めるには、コマンドプロンプトウィンドゥの右上隅の[×]ボタンで「コマンドプロンプトウィンドゥごと強制終了する」しかありません。 なお「MS-DOS」や「Windowsのコマンドプロンプト」では 1|2 と実行するのは 1 > tempfile.$$$ 2 < tempfile.$$$ del tempfile.$$$ と書かれたバッチファイルを動かすのと同等です。 このバッチファイルは 1 > tempfile.$$$ が終了しない限り 2 < tempfile.$$$ の行は実行しません。 これからも判る通り「Windowsのコマンドプロンプトでは、パイプコマンドの中に無限ループして終了しないプログラムがあると、それより右に書いたプログラムは起動されない」です。 「2が起動される事はない」のですから、1の中でsetbuf(stdout, NULL);してバッファリグしないようにしたりfprintfのあとでfflush(stdout);をしようが、すべては無駄です。徒労に終ります。 「本当に2が起動されないままなのか確かめたい」のなら「2の先頭に、無条件に何かを表示するprintfを入れてみる」と良いでしょう。 「無限ループして終了しないプログラムをパイプラインで繋いで、ちゃんと表示させたい」のなら「Windowsでは不可能」なので、今すぐCドライブをフォーマットしてWindowsを全部消し、FreeBSDなど、Unix系のOSを導入しましょう。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

手元で実験してみたけど, 1 の方で書きだすときにバッファリングしてるため, 十分なデータがたまらないと 2 で読み込めなくなってる. だから Sleep しなければちゃんと出力されるし, Sleep しても最初に setbuf(stdout, NULL); でバッファリグしないようにしたり fprintf のあとで fflush(stdout); によりフラッシュすればちゃんと出力できる.

関連するQ&A

  • enterでループ終了

    #include <stdio.h> int main(void) { char str[255]; int i, len; while (1){ printf("文字列を入力してください:"); if (fgets(str, sizeof(str), stdin) == NULL) { break; } len = strlen(str); if (len > 0 && str[len - 1] == '\n') str[len - 1] = '\0'; if (str[0] == '\0') break; enterで終了するプログラムの例ですが、 if (fgets(str, sizeof(str), stdin) == NULL) のNULLはどういった理由で必要ですか? また、 if (len > 0 && str[len - 1] == '\n') str[len - 1] = '\0'; を消して、 if (str[0] == '\0') break; を、if (str[0] == '\n') break; と書き換えれば、終了すのではないですか?不適な理由がありますか?

  • stdin,stdoutについて

    C言語を学び始めたものです stdin・stdoutがどのように機能するか分かりません またstdoutはどこに出力しているんですか #include <stdio.h> int main(void) { char ch; while(!feof(stdin)) { scanf("%c", &ch); if(!feof(stdin)) printf("%c", ch); } return 0; } このプログラムは「コンソール」入出力関数だけを使用しテキストファイルの内容を別のテキストファイルにコピーするプログラムだそうですがどのテキストファイルの内容をどこのテキストファイルにコピーしているんですか?stdin・stdoutの機能が全く分かりません。 どなたか分かる方、回答お願いします。

  • トークン

    Cプログラムで、標準入力から入力された文から、アポストロフィーをだけをとって表示するプログラムを作っています。さらに、空白は無視して表示しない様にしたいんですけど、以下のようなプログラムだと #include <stdio.h> #include <string.h> int main(void){ char str1[256],str2[256][256],*bp,*cp; int i=0,h=0; putchar('>'); cp = fgets(str1, 256, stdin); while( (bp = strpbrk(cp ," \"\n")) ){ strncpy(str2[i], cp, bp-cp); str2[i][bp-cp+1] = '\0'; printf("%s\n",str2[i]); bp++; cp = bp; i++; } return 0; } >Commannd "ww" Commannd ww という風になり空白がなぜか出力してしまいます。何故でしょうか?

  • ファイル操作

    コンパイラ:VisualC++6.0 ファイル操作について質問です。 書き込みは出来ますが、書き込みの追記の仕方が分かりません。(毎回上書きされる) #include<stdio.h> int main(void){ FILE* fp; char write[100]; fgets(write,sizeof(write),stdin); fp=fopen("../test.txt","w"); if(fp==NULL){ printf("エラー"); return 0; } fprintf(fp,"%s",write); fclose(fp); return 0; } よろしくお願いします。

  • int とcharの使い方と違い

    教えてgooに投稿するのは初めてですがよろしくお願いします。 最近C言語を勉強し始めた初心者です。 ネットのサイトを見て独学でしています。 過去スレッドをさらっと見て聞きたいことが書いてなかったので投稿します。(同じスレッドがあったらすみませんOTL) #include<stdio.h> int main(void) { int str='a'; printf("str=%c\n",str); return0; } この上のプログラムでは str=a と出て、エラーが出ずにコンパイル出来ました。でも、 #include<stdio.h> int main(void) { int str[]="abc"; printf("str=%s\n",str); return0; } とするとエラーが出ます。 int とcharの使い方と違いについて詳しく教えてほしいです>< お願いします。

  • このプログラムは「こんにちは」と打つと「こんにちは、元気ですか」と返答

    このプログラムは「こんにちは」と打つと「こんにちは、元気ですか」と返答するプログラムです このプログラムを改良して「こんにちは」と打つと「こんにちは、元気ですか」と言うようなキーワードを打つ決められた回答をするようなものを増やしていきたいのですが、どのように改良すればよいでしょうか? 例えば 「寒いですね」といれると「冬だからね」となるように #include <stdio.h> #include <string.h> int reply(const char *s) { const char *reply_s[] = {"こんにちは 元気ですか?", "バイバイ", "ふ~ん?"}; if(strstr(s, "こんにちは")) puts(reply_s[0]); else if(strstr(s, "さようなら")){ puts(reply_s[1]); return 0; } else puts(reply_s[2]); return 1; } int main(void) { char s[128]; do{ char *p; fgets(s, sizeof s, stdin); if(p = strchr(s, '\n')) *p = '\0'; }while(reply(s)); return 0; }

  • 文字列の検索

    プログラミングの勉強の際に下のプログラムを作りました。 最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 コンパイルは通るのですが、文字列を2つ入力すると 「セグメンテーション違反です」と表記されます… どこが悪いのでしょうか? どなたか解説・指摘・模範解答などおねがいします。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(*c!='\0'){ c=a; d=b; while(*c!='\0' && *d!='\0') if(*c!=*d) printf("0"); break; c++; d++; } if(*d='\0') printf("1"); a++; return a; return NULL; }

  • scanfの後のfgetsについて

    #include <stdio.h> int main(void) { char name[10]; int no; printf("ナンバーを入力してください: "); scanf("%d",&no); /* 35を入力 */ printf("文字列を入力してください: "); fgets(name,10,stdin); /*入力できない*/ return 0; } この例文だと、fgets関数が改行コードを読み取って、終了してしまい文字列入力が出来ないみたいなんですが、scanfの後にfgetsを使うような(scanfとfgetsの間にscanfの残した?改行コードを取り除く方法)処理はどのような方法があるのでしょうか? 試しにfgets文を2度書いたら思っていた動作をしてくれたのですが、はたしてfgets文を2度書くというような事をしていいものなのでしょうか?見た目もなんだか変な感じですし。。↓ #include <stdio.h> int main(void) { char name[10]; int no; printf("ナンバーを入力してください: "); scanf("%d",&no); /* 35を入力 */ printf("文字列を入力してください: "); fgets(name,10,stdin); fgets(name,10,stdin);  /*入力できる*/ return 0; }

  • 分岐について

    「y」もしくは「n」が入力された時、ループから抜けるプログラムを作りたいとおもっています。 一応作ってはみたのですが、なんかスッキリとしない感じなので、 もっと簡単な方法がありましたら教えてもらえないでしょうか? #include <stdio.h> #include <string.h> int main(void) { int cnt; char judge[256]; cnt = 0; memset(&judge[0],'\0',sizeof(judge)); while(1) { printf("y or n : "); fgets(&judge[0],sizeof(judge),stdin); for(cnt = 0 ; judge[cnt] != '\0' ; cnt++) { if(judge[cnt] == '\n') { judge[cnt] = '\0'; break; } } if((judge[0] == 'y' && judge[1] == '\0') || (judge[0] == 'n' && judge[1] == '\0')) { break; } printf("\nError. Input y or n.\n"); } return 0; }

  • 入力した文字列の文字コードを16進数で出力

    入力した文字列の文字コードを16進数で出力するプログラムを作っているのですが 下のように記述してもどうしても最後にaが表示されてしまいます。 打開策、または何故aが表示されるのかを教えてください。 #include <stdio.h> main() { int str; while(1){ str=getc(stdin); if(str==EOF) break; printf("%x ",str); } return 0; }

専門家に質問してみよう