0

I know there is some question about this already, but I don't understand what I'm doing wrong here. I'm reading numbers from file, and storing them into array. Now I want to create process that the parent is reading 10 numbers, then the children read the other numbers, add them together and send to the parent process, but for some reason the return value I'm getting is wrong. what I'm missing here? I added image to demonstrate example

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

int my_read(char *arg1);

int main(int argc, char *argv[])
{
  my_read("numbers.txt");
}

int my_read(char *arg1)
{
  int status;
  int avg = 0;
  int p, i;
  int arr[26];

  FILE *file = fopen(arg1, "r");

  if (NULL == file)
  {
    printf("file can't be opened \n");
  }

  fscanf(file, "%d", &i);
  while (!feof(file))
  {
    arr[p] = i;
    p++;
    fscanf(file, "%d", &i);
  }
  arr[25] = i;

  // fork
  printf("I am the parent: %d\n", (int)getpid());

  pid_t pid = fork();

  if (pid < 0)
  { /* error occurred */
    perror("Fork failed");
  }
  if (pid == 0)
  { /* child process */
    printf("I am the child with pid %d\n", (int)getpid());
    for (i = 10; i < 26; i++)
    {
      printf("%d\n", arr[i]);
      avg += arr[i];
    }
    exit(avg);//send to parent
    
  }

  /* parent process */

  for (i = 0; i < 10; i++)
  {
    printf("%d\n", arr[i]);
  }

  wait(&status);
  printf("I am the parent: %d\n", (int)getpid());
  printf("%d\n", status);

  fclose(file);
  return (0);
}
  • Wholly tangential to your parent/child communications problem: You list `1` and all the prime numbers up to 100 as the inputs. Note that one is not a prime number. A Google search 'one is not a prime number' confirms this multiple times. Historically, it was considered a prime number, but later was removed from the list of prime numbers. Nowadays, two is the smallest prime number. – Jonathan Leffler Apr 03 '22 at 18:16
  • 2
    Note that [`while (!feof(file))` is always wrong](https://stackoverflow.com/q/5431941/15168). – Jonathan Leffler Apr 03 '22 at 18:18
  • 1
    The exit status of a process that exits normally is encoded in a 16-bit unsigned value 0xXXYY where the XX is the exit status and the YY encodes information about signals that killed the child. You should use the `WEXITSTATUS(status)` macro (from ``) to get the number that the child sets. Note that in the ordinary course of business, you can only return values 0..255 (0x00..0xFF). That's adequate for this problem but not for the more general case (say where you have primes up to 1000 instead of just 100). – Jonathan Leffler Apr 03 '22 at 18:21
  • You don't need to include `` or `` twice; you shouldn't include `` unless you know how to use the extensions it provides. The memory allocation functions are declared in `` and including that is sufficient. AFAICS, you don't use any dynamic memory allocation at all, which makes the `` even more superfluous. – Jonathan Leffler Apr 03 '22 at 18:24
  • You don't seem to initialize `p` but blithely assume it will be zero. That's dangerous at best — mostly, it is just plain wrong. – Jonathan Leffler Apr 03 '22 at 18:27
  • 1
    If `fopen` fails, it is a good idea to print an error message, but not such a great idea to proceed with attempting to read the file.`fscanf( NULL, ...)` is not going to be useful. Try `if( file == NULL ){ perror(arg1); return -1; }` – William Pursell Apr 03 '22 at 19:00

1 Answers1

0

This code deals with most of the problems outlined in my comments. One area it addresses that wasn't highlighted in the comments is the fragility of the original code — it assumes that there will be exactly 26 numbers in the file. This code ensures that only 26 numbers are read.

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

int my_read(char *arg1);

int main(void)
{
  my_read("numbers.txt");
  return 0;
}

int my_read(char *arg1)
{
  int status;
  int avg = 0;
  int p, i;
  int arr[26];

  FILE *file = fopen(arg1, "r");

  if (NULL == file)
  {
    fprintf(stderr, "file '%s' can't be opened for reading\n", arg1);
    exit(EXIT_FAILURE);
  }

  p = 0;
  while (fscanf(file, "%d", &i) == 1 && p < 26)
    arr[p++] = i;

  fclose(file);

  /* p contains the number of values */

  // fork
  printf("I am the parent: %d\n", (int)getpid());

  pid_t pid = fork();

  if (pid < 0)
  { /* error occurred */
    perror("Fork failed");
  }
  if (pid == 0)
  { /* child process */
    printf("I am the child with pid %d\n", (int)getpid());
    for (i = 10; i < p; i++)
    {
      printf("%d\n", arr[i]);
      avg += arr[i];
    }
    printf("Sum of values: %d\n", avg);
    avg /= (26 - 10);
    printf("Avg of values: %d (0x%.2X)\n", avg, avg);
    exit(avg);//send to parent
  }

  /* parent process */

  for (i = 0; i < 10; i++)
  {
    printf("%d\n", arr[i]);
  }

  wait(&status);
  printf("I am the parent: %d\n", (int)getpid());
  printf("Raw: 0x%.4X\n", status);
  printf("Value: %d\n", WEXITSTATUS(status));

  return (0);
}

Given the input file (with 4 extra primes):

1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
101 103 107 109

it still works correctly — and produces output such as:

I am the parent: 18797
1
2
3
5
7
11
13
17
19
23
I am the child with pid 18798
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
Sum of values: 960
Avg of values: 60 (0x3C)
I am the parent: 18797
Raw: 0x3C00
Value: 60

Note that it is preferred not to include screenshots of plain text; showing it as text in the question is fine.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278