0

I have 3 ".c" files called pre, sort and pipe. Pre takes a user input of names and GPA from a console. If the GPA is greater than or equal to 3.0, the name is stored into a struct.

Here's the pre.c file:

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

struct student{
  char temp_name[50];
  char names[50];
};

int main()
{
  int read_index = 0;
  float check_gpa;

  struct student data[read_index];

  printf("Enter student name and GPA: \n");
  scanf("%s %f\n", data[read_index].temp_name, &check_gpa);
  read_index++;

  while(scanf("%s %f\n", data[read_index].temp_name, &check_gpa) != EOF)
       {
         if (check_gpa >= 3.0)
            {
              strcpy(data[read_index].names, data[read_index].temp_name);
              read_index++;
            }
       }

  return 0;
}

The pipe file links the pre and sort files so that data from pre is sent to sort.

Here is the pipe.c file:

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

int main()
{
  char *args[] = {"./sort", NULL};
  char *argv[] = {"./pre", NULL};

  int pipe_end[2];
  int pipe_id;
  pipe(pipe_end);

  if (pipe(pipe_end)==-1) // Check for pipe functionality
    {
        perror("Pipe Failed");
        return 1;
    }

  pipe_id = fork();

  if (pipe_id < 0) //Check for fork functionality
  {
    printf("Fork failed");
    return 1;
  }
  else if(pipe_id == 0)//Child
  {
    close(pipe_end[0]);
    dup(pipe_end[0]);
    execvp(argv[0], argv);
  }
  else //Parent
  {
    wait(NULL);
    close(pipe_end[1]);
    dup2(pipe_end[1], 0);
    close(pipe_end[0]);
    execvp(args[0], args);

  }

  return 0;
}

The sort file takes names from a struct array and sorts them alphabetically and prints them to the console. And this is where the problem starts, because when I run the pipe file i get to enter names and GPA's But when ever I initiate an EOF (which is required and cannot change) by pressing Ctrl+D, I'm expecting the strings to be sent over to sort and displayed alphabetically, however this doesn't happen.

Here's the sort.c file:

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

struct student{
  char temp_name[50];
  char names[50];
};

int main()
{
  int print_index1 = 0,
      print_index2,
      read_index,
      SIZE;

struct student data[print_index1];

SIZE = print_index1;


printf("Students with GPA's greater than or equal to 3.0, listed in alphabetical order:\n ");
for(print_index1 = 0; print_index1 < SIZE; print_index1++)
   {

            for(print_index2 = print_index1 + 1; print_index2 < SIZE; print_index2++)
               {
                  if(strcmp(data[print_index1].names, data[print_index2].names) > 0)
                    {
                      strcpy(data[print_index1].temp_name, data[print_index2].names);
                      strcpy(data[print_index2].names, data[print_index1].names);
                      strcpy(data[print_index1].names, data[print_index1].temp_name);

                    }
                }

      printf("%s\n", data[print_index1].names);
    }

  return 0;
}

I've tested both files independently with user input and they worked. But a new problem has showed up, if you look at the sort file and notice I have a while loop that takes a for loop condition that I thought made sense> It worked a week ago but now it doesn't (unless it was a fluke). But that's my dilemma, I can't seem to get user input from "pre.c" over to "sort.c" I would really appreciate some help. I also think the while loop in the "sort.c" file is causing an issue with printing the names.

  • 1
    [C11 Standard - 6.7.6.2 Array declarators(p5)](http://port70.net/~nsz/c/c11/n1570.html#6.7.6.2p5) `"... each time it is evaluated it shall have a value greater than zero..."` (referring to `read_index`), Yours does not. You attempt to declare a VLA of `struct student` with size zero with `struct student data[read_index];`. That's not going to work. Instead, choose a reasonable maximum, e.g. `struct student data[128];` (or prompt the user to enter the max number of students first) You likely have other issues -- this was the first major show-stopper encountered. – David C. Rankin Feb 24 '20 at 04:19
  • @DavidC.Rankin If I were to run "sort.c" by itself that declaration worked. Do you think its casuing problems with the pipe? – murphman10 Feb 24 '20 at 04:27
  • Yes, you invoke *Undefined Behavior* with `struct student data[read_index];` and then attempting to write to `data` and increment `read_index++;` *Undefined Behavior* means anything can happen -- from appearing to run normally, to SegFaulting. I would ensure your storage is valid and then continue working through your code. See [Does "Undefined Behavior" really permit *anything* to happen ...](https://stackoverflow.com/questions/32132574/does-undefined-behavior-really-permit-anything-to-happen) – David C. Rankin Feb 24 '20 at 04:37
  • Since `pre.c` doesn't print the data it reads, it is unsurprising that other programs cannot read the data it doesn't produce. – Jonathan Leffler Feb 24 '20 at 04:39
  • Note that the prompt in `pre.c` will be sent down the pipe (and will be invisible on the screen) if you run `pre` with its standard output connected to a pipe. You could print the prompt to `stderr` instead of `stdout`. – Jonathan Leffler Feb 24 '20 at 04:42
  • The line `while(scanf("%s %f\n", data[read_index].temp_name, &check_gpa) != EOF)` exhibits several problems. You should check that you read precisely 2 values. EOF is not the same as 2; it will break the loop. But you might not have a number after the name and that will get you a return value of 1. Your code uses the questionable data, which will give you problems. The other problem is the trailing newline in the format — see [What is the effect of trailing white space in a scanf()` format string?](https://stackoverflow.com/q/19499060/15168). Don't do it — especially with interactive input. – Jonathan Leffler Feb 24 '20 at 04:49
  • In `pipe.c`, you don't close enough file descriptors in the child. **Rule of thumb**: If you [`dup2()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html) one end of a pipe to standard input or standard output, close both of the original file descriptors from `pipe()` as soon as possible. In particular, that means before using the [`exec*()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/execvp.html) family of functions. The rule also applies with either `dup()` or [`fcntl()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html) with `F_DUPFD`. – Jonathan Leffler Feb 24 '20 at 04:52
  • The parent process should not wait for the child to finish before it reads from the pipe. The child might (in general) write more data than can be stored in the pipe buffer (minimally 4 Kib, classically 5 KiB, usually 64 KiB) and will block waiting for the parent to read, while the parent waits for the child to exit – deadlock! – Jonathan Leffler Feb 24 '20 at 04:55
  • In `pre.c`, the futzing with the `temp_name` and `names` members of the structure is odd; you seem to make sure that the fields contain the same data, for no very obvious reason. – Jonathan Leffler Feb 24 '20 at 04:59

0 Answers0