2011-12-25 6 views
2

私は何度も何度もこの割り当てをやっています。これは10回目のバージョンです。問題は、1つのメッセージだけがパイプを通過し、正しい結果が計算されることです。次の文字列はまったく渡されません。またはバッファを使っていくつかの文字だけを操作した後に渡します。助けてください、私は本当にこれで多くの時間を失ってしまったので、私はすぐにテストのためにこのものを学ぶ必要があります。パイプを通るメッセージは1つだけです

#include <ctype.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <string.h> 
#include <stdio_ext.h> 

/* Prototypes */ 

void usage(void); 
void calchild(void); 

char command[] = "<not yet set>"; 

int main(int argc, char **argv) 
{ 
    char input1[512]; 
    char input2[512]; 
    char tmp[512]; 
    char *endptr; 
    char c = 0; 
    int a, b, result; 
    pid_t cpid; 
    int status = 0; 
    int stocpipe[2]; /* Server to client pipe. [0] -read; [1]- write*/ 
    int ctospipe[2]; /* Client to server pipe.  - || -   */ 
    int i = 0; 
    FILE *send, *receive; 

    if(argc > 1) 
    { 
     usage(); 
    } 

    /* Pipe Setup */ 
    if(pipe(stocpipe) != 0 || pipe(ctospipe) != 0) 
    { 
     fprintf(stderr, "ERROR: Can't create unnamed pipe! \n"); 
     exit(EXIT_FAILURE); 
    } 

    switch(cpid = fork()) 
    { 
    case -1: 
     fprintf(stderr, "ERROR: Can't fork! \n"); 
     exit(EXIT_FAILURE); 
     break; 
    case 0: 
     /* calchild */ 
     close(stocpipe[1]); 
     close(ctospipe[0]); 

     receive = fdopen(stocpipe[0], "r"); 
     send = fdopen(ctospipe[1], "w"); 

/*Gets the string from the parent process and does the computation.*/ 
     while(fgets(input2, 17, receive) != NULL) 
     { 
     strcpy(tmp, input2); 
     fprintf(stdout, "After receive: %s", tmp); 
     a = strtol(tmp, &endptr, 10); 
     fprintf(stdout, "a = %d\n", a); 
     b = strtol(endptr, &endptr, 10); 
     fprintf(stdout, "b = %d\n", b); 
     c = endptr[0]; 

/*Loops until it finds a non-space char*/ 
     for(i = 0; isspace(c = endptr[i]); i++); 

     switch(c) 
    { 
    case '+': 
     /*add*/ 
     result = a + b; 
     break; 
    case '-': 
     /*subtract*/ 
     result = a - b; 
     break; 
    case '*': 
     /*multiply*/ 
     result = a * b; 
     break; 
    case '/': 
     /*divide*/ 
     result = a/b; 
     break; 
    default: 
     fprintf(stderr, "the funk!? %c\n", c); 
     break; 
    } 

     fprintf(stderr, "%d\n", result); 
     fprintf(send, "%d", result); 

    } 
     break; 
    default: 

    close(stocpipe[0]); 
    close(ctospipe[1]); 

    send = fdopen(stocpipe[1], "w"); 
    receive = fdopen(ctospipe[0], "r"); 

/*Reads string from stdin and sends it to the child process through a pipe. */ 
    while(fgets(input1, 17, stdin) != NULL) 
    { 
     fprintf(stdout, "Before send: %s", input1); 
     fwrite(input1, 17, 1, send); 

if(fflush(send) == EOF) 
    { 
     fprintf(stderr, "Flush error!"); 
    } 
} 

    (void) waitpid(cpid, &status, 0); 
    if(status != 0) 
    { 
     fprintf(stderr, "ERROR: Child calculator exited with %d \n", status); 
    } 
     break; 
    } 


    return 0; 
} 

void usage(void) 
{ 
    fprintf(stderr,"Usage: %s", command); 
    exit(EXIT_FAILURE); 
} 

プログラムは電卓です。その目的はIPCを学ぶことです。親プロセスはstdinからの文字列を受け取り(例えば3 5 +)、それを子に送る。子は文字列を解析し、結果を計算します。そして、結果を親プロセスに送り返し、それをstdoutに出力します。

私は子供に文字列を送信する部分に立ち往生しました。最初に受け入れられた文字列が子に送信されます。そして、それは良い結果を計算します。 2番目の文字列とそれ以降は空であるか、少なくとも空であるようです。

+0

ネストされた 'switch/while/swicth'とボディーレス' for'はありますか?きちんとした本当に、本当に読みにくいです。親と子の処理のための関数を作って、あなたのコードをちょっと入れ子にしてみてください。 (正確にインデントしてください) – Mat

+2

私はプログラムを理解しやすくする必要があると思います。最初に、同じ悪い行動を示すカットダウンの最小限のプログラムを使うようにしてください。プログラムが何をすべきかについても説明してください。 –

+0

私はボディーレスのコメントを追加しました。 :D私はすでに独立した実行ファイルを別々の関数で実行しましたが、今度はそれらがスイッチで分離されています。また、私はそれが何をしているのかを記述し、送受信が行われる箇所(問題が発生する部分)についてコメントします。問題は私が間違ったバッファサイズまたはsthを選択したことさえある可能性があります。私は2日で問題を見つけることができませんでした...: -/ – z0rb

答えて

1

fwrite(input1, 17, 1, send);に注意してください。 親のプロセスは、 '\ n'文字の後にランダムなものをの子ののプロセスに送信している可能性があります。 while(fgets(input2, 17, receive) != NULL)の場合、fgetsは '\ n'を取得中に停止し、17-1文字未満になることがあります。その次の読書パイプはランダムなものを得るでしょう。

即時修正の1つはfwrite(input1, strlen(input1), 1, send);です。 'man fwrite'を参照すると、fwrite(input1, sizeof (input1[0]), strlen(input1), send);を使用する方が良いでしょう。

とにかく、マジックナンバー17を使用すると危険です。 PIPEは連続した文字ストリームです。

関連する問題