gpt4 book ai didi

c - 从文件中获取数据并通过管道移动

转载 作者:太空狗 更新时间:2023-10-29 11:15:20 27 4
gpt4 key购买 nike

免责声明:这是一项作业。我不要求显式代码。我只是寻求帮助来理解这些概念,这样我就可以在不复制别人所做的情况下学习这些 Material 。

我的任务是从一个文本文件中取出一些数据,解析出单词,按字母顺序对它们进行排序,删除重复项,然后将它们输出到一个新的文本文件中。这是要使用三个进程来完成的,使用管道进行IPC。这是我第一次在这方面使用管道或任何 IPC,所以如果我遇到一些不熟悉的情况,请理解。

因此,我将主函数分为三个进程:输入/父进程、排序(子进程)和输出(孙进程)。我在父进程中创建了一个 IO 流,需要将其通过管道传递给排序过程。我已经创建了那个管道并关闭了未使用的末端(stdin 用于输入,stdout 用于排序。)

我的问题是:我不知道如何将数据从 IO 缓冲区移动到管道(在 stdout 处)。我觉得它应该使用 fputs,其中解析后的单词列表将一次一个单词传递到 stdout

下面是我迄今为止为输入过程创建的内容。文件 IO 不是我的强项,所以如果那里有错误,请告诉我,我会尽我所能来修复它们。感谢您的帮助!

} else {                            /* This is the input/parent process */

printf("This is the input process\n");

close(input_to_sortFD[0]); /*
* Closes the parent-side read-end of
* the pipe
*/

pipeStream = fdopen(input_to_sortFD[1], "w"); /*
* Buffer that feeds into
* write-end of pipe
*/


ioFileFD = fopen(ioFile, "r");
if (ioFileFD == NULL) {
perror("Fatal error: failed to open requested file");
exit(-1);
}

int i = 0;

while (fscanf(ioFileFD, "%s", wordList) != EOF) {
fputs(wordList[i], stdout);
i++;
}
}

最佳答案

您的问题是:

I don't know how to move the data from the IO buffer into the pipe (at stdout).

据我所知,您对这个问题想得太多了。如果您知道如何从 FILE * 读取和写入 FILE *,那么管道就没有什么特别之处。

我会像这样构建程序:

  • 父进程
    • 打开输入和输出文件,创建管道
    • 启动子进程“wordify”
    • 启动子进程“sortunique”
    • 等待 child 完成
  • 文字化过程
    • 读取输入并写字
  • 独特的过程
    • 读取单词,对出现的唯一项进行排序,并输出结果列表

您可以分别使用 sedsort 对“wordify”和“sortunique”流程进行原型(prototype)设计。下面的原型(prototype)将单词定义为连续出现的字母字符。

void wordify (FILE *infile, FILE *outfile)
{
int r;
make_stdio(infile, outfile);
r = execlp("sed", "sed", "-e",
"s/[^a-zA-Z][^a-zA-Z]*/ /g;s/^ *//;s/ *$//;/^$/d;s/ /\\n/g",
(char *)0);
assert(r == 0);
}

void sortunique (FILE *infile, FILE *outfile)
{
int r;
make_stdio(infile, outfile);
r = execlp("sort", "sort", "-u", (char *)0);
assert(r == 0);
}

由于原型(prototype)使用execlp()infile需要映射到stdinoutfile需要映射到 stdout。这是通过 dup2() 完成的,但我实现了一个处理 FILE * 的包装函数 fdup2()

FILE * fdup2 (FILE *oldstream, FILE *newstream)
{
if (newstream) {
if (fileno(oldstream) != fileno(newstream)) {
if (dup2(fileno(oldstream), fileno(newstream)) < 0) return 0;
fclose(oldstream);
}
return newstream;
}
return oldstream;
}

void make_stdio (FILE *infile, FILE *outfile)
{
FILE *x = fdup2(infile, stdin);
FILE *y = fdup2(outfile, stdout);
assert(x && y);
}

进程按预期使用 fork() 启动。

void launch (void (*func)(FILE *, FILE *), FILE *infile, FILE *outfile)
{
assert(infile && outfile);
switch (fork()) {
case -1: perror("fork");
exit(EXIT_FAILURE);
case 0: func(infile, outfile);
exit(EXIT_SUCCESS);
default: fclose(infile);
fclose(outfile);
}
}

现在,主程序只需打开输入和输出文件、创建管道、启动进程并等待它们完成。唯一的技巧是必须使用管道,以便它的写入端是 wordify 的输出,而它的读取端是 sortunique 的输入。

int main (int argc, char *argv[])
{
FILE *infile;
FILE *outfile;
int pipefds[2];
int r;

if (argc < 3) {
fprintf(stderr, "need input and output filenames\n");
exit(EXIT_FAILURE);
}

if ((infile = fopen(argv[1], "r")) == 0) {
perror(argv[1]);
exit(EXIT_FAILURE);
}

if ((outfile = fopen(argv[2], "w")) == 0) {
perror(argv[2]);
exit(EXIT_FAILURE);
}

r = pipe(pipefds);
assert(r == 0);

launch(wordify, infile, fdopen(pipefds[1], "w"));
launch(sortunique, fdopen(pipefds[0], "r"), outfile);
while (waitpid(-1, 0, 0) == 0) {}

return 0;
}

注意,共有3个进程参与。如果您必须启动 3 个,并且有 4 个进程参与,我会考虑将 sortunique 拆分为 sortunique

    r = pipe(pipefds1);
assert(r == 0);
r = pipe(pipefds2);
assert(r == 0);

launch(wordify, infile, fdopen(pipefds1[1], "w"));
/* sort: behaves like "sort" command with no arguments */
launch(sort, fdopen(pipefds1[0], "r"), fdopen(pipefds2[1], "w"));
/* unique: behaves like "uniq" command with no arguments */
launch(unique, fdopen(pipefds2[0], "r"), outfile);
while (waitpid(-1, 0, 0) == 0) {}

一旦您将问题分解为这些组件,那么实现特定组件的工作就只是标准的读取输入和写入输出练习。管道问题被抽象出来,因为文件流以正确的顺序排列,组件只是读写。您甚至可以删除 make_stdio() 代码,并从 infile 中读取并写入 outfile

关于c - 从文件中获取数据并通过管道移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14989319/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com