【问题标题】:How do I get keyboard inputs from the user using C and linux?如何使用 C 和 linux 从用户那里获取键盘输入?
【发布时间】:2020-05-05 22:44:05
【问题描述】:

我必须编写一个简短的程序,创建两个子进程,每个子进程从键盘接受一个整数并将它们写入管道,父进程从管道汇总它们并在屏幕上显示总数。

我用 scanf() 写了一个,但它冻结了,它没有给我总和。如果可能的话,我如何使它与 scanf 或任何其他方式一起工作?

#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);
}

【问题讨论】:

  • 您需要在进程之间进行一些同步,以确保它们不会同时尝试从终端读取;否则 AFAIK 你不能确定哪一个会得到数据。另请注意,子进程将继续运行通过 if(fork()==0) 块,因此您可能希望在该块的末尾放置一个 _exit()
  • 输入数字后是否按 Enter 键?
  • @NateEldredge 你能帮忙实现同步吗?我知道我需要一个信号量或互斥体,但我不知道在运行代码时如何区分两个孩子。我也会把 _exit() 命令放在代码的末尾。
  • @Joseph SIble-Reinstate Monica 是的,我是,但它只是换了一个新行。
  • 由于孩子们都做同样的事情,你不需要区分他们。他们都可以尝试锁定信号量;一个会成功,另一个会等到第一个解锁它。

标签: c linux pipe fork


【解决方案1】:

这里有很多问题:

  • 你有if(pipe(pd) == -1),我假设你打算有一个错误处理程序作为它的“then”子句,但你没有,所以只有在管道失败时才会产生孩子,这基本上与你想要什么。
  • 你有scanf("%d", num);。您需要 &amp;num,因为 num 还不是指针。
  • 您需要来自子进程的returnexit,否则它们将进入下一个循环并消耗输出。

只要解决了这些问题,就足以让它发挥作用:

#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);
}

还有一些其他问题您也应该解决,但它们并不是完全的阻碍。这就是我突然想到的:

  • 您不需要声明自己的pipe 原型。 unistd.h 中的那个很好。
  • 您应该处理forkscanf 失败的情况。
  • 您应该处理部分读取和写入。
  • 您应该在分叉后关闭子管道的读取端和父管道的写入端。
  • 您应该考虑使用锁来控制读取输入,使其不依赖于 TTY 线路缓冲来可靠地工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多