具有管道c ++的(wrtie / read)功能的关闭功能

时间:2016-05-11 09:53:38

标签: c++

我尝试编写从文件中读取的程序(逐行)并计算与空格之前相同行中的字符相似的字符数。

#include<iostream>
#include<fstream>
#include<unistd.h>
#include<cstdlib>
#include<sys/types.h>
#include<sys/wait.h>
#include<string>
#include<string.h>
#include <sstream>
using namespace std;
string count ( string C , int size )
{
    int counter=0;
    char word[10] ;
    char ch ;

          for ( int i=0 ; i < size ; i++ )
          { 
               if ( C[i] == ' ' )
               {

                  for ( int j=i-1 ; j >= 0 ; j-- )
                  { word[j] = C[j]; } //save the word before the space.

                  ch = C[i+1]; //save the char after the space.
               }
          }

          for ( int z=0 ; z < strlen(word) ; z++ )
          {
              if ( word[z] == ch )
              { counter++ ; }

          }

          stringstream ss;
          ss << counter << endl;
          string newS = ss.str();
          string Result = ch + " " + newS ;

       cout << "The Result:" << Result << endl ;
       return Result;
}

int main()
{
     int pfd[2]; // file disriptors controlling the pipe ends
     pipe(pfd); //create pipe.

     ifstream myfile;
             myfile.open("Things.txt");
             string line;

               while ( !myfile.eof() )
               {
                   getline(myfile,line);
                   cout << line << endl;

                   const char *cstr = line.c_str();

                   close ( pfd[0] ); //close read of pipe.
                   write ( pfd[1] , cstr , strlen(cstr)+1 ); 
                }

              myfile.close();


     int child1 = fork();

     if ( child1 > 0 ) //parent process.
     {
             wait(NULL);



     }
     else if ( child1 == 0 ) //Child 1 process.
     {
             string Str;
             char words[10];
             cout << "hello"<<endl;
             close ( pfd[1] ); //close write pipe1.
             read ( pfd[0] , words , strlen(words)+1 ); //read - pipe1.
             Str = count( words , strlen(words)+1 );//call function count to calculate.
             cout << Str << "****"<< endl;


             int pfd2[2]; //file disriptors controlling the pipe ends.
             pipe(pfd2); //create pipe 2 .

             int child2 = fork();

             if ( child2 > 0 )//parent process.
             {
                 wait(NULL);


                 //close ( pfd2[0] ); //close read of pipe 2. 
                 //write ( pfd2[1] , ,  )

             }
             else if ( child2 == 0 )//child 2 process.
             {
                 //close ( pfd2[1] ); //close write pipe1.
                 //read ( pfd2[0] ,  ,  ); 

                 exit(0);
             }

             else
             { cout << "No Child 2 process! Error in creation" << endl; }


            exit(0);

     } 
     else
     { cout << "No Child 1 process! Error in creation" << endl; }


     return 0 ;
}

这是我想要阅读的文件:

table a

chair i

water t

green e

money m

zebra Z

我的问题是在读取/写入管道之前关闭,它在它之后没有显示任何内容..并且在关闭功能不显示后没有写入任何内容。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

此代码存在许多问题。

&#34;在阅读之前关闭&#34;问题是,在main中,在 fork之前关闭管道的读取端。这意味着子进程没有要读取的有效文件描述符。这也意味着写入(在主进程中)很可能出错,因为没有办法从管道中读取数据。

解决方案是将调用移到fork更高的位置,并将写入管道的代码放在if (child1 > 0)测试中(等待之前)。

所以主要看起来像:

int main()
{
    int pfd[2]; // file disriptors controlling the pipe ends
    pipe(pfd); //create pipe.

    const int child1 = fork();

    if ( child1 > 0 ) //parent process.
    {
        close ( pfd[0] ); // close read of pipe. Only do this once 
                          // - not in the while loop.
        ifstream myfile;
        myfile.open("Things.txt");
        string line;

        while ( !myfile.eof() )
        {
            getline(myfile,line);
            cout << line << endl;

            const char * const cstr = line.c_str();

            write ( pfd[1] , cstr , line.length()+1 ); 
        }

        myfile.close();
    }
    else if ( child1 == 0 ) //Child 1 process.
    {
        char words[10];
        cout << "hello"<<endl;
        close ( pfd[1] ); //close write pipe1.
        read ( pfd[0] , words , sizeof(words)); //read - pipe1.
        string Str = count( words , strlen(words)+1 );//call function count to calculate.
        cout << Str << "****"<< endl;


        int pfd2[2]; //file descriptors controlling the pipe ends.
        pipe(pfd2);  //create pipe 2 .

        int child2 = fork();

        if ( child2 > 0 )//parent process.
        {
            wait(NULL);

            //close ( pfd2[0] ); //close read of pipe 2. 
            //write ( pfd2[1] , ,  )

        }
        else if ( child2 == 0 )//child 2 process.
        {
            //close ( pfd2[1] ); //close write pipe1.
            //read ( pfd2[0] ,  ,  ); 

            exit(0);
        }
        else
        { cout << "No Child 2 process! Error in creation" << endl; }


        exit(0);
     } 
     else
     { cout << "No Child 1 process! Error in creation" << endl; }


     return 0 ;
}

除了这个问题,你使用strlen(word),但是你永远不会在字符串之后写一个终止'\0'。更好的方法是:

 size_t wordlen;
 ...
                  wordlen = i;
                  for ( int j=i-1 ; j >= 0 ; j-- )
                      { word[j] = C[j]; } //save the word before the space.
 ...
          for ( size_t z=0 ; z < wordlen; z++ )
          {
              if ( word[z] == ch )
              { counter++ ; }
          }

您会注意到我使用的是size_t而不是int。如果您这样做,您会发现有关签名/未签名比较的警告较少。大多数索引运算符都返回size_tstrlen也是如此。

最终评论:如果您将count简化为return "a 1";,那么您的实际问题会更加明显 - 这就是我们要求 minimal 示例的原因。< / p>