0

目标是为文件中的每个单词创建一个子进程,并让子进程打印该单词。该文件只有以下五个单词,每个单词单独一行:

Aachen
Biscay
Capri
Dino
Ellis

问题是当我尝试打印到文件时,我得到一个单词打印两次。

Aachen
Ellis
Biscay
Capri
Ellis
Dino

这是代码。这似乎很简单,但我不明白为什么我会得到额外的词。

int main (int argc, char *argv[])
{
  char word[50];
  int i;
  pid_t p;

  while (fscanf(stdin, "%s", word) != EOF) {
    i = 0;
    while (i < sizeof(word)) {
      if (word[i] < 'A' || word[i] > 'z') {
        word[i] = '\0';
        break;
      }
      i++;
    }

    p = fork();

    if (p != 0) 
      continue;

    break;
  }

  fprintf(stdout, "%s\n", word);

  return 0;
}

我运行程序如下:

$ ./printwords < words2.txt > out.txt

4

3 回答 3

1

父亲也在最后打印最后一个字。试试这个而不是在循环后打印:

if (p == 0) {
  fprintf(stdout, "%s\n", word);
}
else {
  continue;
}
于 2013-05-08T23:25:44.970 回答
0

当您使用 %s 时,Scanf 会自动为字符串添加一个空终止符,因此您可以从代码中删除这整个部分:

i = 0;
while (i < sizeof(word)) 
{
    if (word[i] < 'A' || word[i] > 'z') 
    {
        word[i] = '\0';
        break;
    }
    i++;
}

这是我发现有效的解决方案。

#include <stdio.h>
#include <unistd.h>

int main (int argc, char *argv[])
{
    char word[50];
    int i;
    pid_t p;

    while (fscanf(stdin, "%s", word) != EOF) 
    {

        p = fork();
        if (p != 0)
            break; //this will allow the parent process to exit the loop    

        fprintf(stdout, "%s\n", word);
        fflush(stdout);

    }

    return 0;
}

在再次分叉之前有必要刷新输出缓冲区。如果您在输出缓冲区刷新之前分叉,则子进程也将继承该输出缓冲区,这将导致重复。

于 2013-05-08T23:54:33.173 回答
0
// remove pid_t p; attribution in the beginning then:

pid_t = fork();

if( pid_t == 0){
// here we're a child process. put your worker code here

}
else if (pid_t < 0){
printf("Fork failed!");

exit(1);
}
else { // here we're parent process

}
于 2013-05-08T23:55:01.317 回答