2017-02-23 7 views
0

乱数の列を取り除くことができるパイプを作成しようとしています。親と子に分割し、乱数を生成し、子の場合はパイプに書き込み、親の場合は読み込みます。私はこれが近いと感じますが、私の出力はナンセンスです。誰かがパイプが何をしているのかを説明して、この行動をどのように実行するかを正しい方向に向けることができますか?文字列でパイプを使用する

#include <sys/types.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <iostream>   /* c++ I/O headers */ 
#include <string.h> 
#include<math.h> 

using namespace std; 

int main(int argc, char *argv[]) { 

//Get the number of random numbers 
int numberOfRandomNumbers = stoi(argv[1]); 

//char childPipe[200], parentPipe[200]; //pipes to hold numbers 
int pid, index, count; //counters 
int pipe1[2]; // main pipe 

int xyz = pipe(pipe1); //perform the pipe 
string stringOfRandomNumbers = ""; 

pid = fork(); //fork the process 

//check for errors------------------------------------------- 
if(xyz < 0 || pid < 0){ 
    //break 
    cout << "Error" << endl; 
    return 0; 
} 

//Check process---------------------------------------------- 

if (pid == 0) { /* child */ 

    srand(pid+4); //seed the random 
    int randNum; 


    //Start building the string 
    stringOfRandomNumbers = "Child, ID = "; 
    stringOfRandomNumbers += to_string(pid); 
    stringOfRandomNumbers += ", Random numbers: >"; 


    //Now generate random numbers 
    for (index = 0; index < numberOfRandomNumbers; index++) { 

     randNum = rand() % 100; 

     //add to string..... 
     if(index == (numberOfRandomNumbers - 1)){ 
      //last one 
      stringOfRandomNumbers += (to_string(randNum) + "<"); 
     } 
     else{  

      stringOfRandomNumbers = stringOfRandomNumbers + (to_string(randNum) + ", "); 

     } 

    } 

    cout << endl << stringOfRandomNumbers << " length = " << stringOfRandomNumbers.length() << endl; 

    close(pipe1[0]); //don't read off of pipe 
    write(pipe1[1], stringOfRandomNumbers, stringOfRandomNumbers.length()); 
    close(pipe1[1]); //done 

} 

else {  /* parent */ 


    // Now generate random numbers 
    srand(pid+8); 
    int randNum; 

    //Start the string 
    stringOfRandomNumbers = "Parent, ID = "; 
    stringOfRandomNumbers += to_string(pid); 
    stringOfRandomNumbers += ", Random numbers: >"; 


    //Now generate random numbers 
    for (index = 0; index < numberOfRandomNumbers; index++) { 

     randNum = rand() % 100; 

     //Add to string..... 
     if(index == (numberOfRandomNumbers - 1)){ 
      //last one 
      stringOfRandomNumbers += (to_string(randNum) + "<"); 
     } 
     else{  

      stringOfRandomNumbers = stringOfRandomNumbers + (to_string(randNum) + ", "); 
     } 
    } 

    close (pipe1[1]); 

    count = read(pipe1[0], stringOfRandomNumbers, stringOfRandomNumbers.length()); 

    for (index=0; index < count; index++){ 
      cout << stringOfRandomNumbers[index] << endl; 
    } 
    close (pipe1[0]); //done 
} 
} 
+0

また、この件に関する余分な資料もあります。 – MattCucco

+0

なぜ親に乱数を生成していますか?親で読み取り呼び出しを行うときは、バッファと、そのバッファに読み込む最大長を指定する必要があります。 –

+0

読み取り呼び出しに関する文書を参照してください。 'std :: string'を引数として渡すことができるとは思いません。 –

答えて

2

readwriteは、古い学校のC関数です。彼らはC++の文字列は何かを知りません。stringOfRandomNumbersは、送信したいデータへのポインタまたは受信したいバッファへのポインタです。

stringOfRandomNumbersはポインタではありません。コンパイラからの完全な拒否ではない場合、警告メッセージが表示されるはずです。たとえそれがポインタであったとしても、std::stringはそれが表すデータを必ずしも直接含むとは限りません。多くの場合、std::stringは動的に割り当てられたストレージのブロックを指し、writestd::stringの場合は、指し示すデータではなくポインタを書きます。

受信側std::stringには送信プロセスで意味をなさないメモリへのポインタがありますが、受信プロセスでは意味がなく危険です。両方が同じプロセスにある場合、メモリはまだ有効ですが、同じメモリを指す2つのstd::stringがあります。 std::stringのうちの1つが有効範囲外になると、メモリを削除し、もう1つは無効なメモリを指しているstd::stringのままにします。

いずれかの方法で本当に悪いシーンです。

次に、文字列データの長さがsizeof(std::string)と完全に一致すると、文字列データではなくstd::stringオブジェクトが送信されるため、ガベージデータまたは十分なデータが送信されません。あなたが何をしたいか

write(pipe1[1], stringOfRandomNumbers.c_str(), stringOfRandomNumbers.length()+1); 

std::string::c_strの線に沿って何かである文字列データが含まれているバッファへのポインタを取得し、受信機がどこを知っているように、1は、バッファの終端のヌルを送信します文字列は停止します。

この方法では、問題が残っています。どのくらいのデータを読み込む必要がありますか?あなたはパイプからの読み取りを続け、ヌルが見つかるまでstd::stringに何を読み込むかを追加する必要があります。 ickyの種類。

しかし

uint32_t len = stringOfRandomNumbers.length(); 
write(pipe1[1], &len, sizeof(len)); 
write(pipe1[1], stringOfRandomNumbers.c_str(), len); 

は、最初の32ビットの符号なし整数として文字列の長さを書き込み、その後、stringOfRandomNumbersバッファからlenバイトを書き込みます。

注意:uint32_tはオプションであり、コンパイラでサポートされていない可能性があります。考え方は、両方のPCが長さの正確さを正確に知ることを確認することです。そのため、送信者と受信者の両方が同意する固定サイズを見つけなければならない場合があります。受信側では

もしstd::stringから非constデータポインタを要求することができるようになるので、

uint32_t len; 
read(pipe1[0], &len, sizeof(len)); //read len 
std::vector<char> buffer(len+1); // Make buffer big enough for string and terminating null 
read(pipe1[0], buffer.data(), len); // read into buffer 
buffer[len] = '\0'; // null terminate 
stringOfRandomNumbers = buffer.data(); 

C++ 17標準は、これは少し簡単にするために投影されます。事前にstd::stringのサイズを設定しておけば、安全にそれを直接読むことができます。

+0

パイプの文脈では、両方のプロセスが同じマシン上にあります(1つはヘブン用に別のフォークされたコピーです!)ので、 'int'のような実装定義型は問題ありません。ネットワークのコンテキストでは、おそらくhtonl/ntohlを使用したいと考えています。 –

+0

実際には、読み込まれた文字列のサイズを設定し、 '&stringOfRandomNumbers [0]' .todayを渡すことができます。実際、私は今日は仕事が保証されていると思う。 –

+0

愚かな愚かなカットアンドペーストミス!ありがとう、マーティン。 – user4581301

関連する問題