dshin
dshin

Reputation: 37

How do I get keyboard inputs from the user using C and linux?

I have to make a short program that, creates two child processes, each one accepting an integer from the keyboard and writes them to a pipe, from where the parent process summarizes them and displays the total on the screen.

I've written one with scanf(), but it freezes up and it doesn't give me the sum. How do I make it work with scanf or any other way if possible?

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int pipe(int pd[2]);
int main(int argc, char *argv[])
{

    int pd[2], sum=0, num=0;
    if(pipe(pd) == -1)
    for(int i = 0; i < 2; i++)
    {
        if(fork() == 0)
        {
            scanf("%d", num);
            if(write(pd[1], &num, sizeof(int)) == -1)
                printf("Error: Write()");           
        }
    }

    for(int j = 0; j < 2; j++)
    {
        wait(NULL);
        if(read(pd[0], &num, sizeof(int)) == -1)
            printf("Error: Read()");

        sum += num;
    }
    printf("Total: %d\n", sum);
}

Upvotes: 0

Views: 498

Answers (1)

Lots of problems here:

  • You have if(pipe(pd) == -1), and I assume you meant to have an error handler as the "then" clause for it, but you don't, so children will only spawn if the pipe fails, which is basically the opposite of what you want.
  • You have scanf("%d", num);. You need &num since num isn't already a pointer.
  • You need to return or exit from the child processes, or they'll fall into the next loop and consume the output.

With just those things fixed, it's enough to make it work:

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int pipe(int pd[2]);
int main(int argc, char *argv[])
{

    int pd[2], sum=0, num=0;
    if(pipe(pd) == -1)
    {
        perror("pipe");
        return 1;
    }
    for(int i = 0; i < 2; i++)
    {
        if(fork() == 0)
        {
            scanf("%d", &num);
            if(write(pd[1], &num, sizeof(int)) == -1)
                printf("Error: Write()");
            return 0;
        }
    }

    for(int j = 0; j < 2; j++)
    {
        wait(NULL);
        if(read(pd[0], &num, sizeof(int)) == -1)
            printf("Error: Read()");

        sum += num;
    }
    printf("Total: %d\n", sum);
}

There's a few other things you should fix too, but they're not complete show-stoppers. Here's what jumped out at me:

  • You don't need to declare your own pipe prototype. The one from unistd.h is fine.
  • You should handle the case where fork or scanf fail.
  • You should handle partial reads and writes.
  • You should close the read end of the pipe in the children and the write end of the pipe in the parent after forking.
  • You should consider using a lock to control reading input, so that it doesn't depend on TTY line buffering to work reliably.

Upvotes: 1

Related Questions