-3

As the title says I'm tryng to create a program in C in which 2 son process research a vowel(son2) and a consonant(son2). To perform the research i use 2 function, the first to research a vowel and the second to research a consonant. I give to the program 3 more file from command line:

-1° is the file in which is stored a combination of vowel and consonant

-2° is the file in which will be stored all the vowel founded

-3° is the file in which will be stored all the consonant founded

The program is compiled without error/warning but it doesn't complete the research correctly, here is an example:

-first file: qwerty

-second file: ey

-third file: 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);
            }
        }
    }

}

I use these command to compile it

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

Thanks in advance for the help!

EDIT(final) Code (now is working) simplified following all of the tips of David C. Rankin

Allen
  • 21
  • 5
  • Using `tolower (ch)` will cut the number of `if` conditions by a factor of 2. Why 2 functions instead of 1? Just `if (isalpha(ch)) { ch = tolower(ch); if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') return 1; else return 2; }` (or whatever you want to indicate consonant or vowel) – David C. Rankin Dec 08 '17 at 23:32
  • I have to say that my book never quoted this function, thanks for the tip! – Allen Dec 09 '17 at 00:54

2 Answers2

1

You don't initialize pid1 or pid2 to any particular value. And if pid1 is zero, you don't set pid2 to any value at all. But your first if checks the value of pid2. That can't be right.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Update right now the code with some fixies regarding the control over the creation of the fork and all the consonant are recognized but all the vowel are skipped. What do you mean by initialize the pid1 or pid2 to any particular value? – Allen Dec 09 '17 at 00:52
  • Suppose `pid1` is greater than zero. When you get to `if(pid2 == 0)`, what do you think the value of `pid2` will be? What code sets its value? – David Schwartz Dec 09 '17 at 00:54
  • If pid1 is greater than 0 i suppose that the fork should set the value of pid2 to 0, right? – Allen Dec 09 '17 at 01:21
  • @Allen Oh, sorry. I meant in the case where `pid1` is zero. – David Schwartz Dec 09 '17 at 15:09
  • Ok with the code writed in this way if pid1 is set to 0 pid2 will be a value lower than 0 and this explain why all the vowel are skipped, but right now i don't know how to fix this issue – Allen Dec 09 '17 at 15:30
  • In C, it is a good practice to initialize _every_ variable when you declare that variable. (The variable _will_ have a value no matter what you do, the only question is whether it is a value you would want.) If you can't think of an initial value that will allow the rest of the program to function correctly, why would you expect the compiler or runtime to assign a good value for you? For example, I might declare `pid_t pid1 = -1, pid2 = -1;`, because if `pid2` is initially set to 0, it will be zero when the first child executes `if(pid2==0)`. That will have a result you don't want. – David K Dec 11 '17 at 01:03
0

Here's one probable source of trouble:

if(pid1 = fork() < 0)

In C, < has higher precedence than =, so the order of operations is something like this:

  1. Call fork().
  2. Evaluate fork() < 0. If fork() is negative, this evaluates to 1, otherwise to 0.
  3. Set pid1 to the value of fork() < 0.

Normally, in both the parent process and in the child, fork() will return 0 or a positive number (provided that the parent was able to create a child process). So in both the parent and the child process, fork() < 0 will evaluate to 0 and pid1 will be set to 0.

Since pid1 is now equal to 0, if(pid1 > 0) will have a false condition, and the block of code after it will not execute in the child or in the parent. The second fork() will never be called, not even in the parent process where it is meant to be called.


Another thing to investigate is the effect of opening all the files in the parent process. Referring to information in the answers to Are file descriptors shared when fork()ing?, when one child reads a character from the input file it may cause the other child to "skip over" that character. The input received by each child would then depend on the order in which the child processes' calls to read overlapped, which could be random.

You could try opening the files in the child processes instead of the parent (so the input file has to be opened twice) and see if that clears things up.

David K
  • 3,147
  • 2
  • 13
  • 19
  • Re-edited the code to fix this oversight, but the problem still persist furthermore the code seems to act randomly doesn't recognize the same number and types of character from the first file but this should be a conseguence of the fact that i can't get it to work properly – Allen Dec 11 '17 at 18:05
  • I have added something to the answer that may explain the random behavior. – David K Dec 12 '17 at 13:36
  • Seems that was everything related to the open sys call, once shifted the position of that call from the parent to the son the code started to work properly. Thanks a lots! – Allen Dec 12 '17 at 17:22