3

I'm trying to implement the Producer Consumer Algorithm in C so that producer.c takes in one character from a mydata.txt file and puts it into the shell variable DATA then consumer.c will read it from DATA and print it out. The output must be in the same format. All the while, producer.c and consumer.c gives the TURN to each other during the busy loop.

When I compile the program, I'm getting an error: error: too few arguments to function call, expected 1, have 0 because of both wait() functions. Please let me know if I did something wrong. I'm not sure if you'd need all the code but I hope this isn't too much!

main.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "producer.c"
#include "consumer.c"

int main(){
  char turn;
  FILE *mydata = fopen("mydata.txt", "rt");

  // Writing 0 into TURN.txt
  FILE *TURN = fopen("TURN.txt", "wt");
  if(TURN == NULL) exit(1);

  putc('0', TURN);
  fclose(TURN);

  int pid = fork();

  // Program done when turn == 'x'
  while(turn - 'x' != 0){

    TURN = fopen("TURN.txt", "rt");
    turn = getc(TURN);
    fclose(TURN);

    // producer() uses pointer to mydata.txt, to avoid having to reopen in producer.c each time
    if(pid == -1){ exit(1); }
    if(pid == 0){ producer(mydata); wait(); }
    if(pid != -1){ consumer(); wait(); }

  }

  fclose(mydata);

  return 0;
}

Producer.c:

#include <stdio.h>
#include <stdlib.h>

void producer(FILE *mydata){
  FILE *DATA;

  // Writing 1 character from mydata.txt to DATA.txt
  DATA = fopen("DATA.txt", "wt");
  if(DATA == NULL) exit(1);
  fprintf(DATA, "%c", getc(mydata));
  fclose(DATA);

  // Writing '1' into TURN.txt for consumer, or 'x' if done reading mydata.txt
  FILE *TURN = fopen("TURN.txt", "wt");
  if(TURN == NULL) exit(1);
  if(!feof(mydata))
    putc('1', TURN);
  else
    putc('x', TURN);
  fclose(TURN);
}

consumer.c:

#include <stdio.h>
#include <stdlib.h>

void consumer(){

    FILE *DATA;

    DATA = fopen("DATA.txt", "r");
    if(DATA == NULL) exit(1);
    int c;
    if(DATA == NULL) { exit(1); } 
    do {
    c = fgetc(DATA);
      if( feof(DATA) ) {
         break ;
      }
      printf("%c", c);
    } while(1);

    fclose(DATA);

    FILE *TURN = fopen("TURN.txt", "wt");
    if(TURN == NULL) exit(1);
    if(!feof(DATA))
      putc('0', TURN);
    else
      putc('x', TURN);
    fclose(TURN);

}
Sam
  • 495
  • 3
  • 11
  • 19
  • 1
    recommend `#include`ing only `.h` files and compiling with `producer.c` and `consumer.c` – yano Dec 04 '17 at 04:01
  • @yano why is that, if you don't mind answer? – Sam Dec 04 '17 at 04:03
  • I dont want to say its _always_ wrong since there are probably legit uses, but I cant say ive ever seen any. Someone more experienced can chime in one way or the other.. but `#include`ing `.c` files is not common practice. It at least cuts down on modularity... now you cant separate `main.c` from `producer.c` and `consumer.c` or compile `main.c` without those files. – yano Dec 04 '17 at 04:12
  • but as for your error, [`wait`](https://linux.die.net/man/2/wait) requires an argument,, youre not giving it one – yano Dec 04 '17 at 04:13
  • Your fopen's calls have a mode (2nd argument) that includes a "t" (tee)... Which is absent in my ubuntu man page for fopen... what is the intent, or is it a mistake? – TonyB Dec 04 '17 at 04:28
  • @TonyB `t` refers to the text mode. There is no difference between `r` and `rt` or `w` and `wt` since text mode is the default. – Sam Dec 04 '17 at 04:35
  • @Sam: `t` is a modifier for text mode on WIndows, and not on Unix. The `b` modifier (for binary mode) is portable, being defined by the C standard. On Unix, there's no difference between a text mode file stream and a binary mode file stream. On Windows, there are big differences — most notably that a text file has CRLF line endings on disk mapped to newline on input, and newline on output is mapped to CRLF, but this mapping doesn't occur with binary files. – Jonathan Leffler Dec 04 '17 at 06:00
  • 1
    @yano: You're basically correct that you should not normally include source files in other source files. However, there are occasions when including source code is a good idea, or even necessary — see [How to test a static function?](https://stackoverflow.com/questions/593414/how-to-test-a-static-function/593423#593423) for one such example. Such use cases tend to be rare. OTOH, the SQLite build compiles a single source file, which is built from multiple separately-maintained source files. That's not a million miles removed from including the source directly in the master file. – Jonathan Leffler Dec 04 '17 at 06:05
  • @JonathanLeffler thanks for the info and the link! – yano Dec 04 '17 at 15:58

1 Answers1

1

The wait function requires an argument, as the error tells you.
An address to an integer, to be precise.

TheSHEEEP
  • 2,961
  • 2
  • 31
  • 57
  • I added an argument the two wait functions are now: `if(pid == 0){ producer(mydata); wait(&status); }` `if(pid != -1){ consumer(); wait(&status); }` Now there isn't an error when compiling as it does compile, but when I run, it only prints back some of the text with many question marks and doesn't run all the way: `?erhe????e?a?atr?ss ????? motionessupn????` mydata.txt includes `Overhead the albatross hangs motionless upon the air And deep beneath the rolling waves in labyrinth of coral caves`. Can you tell what the error is? – Sam Dec 04 '17 at 15:20
  • That sounds like an entirely new question, to be honest. Likely a problem with encoding or two processes accessing the same file at the same time? Probably best to resolve this question with the wait() error an open up a new one. – TheSHEEEP Dec 05 '17 at 06:03