1

I have to solve the following problem as homework: create two processes with popen. The parent process will read from stdin lines of at most 30 chars and give the first child the digits from the line and give the second child the letters from the line, which will transform them to uppercase. Both processes will then print these things to the parent's stdout. So basically i want something similar to running the "tee" command. Read a line, write some output and repeat until ctrl-d

Here is my attempt:

#include <stdio.h>
#include <ctype.h>

int main() {
    FILE *digits, *letters;
    char string[31];

    if ((digits = popen("tee", "w")) == NULL) {
        perror("can't create pipe for digits");
        return 1;
    }

    if ((letters = popen("tr a-z A-Z", "w")) == NULL) {
        perror("can't create pipe for letters");
        return 1;
    }

    while(!feof(stdin)) {
        fgets(string, 31, stdin);
        for (char* c = string; *c != '\0'; c++)
            if (isdigit(*c))
                fputc(*c, digits);
            else if (isalpha(*c))
                fputc(*c, letters);
        fputc('\n', digits);
        fputc('\n', letters);
    }
    pclose(digits);
    pclose(letters);
    return 0;
}

But after I write a line and press enter, the program expects input again, without printing anything. It prints all of the output at the end, after pressing ctrl-d. And I don't understand why. It reads the line correctly, then it feeds the correct characters to each child, followed by a new line. Why don't these processes immediately print their output? Is the actual command ran when pclose is called? Because I couldn't find any information about that. Also, is writing '\n' to a child's stdin the same as pressing enter? And what's even weirder is that the last line from the output of each child is printed twice.

For example, here is how I would like it to work:

(input)
1a2b3c
(output)
123
ABC
(input)
4d5e6f
(output)
456
DEF
(ctrl-d)

But I get this:

(input)
1a2b3c
(input)
4d5e6f
(ctrl-d)
(output)
123
456
456
ABC
DEF
DEF
  • 1
    It could be you need to call fflush(stdout) to get things out of the buffer if it is waiting to print. – possum May 06 '20 at 22:01
  • @possum actually what i needed to do is fflush digits and letters, the two streams i was writing to. the reason they weren't executing immediately was because the input i gave them was still in the buffer and wasn't actually written to them. now it works as expected – Andrei Toterman May 06 '20 at 22:15
  • 1
    Sorry, yeah, those were the streams. Glad you figured it out! – possum May 06 '20 at 22:19
  • 1
    you should check the return value of `fgets`. your check for end of file `!feof(stdin)` is occurring *before* `fgets` so it's not doing what you expect. please see [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – MFisherKDX May 06 '20 at 22:50

0 Answers0