1

这可能是一个相当复杂的问题。情况如下:

我正在尝试编写一个带有两个命令行参数的程序:要生成的孩子的数量,以及用空格分隔的单词的文件名。

该程序获取文件,解析单词,必须使用 fputs 将每个单独的单词以循环方式放入管道(如第一个单词进入第一个管道,第二个单词进入第二个管道等)并附加这些管道到正确的产生的孩子。

在解析器解析单词并填充管道之后,产生 # 个子子进程,每个子进程从解析器接收一个管道,其中包含单词。然后将管道映射到标准输入以与 sort() 进程一起使用,然后将 sort() 进程的 stdout 输出附加到第二组管道(再次 #children *2)。这些来自孩子的输出管道然后被带到程序的抑制器部分,然后必须从每个管道的顶部取出一个单词,必须使用 fgets,找到最小的,打印它,丢弃它,然后替换它丢弃该管道中的第二个单词,再次查找最小的单词,直到所有管道都为空。

我知道可能有一种更简单的方法,但我决定创建一个长度为#children 的 char* 数组,因此从每个管道中,当我拉出一个单词时,我可以将它放入数组中循环并比较。当找到最小的单词时,最小单词的索引处的内容在打印该单词后设置为 NULL,并且整个 WHILE 循环的下一次迭代确保用数组中的下一个单词填充该数组的索引。对应的管道。WHILE 应该一直运行,直到数组中的所有单元格都为 NULL(不再有来自任何管道的单词)。

到目前为止,我只让 WHILE 循环迭代了 3 次,并且发现单词数组得到了它的第一组单词,它找到了最小的单词,打印它,将它设置为 NULL,但是在第二次迭代期间 NULL 内容数组的 被一个不是新词的新词替换。它是另一个管道的副本。

我不认为解析单词并将其放入管道中存在问题。我已经对其进行了广泛的测试,并且在 sort() 过程之前它似乎还不错。在排序过程之后,我恐怕只能猜测出了什么问题。我花了很多时间试图解决它,但无济于事。

所以,现在一些代码。我将发布儿童产卵部分,然后是抑制器。由于这仍在进行中,因此有点混乱,并且有几个变量仅在调试中真正使用。我提前道歉!!

子项的产生(将管道映射到标准输入/标准输出并创建 sort() 进程):

//Collection of children need to be created specified by numChildren
int count;
for(count = 0; count < numChildren; count++){
    printf("Count: %d\n", count);

    switch((p = fork())){

    case -1:
        perror("Could not create child");
        exit(-1);

    case 0:
        printf("Entering child\n");
        close(0);
        close(1);
        dup(pipefds[count*2]);
        dup(pipefds_two[(count*2)+1]);
        execlp("/bin/sort", "sort", (char*)NULL); // (char*)NULL
        break;

    default:
        //parent case -- p holds pid of child
        printf("I am the parent, PID: %d\n", getpid());
        child = wait(&status);
        printf("pipefds_two: %d\n", pipefds_two[count*2]);
        printf("Waited on child %d\n", child);

        break;
    }

}

最后,抑制器:

//Suppressor - Reads one word from each pipe, compares, prints largest.  Gets next word from that one pipe, compares, prints largest.  
//Suppressor deletes duplicate words
//Reads from pipefds_two[count*2] position
char* words[numChildren];
int index, cont=1;
char* smallest; 
int smallestIndex;
int checker;
int duplicateCount = 0;
int kindex;
char* temptwo;
int length;
int nullCount = 0;
int counter = 0;

for(kindex = 0; kindex < numChildren; kindex++){ //Initializes array with beginning values
    FILE* sortOutput = fdopen(pipefds_two[kindex*2], "r");
    fgets(buffer, PIPE_BUF, sortOutput);
    words[kindex] = strdup(buffer);
    fflush(sortOutput);
    close(pipefds_two[(kindex*2)+1]);
}
while(counter < 3){ //This is where it prints out lowest values each "round", gets new words, and gets rid of duplicates
    for(index = 0; index < numChildren; index++){
        if(words[index] != NULL){ //Searches for first value in array that's not null to be "lowest" value
            smallest = words[index];
            smallestIndex = index;
            break;
        }
    }
    printf("Suppressor WHILE \n");
    nullCount = 0;
    printf("smallest word assigned: %s\n", smallest);
    printf("smallest index %d\n", smallestIndex);
    for(index = 0; index < numChildren; index++){ //need to loop through each pipe and pull a word, THEN compare them all!
    printf("Suppressor FOR (index: %d word:%s)\n", index, words[index]);
        if(words[index] == NULL){ //Fills in a NULL gap in the array with a new word from the corresponding pipe
            FILE* sortOutput = fdopen(pipefds_two[index*2], "r");
            fgets(buffer, PIPE_BUF, sortOutput);
            words[index] = strdup(buffer);
            fflush(sortOutput);
            printf("the word which replaces a NULL: %s\n", words[index]);
        }
    }
    for(index = 0; index < numChildren; index++){ //COMPARE ALL VALUES NOW THAT IT IS POPULATED
    printf("compare FOR loop index: %d\n", index);
        if((index != numChildren) && (words[index] != NULL) && (index != smallestIndex)){
            printf("IF statement, (current arrayWord: %s)(smallest: %s)\n", words[index], smallest);
            checker = strcmp(smallest, words[index]); 
            //printf("checker\n");
            if(checker > 0){
                smallest = words[index];
                smallestIndex = index;
                printf("New smallest assigned: %s\n New Smallest Index: %d\n", smallest, smallestIndex);
            }else if(checker == 0){
                printf("Same word\n");
                words[index] = NULL;
                duplicateCount++;
            }else{
                printf("ArrayWord is larger, smallest staying the same\n");
            }

        } if(index == numChildren-1){ //reached the end of the list
            printf("The smallest this round is: %s\n", smallest);
            words[smallestIndex] = NULL;
        }
    }
    for(index = 0; index < numChildren; index++){ //Check for removed words!
    printf("Checking if entries are null in array: index %d\n", index);
        if(words[index] == NULL){
            nullCount++;
            printf("words at index null num: %d\n", nullCount);
        }
    }
    //check to see if everything is null
    counter++;
}

无论如何,如果你已经读到这里,我真诚地感谢你。这个问题困扰了我至少一个星期,任何建议/评论都非常感谢!

编辑:

据我所知,解析器将其正确拆分,并且我已经看到单词正确到达子进程。另外我昨晚做了更多的测试,抑制器首先拉出的单词是正确的单词。例如,如果您的单词列表是

关于沙发胡须的相机是伏特加裁判价格收益率

然后,假设您有 3 个孩子,当它进入管道时,它将是:第一个是相机胡须裁判,第二个是大约是的价格,第三个是沙发伏特加和产量。

当这些被排序时,第一个输出管道应该包含相机裁判须,第二个是大约价格,第三个是沙发产量伏特加。然后抑制器拿出相机,左右,沙发,并比较它们。在那之前它似乎运行良好,通过测试我发现它确实从排序列表中提取了正确的第一个单词。最小的将是 about,然后抑制器在比较数组中将其设置为 null,但这就是问题发生的地方。

问题出现在第二次迭代中。从每个管道中提取一个单词并进行比较后,然后将一个单词设置为 NULL,以便下一次迭代它被正确管道中的一个新单词替换。无论出于何种原因,在这一步,当 about 被(应该是)price 取代时,它实际上被 couch(这是第三个管道中的单词)所取代。

似乎它是从错误的管道中提取的,但根据我的代码,我看不出这是怎么可能的。

编辑2!!

我已经大大缩小了范围。通过使用 bzero(buffer, PIPE_BUF) 清除缓冲区;在从管道读取其他内容之前(在抑制器部分中,在检测到数组内容是否为 NULL 之后),以及我的 FILE* sortOutput 声明方式的一些更改(一个全局变量,而不是通过循环每次迭代重新定义它) 它现在抓取新单词。但是,当管道用完单词时,它仍然出于某种原因将空索引内容与单词进行比较(这意味着空索引内容是最小的!)

我该如何防止呢?

4

0 回答 0