使用管道c++的(wrtie/read)函数关闭函数

Close function with (wrtie/read) function for pipe c++

本文关键字:函数 read wrtie 管道 c++      更新时间:2023-10-16

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

#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

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

我该如何解决这个问题?

此代码有许多问题。

"读取前关闭"的问题是,在main中,在分支之前关闭管道的读取端。这意味着子进程没有有效的文件描述符可供读取。这也意味着(在主进程中)写入很可能出错,因为无法从管道中读取数据。

解决方案是将调用移到更高的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),但从未在字符串之后写入终止''。更好的方法是:

 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";,您的实际问题会更加明显——这就是为什么我们要求使用最小示例。