I trying to write a program that gets input of up to 10 .txt
files containing lines of student names and their grades. The program is supposed to create a new process for each input file and write to each student's name and average grade to a temporary file named after the pid of the process.
Eventually, the parent should wait for all processes and create a new process to combine all temporary files into a combined output file. I had struggled to pass over the pids correctly down to the output file creation so I always get only one file written successfully and the other not (when running on two input files).
Basically one of the pids is missing each time therefore my program tries to read an inexistent file. I struggling to understand why this happens and of a possible fix. Any help will be appreciated.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define GRADES_FILE "all_std.log"
typedef struct {
char name[11];
int grades[256];
int num_grades;
} student_t;
void report_data_summary(int num_stud) {
fprintf(stderr, "grade calculation for %d students is done\n", num_stud);
}
void calculate_students_grade_average_from_input(int file_number, char* filenames[])
{
student_t students[256];
int num_students = 0;
char filename[50];
sprintf(filename, "%d.temp", getpid());
FILE* fp_in = fopen(filenames[file_number], "r");
if (fp_in == NULL) {
printf("Could not open file %s\n", filenames[file_number]);
exit(EXIT_FAILURE);
}
while (!feof(fp_in)) {
fscanf(fp_in, "%s", students[num_students].name);
int grade;
students[num_students].num_grades = 0;
while (fscanf(fp_in, "%d", &grade) == 1) {
students[num_students].grades[students[num_students].num_grades] = grade;
students[num_students].num_grades++;
}
num_students++;
}
fclose(fp_in);
FILE* fp_out = fopen(filename, "w");
if (fp_out == NULL) {
printf("Could not open output file %s\n", filename);
return;
}
for (int j = 0; j < num_students; ++j) {
int sum = 0;
for (int k = 0; k < students[j].num_grades; ++k) {
sum += students[j].grades[k];
}
float avg = (float)sum / students[j].num_grades;
fprintf(fp_out, "%s %.1f\n", students[j].name, avg);
}
fclose(fp_out);
fprintf(stderr, "process: %d file: %s number of students: %d\n", getpid(), filenames[file_number], num_students);
}
void create_output(int file_count, pid_t* temp_processes[])
{
int total_students = 0;
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(EXIT_FAILURE);
}
else if (pid == 0) {
FILE* fp_final = fopen(GRADES_FILE, "w");
if (fp_final == NULL) {
perror("Could not open final output file");
exit(EXIT_FAILURE);
}
for (int i = 0; i < file_count; ++i) {
char temp_filename[16];
sprintf(temp_filename, "%d.temp", temp_processes[i]);
FILE* fp_temp = fopen(temp_filename, "r");
if (fp_temp == NULL) {
printf("Could not open temporary file %s\n",temp_filename);
return;
}
char line[101];
while (fgets(line, sizeof(line), fp_temp)) {
fputs(line, fp_final);
total_students++;
}
report_data_summary(total_students);
fclose(fp_temp);
}
fclose(fp_final);
return;
}
else {
wait(NULL);
}
}
void ex01(int file_count, char* filenames[])
{
pid_t temp_processes[10];
pid_t pid;
for (int i = 1; i < file_count; ++i) {
pid = fork();
if (pid < 0) {
perror("fork failed");
exit(EXIT_FAILURE);
}
else if (pid > 0) {
temp_processes[i-1] = pid;
printf("%d = %d\n",0,temp_processes[0]);
printf("%d = %d\nend\n",1,temp_processes[1]);
}
else {
calculate_students_grade_average_from_input(i, filenames);
return;
}
}
for (int i = 1; i < file_count; ++i) {
wait(NULL);
}
if (pid > 0)
{
create_output(file_count - 1, temp_processes);
}
}
int main(int argc, char* argv[]) {
ex01(argc, argv);
return 0;
}
Input:
file1.txt:
Abraham 80 90 75
Benny 90
Garland 70 9 90 100
file2.txt:
Dana 90 95
Ron 100 80 90
Output file:
Abraham 81.7
Benny 90.0
Garland 67.2
Output missing the second file's students.
Console output:
0 = 35222
1 = 0
end
0 = 35222
1 = 35223
end
process: 35223 file: gr_2.txt number of students: 2
process: 35222 file: gr_1.txt number of students: 3
grade calculation for 3 students is done
Could not open temporary file 0.temp