1
votes

I have a program where I need to read the contents of several pipes, compare the words, print smallest word, get a new word from that pipe (and that pipe only), compare again, until all pipes are empty.

I have a couple issues:

1: For some reason I can only read from one pipe. When trying to read from the others, it keeps giving me nothing, even though if I set the pipe to be any of the others, it works with that pipe only.

Basically, I can't get sortOutput to switch to the other pipes when I want it to.

2: For some reason I cannot seem to detect when an array element is empty so it compares "" to the word, and "" is always lower.

As far as I can tell, what is happening is that sortOutput is set to the last pipe, and then it keeps reading from that pipe instead of the other pipes, or nothing if forced to read from the other pipes via the loop. I'm unsure why, but if I set sortOutput explicitly to a different pipe (without a loop, declared globally), it will read all words from any of the other pipes just fine. It's switching sortOutput to other pipes within the loop that is causing the problems, I think. Strangely enough, when setting up the initial word array, switching sortOutput to other pipes works just fine. As a note, I have to use fgets, I don't have a choice in that.

Here's the code for the suppressor, I have commented where I believe the problem to be happening:

//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;
FILE* sortOutput;

for(kindex = 0; kindex < numChildren; kindex++){ //Initializes array with beginning values
    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 < 13){ //This is where it prints out lowest values each "round", gets new words, and gets rid of duplicates
    printf("\nCurrent words in array (0, 1, 2): %s %s %s", words[0], words[1], words[2]);
    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;
            printf("Found first non-null word: %s", smallest);
            break;
        }
    }
    printf("Suppressor WHILE \n");
    nullCount = 0;
    printf("smallest word assigned: %s ", 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)", index, words[index]);
        if(words[index] == NULL){ //Fills in a NULL gap in the array with a new word from the corresponding pipe
            bzero(buffer, PIPE_BUF);
            sortOutput = fdopen(pipefds_two[index*2], "r"); //THIS IS PROBLEM!  Here, or around here!
            fgets(buffer, PIPE_BUF, sortOutput);
            words[index] = strdup(buffer);
            //fflush(sortOutput);
            printf("the word which replaces a NULL: %s", buffer);
        }
    }
    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)", words[index], smallest);
            checker = strcmp(smallest, words[index]); 
            //printf("checker\n");
            if(checker > 0){
                smallest = words[index];
                smallestIndex = index;
                printf("New smallest assigned: %s 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", 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++;
}

I know that the while loop is only set to count to 13, but that is so it's not an infinite loop when I run it and can see what is going on.

Thank you everybody in advance!

1

1 Answers

2
votes

The problem is that you're fdopening the pipes multiple times. The first time you fdopen a pipe and call fgets, it will suck the entire contents of the pipe (or at least a lot more than one line) into the FILE's internal buffer and then give you the first line. The next time you fdopen the pipe, you will have lost all the data sucked into the first FILE's buffer, which you've forgotten about as you've forgotten the value of sortOutput that was returned for the first fdopen call.

What you need to do is make sortOutput an array of FILE * and then loop through your pipes ONCE calling fdopen on each pipe and storing all the resulting FILE *s in the array. Then, later when you want to read from a pipe, you read from sortOutput[index] instead of calling fdopen again.

Also, you say you want to read (and compare) words, but you're actually reading (and comparing) lines -- including their ending newlines. As long as your input lines have one word per line and no other spaces or punctuation, this will work ok.

You also need to check the return value of each fgets for EOF and handle it appropriately.