I'm trying to implement a program that reads in data from a file called grad.dat. Each record (i.e. each line) in the data file gives statistics for a given country, year, degree, and gender, etc. The records are formatted as follows: <countryCode countryName gender degree year numGrads>
Note: there are only 3 different types of degrees - L6, L7, and L8
General format of grad.dat:
Code:
AUS Australia F L6 2010 1276
AUS Australia M L6 2010 5779
AUS Australia F L6 2011 1255
AUS Australia M L6 2011 5739
BEL Belgium F L6 2017 157
BEL Belgium M L6 2017 1665
BEL Belgium F L7 2010 61
BEL Belgium F L8 2016 0
BEL Belgium F L8 2017 1
BEL Belgium M L8 2017 13
BRA Brazil F L6 2010 7187
BRA Brazil M L6 2010 32173
BRA Brazil F L6 2011 6240
BRA Brazil M L6 2011 30527
BRA Brazil M L6 2014 30156
BRA Brazil M L6 2016 32443
CAN Canada F L6 2010 561
CAN Canada F L6 2012 599
CAN Canada M L6 2012 3018
I'm trying to use this data to generate a series of reports. I'm stuck on the first report where I have to include:
The graduate percentage for each country, by degree, for all years and all genders
a. each country will be a row, and there will be a column for each type of degree, plus one column for
all degrees combined
b. each cell will show the proportion of graduates in that specific country, for that specific degree,
compared to the total graduates in all countries combined, for that degree
So generally, I want the first report to be printed like:
Code:
Country L6 L7 L8 Total
----------------------------------------------------
Country#1 % % %
Country#2 .....
Country#3
My program compiles. I'm required to store the graduate data in a linked list which I think I did correctly, but I'm having trouble with figuring out how to find the total number of graduates for all degrees in a specific country, as well as the total graduates in all countries combined, for that degree. My attempt at this is in report.c and I think I have the right idea of declaring variables for each degree (L6, L7, L8) and then adding the number of grads to the variable if the record's degree in the file matches the variable. I also think I have the right idea of finding the total number of graduates in a specific country by doing totalAllDegreesForCountry = L6+L7+L8.
I'm running into issues where it keeps printing the same country multiple times as the country has multiple records in the file. I'm trying to figure out how to print each country only once. My program also seems to print all the records and then seg fault at the very end and I'm not sure why.
I think the stats may be off too as it's printing values 1.00 and 0.00.
I would really appreciate some help with this or a push in the right direction in getting my first report to print correctly.
defs.h
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STR 32
typedef struct {
char code[MAX_STR];
char country[MAX_STR];
char gender[MAX_STR];
char degree[MAX_STR];
int year;
int numberOfGrads;
} DataType;
typedef struct Node {
DataType *data;
struct Node *prev;
struct Node *next;
} NodeType;
typedef struct {
int size;
NodeType *head;
NodeType *tail;
} ListType;
void initData(DataType**, char*, char*, char*, char*, int, int);
void printData(const DataType*);
void addDataToList(ListType*, DataType*);
void printList(ListType*);
void reportOne(ListType*);
main.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "defs.h"
int main()
{
FILE *infile;
DataType *data;
ListType *list ;
char code[MAX_STR];
char country[MAX_STR];
char gender[MAX_STR];
char degree[MAX_STR];
int year;
int numberOfGrads;
char input[MAX_STR];
list->size = 0;
list->head = NULL;
list->tail = NULL;
infile = fopen("grad.dat", "r");
if (!infile) {
printf("Error: could not open file\n");
exit(1);
}
while (1) {
fscanf(infile, "%s %s %s %s %d %d ", code, country, gender, degree, &year, &numberOfGrads);
initData(&data, code, country, gender, degree, year, numberOfGrads);
addDataToList(list, data);
if (feof(infile))
break;
}
fclose(infile);
while (1){
printf(" 0. Quit \n");
printf(" 1 = Top 5 and bottom 5 countries of female graduates \n");
printf("Enter a selection: ");
scanf("%s", input);
if(strcmp(input, "1")==0){
reportOne(list);
}else if(strcmp(input, "0")==0){
break;
}
}
}
void initData(DataType **r, char *co, char *c, char *g, char *d, int y, int n){
*r = malloc(sizeof(DataType));
strcpy((*r)->code, co);
strcpy((*r)->country, c);
strcpy((*r)->gender, g);
strcpy((*r)->degree, d);
(*r)->year = y;
(*r)->numberOfGrads = n;
}
void printData(const DataType *data){
printf("%s %s %s %s %d %d\n", data->code, data->country, data->gender, data->degree, data->year, data->numberOfGrads);
}
void addDataToList(ListType *list, DataType *m){
NodeType *currNode;
NodeType *prevNode;
NodeType *newNode;
prevNode=NULL;
int currPos = 0;
currNode = list->head;
while (currNode != NULL) {
prevNode = currNode;
currNode = currNode->next;
}
newNode = malloc(sizeof(NodeType));
newNode->data = m;
newNode->prev = NULL;
newNode->next = NULL;
if (prevNode == NULL)
list->head = newNode;
else
prevNode->next = newNode;
if (currNode == NULL)
list->tail = newNode;
newNode->next = currNode;
newNode->prev = prevNode;
if (currNode != NULL)
currNode->prev = newNode;
list->size++;
}
}
void printList(ListType* list){
NodeType *currNode = list->head;
while(currNode != NULL){
printData(currNode->data);
currNode = currNode->next;
}
}
reports.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "defs.h"
void reportOne(ListType* list){
NodeType *currNode = list->head;
float L6 = 0;
float L7 = 0;
float L8 = 0;
float totalGradsCountry = 0; //specific country
float totalGradsAll = 0; //all degrees all countries
printf("%15s %10s %10s %10s %10s \n", "Country", "L6","L7","L8", "Total");
printf("-------------------------------------------------------- \n");
while (currNode != NULL) {
if (strcmp(currNode->data->country, currNode->next->data->country) == 0){
if(strcmp(currNode->data->degree, "L6")==0){
L6 += currNode->data->numberOfGrads;
}else if(strcmp(currNode->data->degree,"L7")==0){
L7 += currNode->data->numberOfGrads;
}else if(strcmp(currNode->data->degree,"L8")==0){
L8 += currNode->data->numberOfGrads;
}
totalGradsCountry = L6 + L7 + L8;
totalGradsAll += totalGradsCountry;
printf("%-15s %6.2f %6.2f %6.2f %7.2f \n", currNode->data->country, L6/totalGradsCountry, L7/totalGradsCountry, L8/totalGradsCountry, totalGradsCountry/totalGradsAll);
}
currNode = currNode->next;
}
}
I have attached 2 pictures below to show of my output to show what I mean with the issues I'm facing