好吧,我正在开发一个“简单”的项目,即使用forks和piping来搜索文件以查找给定单词的出现次数。该程序以一种方式分叉该过程,其中父母一次向孩子发送一个单词给孩子,然后搜索文件并总结所传递单词的出现。我的问题是我不熟悉C ++,因此很难弄清楚如何从字符串中取出字符串。程序当前正在通过管道传递单词,但它们仅在运行时作为一长串字符出现。任何人都可以提供一些示例或提示,以检索字符串而不是单个字符?这是我现在的代码:
int main (int argc, char * argv[]) {
fstream fileWell ("well.txt");
fstream fileWords ("words.txt");
int pipefd[2];
int counter = 0;
pid_t cpid;
char buf;
const char * sentWord;
string toCheck;
string toSend;
pipe(pipefd);
cpid = fork();
if (cpid == -1) {
cout << "ERROR" << endl;
exit(1);
}
if (cpid == 0) {
close(pipefd[1]);
while (read(pipefd[0], &buf, 1) > 0)
write(1, &buf, 1);
cout << endl;
write(1, "\n", 1);
}
else {
while (getline(fileWords, toSend)) {
close(pipefd[0]);
sentWord = toSend.c_str();
write(pipefd[1], sentWord, strlen(sentWord));
}
close(pipefd[0]);
toSend = "-1";
sentWord = toSend.c_str();
write(pipefd[1], sentWord, 3);
close(pipefd[1]);
wait(NULL);
exit(EXIT_SUCCESS);
}
return 0;
}
我觉得一旦拿到琴弦就知道该怎么办,但如果没有这一部分我就无法前进。感谢您提出任何建议或帮助。
答案 0 :(得分:2)
拉出未使用的数据并专注于功能代码的目的,我相当确定以下是您至少要完成的任务。一些已经解决的问题。
std:string
成员进行数据指针和长度计算您对收到的词语所做的取决于您自己。我调整了这个,只是在重置之前将它们发送到标准输出。我觉得你可能有其他计划,但这与这个问题有点无关。
见下文。根据需要进行调整:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
using namespace std;
#define READ_FD 0
#define WRITE_FD 1
int main (int argc, char * argv[])
{
int fd[2];
pid_t cpid;
pipe(fd);
if ((cpid = fork()) == -1)
{
cout << "ERROR" << endl;
exit(1);
}
// child process
if (cpid == 0)
{
// don't need the write-side of this
close(fd[WRITE_FD]);
std::string s;
char ch;
while (read(fd[READ_FD], &ch, 1) > 0)
{
if (ch != 0)
s.push_back(ch);
else
{
std::cout << s << '\n';
s.clear();
}
}
// finished with read-side
close(fd[READ_FD]);
}
// parent process
else
{
// don't need the read-side of this
close(fd[READ_FD]);
fstream fileWords ("words.txt");
string toSend;
while (fileWords >> toSend)
{
// send word including terminator
write(fd[WRITE_FD], toSend.c_str(), toSend.length()+1);
}
// finished with write-side
close(fd[WRITE_FD]);
wait(NULL);
}
return EXIT_SUCCESS;
}
测试
我通过这个发送的文件是比利莎士比亚的“你喜欢它的独白,第二幕,第七场”的独白。输出的开头和结尾显示如下:
All
the
worlds
a
stage
And
all
the
men
and
women
merely
players
....
oblivion
Sans
teeth
sans
eyes
sans
taste
sans
everything
替代方案:自定义流缓冲区
另一种选择(也许你真正想要的)是调整可以与std::istream
结合的流缓冲区,以便在客户端使用,类似于常规流io。我可以集合的最简单的例子是一个char-buffer streambuf,如下所示:
// adapt a single char streambuf for an input stream
class ifd_streambuf : public std::streambuf
{
protected:
int d_fd;
char d_buffer[1];
public:
ifd_streambuf(int fd) : d_fd(fd)
{
setg(d_buffer, d_buffer + 1, d_buffer + 1);
};
private:
int underflow()
{
if (read(d_fd, d_buffer, 1) <= 0)
return EOF;
setg(d_buffer, d_buffer, d_buffer + 1);
return *gptr();
}
};
利用此功能,可以调整上一个源列表中的客户端流程代码段,以便简单地遵循:
ifd_streambuf fdbuf(fd[READ_FD]);
std::istream inf(&fdbuf);
std::string s;
while (inf >> s)
std::cout << s << '\n';
这是你可能习以为常的C ++风格。服务器端也需要更改,附加任何空格作为字分隔符:
while (fileWords >> toSend)
{
write(fd[WRITE_FD], toSend.c_str(), toSend.length());
write(fd[WRITE_FD], " ", 1);
}
需要额外的工作来调整这个streambuf来缓冲超过一个字符(一些额外的内务管理的东西),但我留下让你发现。