【问题标题】:C Research vowel and consonant with fork()C 用 fork() 研究元音和辅音
【发布时间】:2018-05-23 05:50:20
【问题描述】:

正如标题所说,我正在尝试用 C 创建一个程序,其中 2 个子进程研究一个元音 (son2) 和一个辅音 (son2)。为了进行研究,我使用了 2 个功能,第一个研究元音,第二个研究辅音。 我从命令行给程序 3 个文件:

-1°是存储元音和辅音组合的文件

-2° 是存储所有创建的元音的文件

-3°是存储所有创建的辅音的文件

程序编译没有错误/警告,但它没有正确完成研究,这里是一个例子:

-第一个文件:qwerty

-第二个文件:ey

-第三个文件:qr

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>

int test_vowel(char ch) 
{
if(ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || 
ch == 'y')
    return(1);
else 
    return(0);
}


int main(int argc, char *argv[])
{
char c, d;
int s;
pid_t pid1 = 10, pid2 = 10;

if((pid1 = fork()) < 0)
{
  printf("Error in the creation of the first fork\n");
  _exit(0);
}
if(pid1 > 0)
{
 if((pid2 = fork()) < 0)
    {
      printf("Error in the creation of the second fork\n");
      _exit(0);
    }
}

int input = open(argv[1],O_RDONLY);
int output1 = open(argv[2],O_RDWR | O_CREAT | O_TRUNC, 0666);
int output2 = open(argv[3],O_RDWR | O_CREAT | O_TRUNC, 0666);

if(pid2 == 0)
    {
     while((s = read(input, &c, 1)) != 0)
        {
         if(test_vowel(tolower(c)) == 1)
            {
             printf("I've read a vowel = %d\n", d);
             write(output1, &c, 1);
            }
        }
    }

if(pid1 == 0)
    {
     while((s = read(input, &d, 1)) != 0)
        {
         if(test_vowel(tolower(d)) == 0)
            {
             printf("I've read a consonant = %d\n", d);
             write(output2, &d,1);
            }
        }
    }

}

我使用这些命令来编译它

gcc c.c
./a.out c.txt v.txt b.txt

提前感谢您的帮助!

编辑(最终) 遵循 David C. Rankin 的所有提示简化了代码(现在正在运行)

【问题讨论】:

  • 使用tolower (ch) 会将if 条件的数量减少2 倍。为什么是2 个函数而不是1 个?只需if (isalpha(ch)) { ch = tolower(ch); if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') return 1; else return 2; }(或任何你想表示的辅音或元音)
  • 我不得不说我的书从来没有引用过这个函数,谢谢你的提示!

标签: c fork


【解决方案1】:

您不会将 pid1pid2 初始化为任何特定值。如果pid1 为零,则根本不会将pid2 设置为任何值。但是您的第一个if 会检查pid2 的值。这不可能。

【讨论】:

  • 现在更新代码,包含一些关于控制创建分叉和所有辅音的修正,但所有元音都被跳过。将 pid1 或 pid2 初始化为任何特定值是什么意思?
  • 假设pid1 大于零。当你到达if(pid2 == 0) 时,你认为pid2 的价值会是多少?什么代码设置它的值?
  • 如果 pid1 大于 0 我想 fork 应该将 pid2 的值设置为 0,对吧?
  • @Allen 哦,对不起。我的意思是在pid1 为零的情况下。
  • 好的,如果 pid1 设置为 0,则以这种方式编写的代码 pid2 将是一个低于 0 的值,这解释了为什么跳过所有元音,但现在我不知道如何解决这个问题
【解决方案2】:

这是一个可能的麻烦来源:

if(pid1 = fork() < 0)

在 C 中,&lt; 的优先级高于 =,因此操作顺序如下:

  1. 致电fork()
  2. 评估fork() &lt; 0。如果 fork() 为负,则计算结果为 1,否则计算结果为 0。
  3. pid1 设置为fork() &lt; 0 的值。

通常,在父进程和子进程中,fork() 将返回 0 或正数(前提是父进程能够创建子进程)。所以在父进程和子进程中, fork() &lt; 0 将评估为 0,pid1 将设置为 0。

由于pid1 现在等于0,if(pid1 &gt; 0) 将有一个错误条件,并且它之后的代码块不会在子父中执行。第二个fork() 永远不会被调用,即使在它应该被调用的父进程中也是如此。


另外要调查的是在父进程中打开所有文件的效果。 参考答案中的信息 Are file descriptors shared when fork()ing?, 当一个孩子从输入文件中读取一个字符时,可能会导致另一个孩子“跳过”该字符。 然后,每个子进程接收的输入将取决于子进程对read 的调用重叠的顺序,这可能是随机的。

您可以尝试在子进程而不是父进程中打开文件(因此输入文件必须打开两次),看看是否可以解决问题。

【讨论】:

  • 重新编辑了代码以修复这个疏忽,但问题仍然存在,而且代码似乎随机运行,无法识别第一个文件中相同数量和类型的字符,但这应该是我无法让它正常工作的后果
  • 我在答案中添加了一些可以解释随机行为的内容。
  • 似乎与 open sys 调用相关的所有内容,一旦将该调用的位置从父级转移到子级,代码就开始正常工作。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
相关资源
最近更新 更多