Reputation: 168
I'm attempting to create a pipe for a C program that takes pre.c and processes it using a child process and takes sort.c and processes it as a parent process. When I execute the pipe executable I get prompted for the necessary input, but then when I ctrl-d there is no output displaying. When I run ./pre | ./sort more of the same -- no output. When I run these individual executables alone they seem to work fine. Any ideas what is occurring to prevent the output from being processed properly?
pre.c:
#include <stdio.h>
typedef struct{
char name[4];
int population;
} State;
enum { MAX_STATES = 10 };
int main()
{
State myStates[MAX_STATES];
int i, j;
// Function to read in multiple lines (up to 10) of user input; loop
// controls in place, detects format problems, prevents string buffer
// overflows.
for (i = 0; i < MAX_STATES; i++)
{
if (scanf("%2s %d\n", myStates[i].name, &myStates[i].population) != 2)
break;
}
printf("\n");
// Function to output (stdout) array of State structs that exceed 10
// population.
for(j = 0; j < i; j++)
{
if(myStates[j].population >= 10)
{
printf("%s %d\n", myStates[j].name, myStates[j].population);
}
}
return 0;
}
sort.c:
#include <stdio.h>
#include <string.h>
typedef struct{
char name[3];
int population;
} State;
enum { MAX_STATES = 10 };
int main()
{
State myStates[MAX_STATES];
int i,
j,
k,
count = 0;
char temp[3];
while( scanf("%s%d", myStates[i].name, &myStates[i].population)!= EOF)
i++;
count = i;
// for(i = 0; i < MAX_STATES; i++)
// {
// if (scanf("%2s %d\n", myStates[i].name, &myStates[i].population) != 2)
// break;
// count++;
// }
printf("\n");
// Function to sort necessary input
for(j = 0; j < (count-1); j++)
{
strcpy(temp, myStates[j].name);
for(k = j + 1; k < count; k++)
{
if(strcmp(myStates[j].name, myStates[k].name) > 0)
{
strcpy(myStates[j].name, myStates[k].name);
strcpy(myStates[k].name, temp);
}
}
}
for( i=0; i < count; i++)
{
printf("%s\n", myStates[i].name);
}
return 0;
}
pipe.c:
#include <stdio.h>
int main()
{
int pid;
int fd[2];
pid = pipe(fd);
fork();
if(pid < 0) // error case
printf("could not create pipe\n");
else if(pid == 0)
{
// Child Process
close(1);
dup(fd[1]);
close(fd[0]);
close(fd[1]);
execvp("./pre", 0);
}
else
{
// Parent Process
close(0);
dup(fd[0]);
close(fd[0]);
close(fd[1]);
execvp("./sort", 0);
}
return 0;
}
Input:
$ ./pipe
TX 32
RI 3
CA 53
Output:
Upvotes: 0
Views: 376
Reputation: 755044
Fixed code — but sort.c
now uses qsort()
rather than your home-brew sort which was not working for me on bigger data sets.
The programs compile cleanly on a Mac running macOS Sierra 10.12.6 using GCC 7.1.0 and command lines like:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
> pre.c -o pre
$
There were numerous small changes needed to make that work — removed variables, added headers, etc.
One of the key changes in pipe.c
is capturing the pid
from fork()
, not pipe()
.
pre.c
#include <stdio.h>
typedef struct
{
char name[3];
int population;
} State;
enum { MAX_STATES = 10 };
int main(void)
{
State myStates[MAX_STATES];
int i, j;
for (i = 0; i < MAX_STATES; i++)
{
if (scanf("%2s %d\n", myStates[i].name, &myStates[i].population) != 2)
break;
}
for (j = 0; j < i; j++)
{
if (myStates[j].population >= 10)
{
printf("%s %d\n", myStates[j].name, myStates[j].population);
}
}
return 0;
}
sort.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
char name[3];
int population;
} State;
static int cmp(const void *v1, const void *v2)
{
const State *s1 = (State *)v1;
const State *s2 = (State *)v2;
return strcmp(s1->name, s2->name);
}
enum { MAX_STATES = 10 };
int main(void)
{
State myStates[MAX_STATES];
int count = 0;
for (int i = 0; i < MAX_STATES; i++)
{
if (scanf("%s %d", myStates[i].name, &myStates[i].population) != 2)
break;
count++;
}
qsort(myStates, count, sizeof(myStates[0]), cmp);
for (int i = 0; i < count; i++)
{
printf("%s\n", myStates[i].name);
}
return 0;
}
pipe.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int fd[2];
if (pipe(fd) != 0)
{
fprintf(stderr, "could not create pipe\n");
return(1);
}
int pid = fork();
if (pid < 0)
{
fprintf(stderr, "could not fork\n");
return(1);
}
else if (pid == 0)
{
close(1);
if (dup(fd[1]) != 1)
return(1);
close(fd[0]);
close(fd[1]);
char *arg1[] = { "./pre", 0 };
execv(arg1[0], arg1);
fprintf(stderr, "failed to execute %s\n", arg1[0]);
return(1);
}
else
{
close(0);
if (dup(fd[0]) != 0)
return(1);
close(fd[0]);
close(fd[1]);
char *arg2[] = { "./sort", 0 };
execv(arg2[0], arg2);
fprintf(stderr, "failed to execute %s\n", arg2[0]);
return(1);
}
return 0;
}
CA 39250017
TX 27862596
FL 20612439
NY 19745289
IL 12801539
PA 12784227
OH 11646273
GA 10310371
NC 10146768
MI 9928301
(Population figures from Wikipedia.)
./pre < states
CA 39250017
TX 27862596
FL 20612439
NY 19745289
IL 12801539
PA 12784227
OH 11646273
GA 10310371
NC 10146768
MI 9928301
./pre < states | ./sort
CA
FL
GA
IL
MI
NC
NY
OH
PA
TX
./pipe < states
CA
FL
GA
IL
MI
NC
NY
OH
PA
TX
Upvotes: 2