Reading a file in a table format and print it - c

So, what I'm trying to do is, at first create a file in a table format then read that file and put that file in 4 different dynamic arrays using struct and print them in order
So, here is the struct I'm using: I used capacity = 5 to change the size of dynamic array later but still don't know how to change it
struct score{
char *str1;
char *str2;
int *num1;
int *num2;
};
int main(){
int capacity = 5;
struct score table;
table.str1=(char *)malloc(sizeof(int)*capacity);
table.str2=(char *)malloc(sizeof(int)*capacity);
table.num1=(int *)malloc(sizeof(int)*capacity);
table.num2=(int *)malloc(sizeof(int)*capacity);
After I created a File to write:
inFile = fopen("Subject.txt", "w");
if(inFile == NULL)
{
printf("Error!");
exit(1);
}
char names[] = {"Joe Math 52 85\nBilly Phy 65 70\nSophia Chem 86 71"};
fprintf(inFile,"%s",names);
fclose(inFile);
At the end reading a File and putting them in arrays:
inFile = fopen("Subject.txt", "r");
if(inFile == NULL)
{
printf("Error!");
exit(1);
}
fscanf(inFile, "%s %s %d %d",table.str1, table.str2, table.num1, table.num2);
fclose(inFile);
for(i=0;i<6;i++){
printf("%s %s %d %d\n",table.str1, table.str2, table.num1, table.num2);
}
So, I need this code to print like this, and I couldn't do it:
Name Subj. Test1 Test2
------------------------
Joe Math 52 85
Billy Phy 65 70
Sophia Chem 86 71
Here is my full Code just in case:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct score{
char *str1;
char *str2;
int *num1;
int *num2;
};
int main(){
FILE *inFile;
int num, capacity = 5, i;
struct score table;
table.str1=(char *)malloc(sizeof(int)*capacity);
table.str2=(char *)malloc(sizeof(int)*capacity);
table.num1=(int *)malloc(sizeof(int)*capacity);
table.num2=(int *)malloc(sizeof(int)*capacity);
inFile = fopen("Subject.txt", "w");
if(inFile == NULL)
{
printf("Error!");
exit(1);
}
char names[] = {"Joe Math 52 85\nBilly Phy 65 70\nSophia Chem 86 71"};
fprintf(inFile,"%s",names);
fclose(inFile);
inFile = fopen("Subject.txt", "r");
if(inFile == NULL)
{
printf("Error!");
exit(1);
}
fscanf(inFile, "%s %s %d %d",table.str1, table.str2, table.num1, table.num2);
fclose(inFile);
for(i=0;i<6;i++){
printf("%s %s %d %d\n",table.str1, table.str2, table.num1, table.num2);
}
}

You want an array of structs.
But, you've got a fixed number of scores (e.g. num1, num2). This, also, should be an array.
I think you'll be better off with a second struct. That is, struct student and struct score
And, Paul outlined how to do this with fixed limits.
In general, you could allocate things dynamically to accomodate an arbitrary number of students that have an arbitrary (and varying) number of test scores.
Based on your sample data, your input format is:
<name> <subject> <score1> <score2> ... <scoreN>
Because of this, I interpret the subject to be the students major, so it gets grouped in the student record.
Otherwise, we'd need something like:
<name> <subject1> <score1> <subject2> <score2> ... <subjectN> <scoreN>
And, then, the subject would go into the score record
To get it to work, I had to [heavily] refactor your code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct score {
int score;
};
struct student {
char *name;
char *subject;
struct score *scores;
int count;
};
int
main(void)
{
FILE *inFile;
struct student *students = NULL;
int student_count = 0;
struct student *who;
struct score *score;
const char *delim = " \t\n";
char *cp;
char buf[1000];
inFile = fopen("Subject.txt", "w");
if (inFile == NULL) {
printf("Error!");
exit(1);
}
char names[] = { "Joe Math 52 85\nBilly Phy 65 70\nSophia Chem 86 71" };
fprintf(inFile, "%s", names);
fclose(inFile);
inFile = fopen("Subject.txt", "r");
if (inFile == NULL) {
printf("Error!");
exit(1);
}
while (1) {
// get a line
cp = fgets(buf,sizeof(buf),inFile);
if (cp == NULL)
break;
// get the student name
cp = strtok(buf,delim);
if (cp == NULL)
continue;
// allocate new student record
students = realloc(students,
sizeof(struct student) * (student_count + 1));
who = &students[student_count];
student_count += 1;
// save the student name
who->name = strdup(cp);
// get the subject and save it
cp = strtok(NULL,delim);
if (cp == NULL)
break;
who->subject = strdup(cp);
// clear out the scores array
who->count = 0;
who->scores = NULL;
// get all scores
while (1) {
cp = strtok(NULL,delim);
if (cp == NULL)
break;
// increase the size of the scores array for this student
who->scores = realloc(who->scores,
sizeof(struct score) * (who->count + 1));
score = &who->scores[who->count];
who->count += 1;
score->score = atoi(cp);
}
}
fclose(inFile);
for (who = &students[0]; who < &students[student_count]; ++who) {
printf("%10s %10s", who->name, who->subject);
for (score = who->scores; score < &who->scores[who->count]; ++score)
printf("%4d",score->score);
printf("\n");
}
return 0;
}
Here's the program output:
Joe Math 52 85
Billy Phy 65 70
Sophia Chem 86 71

I think you want an array of structs with one array element for each student. Now you are using one struct to hold arrays of the individual pieces of information.
The array would look like:
#define MAX_NAME 30
#define MAX_STUDENTS 10
struct score{
char str1[MAX_NAME];
char str2[MAX_NAME];
int num1;
int num2;
};
struct score table[MAX_STUDENTS];
With this definition you don't need to malloc memory (it is simpler, but not flexible).
You read the information into the array as:
int i=0;
while (fscanf(inFile, "%30s %30s %d %d",table[i].str1, table[i].str2,
&table[i].num1, &table[i].num2) == 4) {
i++;
}

Related

Dynamic Struct Array Being Allocated to infinite size

my task is to write a struct which reads data from file and realloc more memory if needed.
So Far I have done this:
The Struct:
typedef struct myprog
{
int id;
char name[100];
int price;
}myprog;
Read Function:
myprog* readFromFile(FILE* fP, char fileName[], myprog* reg, int* size)
{
fP = fopen(fileName, "r"); //Open Input File as read
if (fP == NULL) //If File is not found, do nothing
{
printf("File does not exist.");
}
else //Else read file line by line
{
printf("\nReading from File");
int x = 0;
char line[100];
char* split;
char* args[4];
while (fgets(line, 100, fP)) //Read the first line
{
if (x == MAX) //If Max Size is reached, increase it twice
{
int new_size = MAX * 2;
reg = (struct vara*)realloc(reg, new_size * sizeof(struct vara)); //Even if i comment these lines the code works :O
}
split = strtok(line, " "); //Split the line on space delimiter i.e {"1", "apple", "10"}
args[0] = split;
int i = 1;
while (split != NULL)
{
split = strtok(NULL, " ");
args[i] = split;
i++;
}
if (i != 3) //Checking if the args size is three
{
//Copy from args to struct
reg[x].id = atoi(args[0]); //Copy Number
strcpy(reg[x].name, args[1]); //Copy Name
reg[x].price = atoi(args[2]); //Copy Balance
x++;
}
}
(*size) = x;
printf("\nReading Completed!");
fclose(fP);
}
return reg;
}
Main Function:
void main()
{
char fileName[100];
FILE* fP = NULL;
printf("Enter file Name : ");
scanf("%s", fileName);
myprog* reg = malloc(MAX * sizeof * reg); //#define MAX 1
int size = 0;
reg = readFromFile(fP, fileName, reg, &size);
//Some Code below
}
The Problem I am facing:
When I run the code with MAX defined with 1, it reads any number of products from file without any memory leak errors. It even works without the realloc, can you please help me identify my mistake?
The data in input file is like this:
1 prod_a 15
2 prod_b 20

How to take unknown number of string from file in C?

I have a struct storing persons' names, surnames and salaries, but the number of their names is random. For example:
list.txt
John Smith Green 1000 //He has two names
Jennifer Wilson 2000 //She has one name
Steve Adams 1500 //He has one name
James Robert Harris 1250 //He has two names
Robin Walker 1750 //He has one name
I want to store their names in person[count].name, their surnames in person[count].surname and their salaries in person[count].salary.
To do that, I wrote:
fscanf(file, "%s %s %d", person[count].name, person[count].surname, &person[count].salary)
However, problem is that if a person has two names, his second name is stored in person[count].surname, and I cannot take the surname.
How can I take the name of a person with two names in person[count].name?
For this text file:
person[0].name ==> "John Smith"
person[1].name ==> "Jennifer"
person[2].name ==> "Steve"
person[3].name ==> "James Robert"
person[4].name ==> "Robin"
I tried reading the file line by line, then separating it into tokens (words). I am assuming each line contains at max 10 tokens (words), and the last token is salary, the one before the last is surname and first N-2 tokens are the names of the person. So, each person could have surnames with only one word, I am assuming. Here is the code, note that I did not pay attention to memory leaks or dangling pointers etc.
I edited the solution according to the suggestions from #
chux - Reinstate Monica
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Person
{
char *name, *surname;
int salary;
} Person;
int main()
{
Person persons[10];
FILE *file = fopen("text.txt", "r");
if (file == NULL)
{
printf("Error opening file!\n");
exit(1);
}
// read file line by line
char line[256];
int person_count = 0;
while (fgets(line, sizeof(line), file) != NULL)
{
char *tokens[10];
int i = 0;
tokens[0] = strtok(line, " ");
while (tokens[i] != NULL && i < 9)
{
tokens[++i] = strtok(NULL, " ");
}
char name[sizeof line];
strcpy(name, tokens[0]);
for (int j = 1; j < i - 2; j++)
{
strcat(name, " ");
strcat(name, tokens[j]);
}
persons[person_count].name = strdup(name);
persons[person_count].surname = strdup(tokens[i - 2]);
persons[person_count].salary = atoi(tokens[i - 1]);
person_count++;
}
for (int i = 0; i < person_count; i++)
{
printf("%s %s %d\n", persons[i].name, persons[i].surname, persons[i].salary);
}
fclose(file);
}
You cannot use fscanf() for this problem. Here is a simple approach reading one line at a time and parsing it explicitly with strrchr():
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Person {
char *name, *surname;
int salary;
};
int main() {
const char *filename = "list.txt";
FILE *file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
return 1;
}
// read file line by line
char line[256];
struct Person *persons = NULL;
int count = 0;
while (fgets(line, sizeof line, file) != NULL) {
char *last = strrchr(line, ' ');
if (!last) // invalid format
continue;
*last++ = '\0';
int salary;
if (sscanf(last, "%d", &salary) != 1)
continue;
const char *name = line;
char *surname = strrchr(line, ' ');
if (surname) {
*surname++ = '\0';
} else {
name = ""; // handle Superman: no first name
surname = line;
}
persons = realloc(persons, (count + 1) * sizeof(*persons));
if (persons == NULL) {
fprintf(stderr, "out of memory\n");
return 1;
}
persons[count].name = strdup(name);
persons[count].surname = strdup(lastname);
persons[count].salary = salary;
count++;
}
fclose(file);
// dump the database
for (int i = 0; i < count; i++) {
printf("%s %s %d\n", persons[i].name, persons[i].surname, persons[i].salary);
}
// free the database
for (int i = 0; i < count; i++) {
free(persons[i].name);
free(persons[i].surname);
}
free(persons);
return 0;
}

Save structure function leaves a spare place in a file instead of writing an array

#include <stdio.h>
struct BirdHome{
char area[500];
char heightcm[100];
char feederquantity[10];
char hasNest[5];
};
struct Bird{
char isRinged[5];
char nameSpecies[50];
char birdAgeMonths[500];
struct BirdHome hom;
char gender[6];
};
struct Bird birds;
int main(void){
FILE *oput;
int max=100;
int count = 0;
char filename[100];
printf("file name? : ");
scanf("%s", &filename);
count = load(filename, &birds, max);
if (count == 0)
printf("No structures loaded\n");
else (
printf("Data loaded\n")
);
save(&birds, oput);
return 0;
}
int load(char *filename, struct Bird *birds, int max){
int count = 0;
FILE *fp = fopen(filename, "r");
char line[100 * 4];
if (fp == NULL)
return 1;
while (count < max && fgets(line, sizeof(line), fp) != NULL){
sscanf(line, "%s %s %s %s %s %s %s %s", birds[count].isRinged, birds[count].nameSpecies,
birds[count].birdAgeMonths, birds[count].hom.area,
birds[count].hom.heightcm, birds[count].hom.feederquantity,
birds[count].hom.hasNest,birds[count].gender);
count++;
}
fclose(fp);
return count;
}
int save (struct Bird *birds, FILE *oput){
int i;
oput=fopen("birdssave.txt","w");
for (i=0;i<3;i++){
fprintf(oput,"%s %s %s %s %s %s %s %s\n",birds[i].isRinged, birds[i].nameSpecies,
birds[i].birdAgeMonths, birds[i].hom.area,
birds[i].hom.heightcm, birds[i].hom.feederquantity,
birds[i].hom.hasNest,birds[i].gender);
}
fclose(oput);
}
Well, the problem was said in the description of the question. Somehow, the load function works properly (at least I think so, because it runs properly and the success message is always displayed) and the save function runs without errors, but it doesn't write the needed info inside a file and just leaves gaps.
True sparrow 3 30 20 2 False Male
False crane 24 200 100 6 True Female
False griffin 14 300 80 1 False Male
This is a text file which my program used to write and load. I think this can somehow help you to find my mistakes in this code.
The load function is made unproperly so it doesn't work. The normal functions does a lot more things to do. Here is the text of it with the needed commentaries
int load(char * filename){
FILE * fp;
char *c;
int m = sizeof(int);
int n, i;
/*prepare memory for info*/
int *pti = (int *)malloc(m);
if ((fp = fopen(filename, "r")) == NULL){
perror("Error occured while opening file");
return 1;
}
/*read the quantity of structures*/
c = (char *)pti;
while (m>0){
i = getc(fp);
if (i == EOF) break;
*c = i;
c++;
m--;
}
/*get the number of elements*/
n = *pti;
/*prepare memory for read massive of structures*/
struct bird * ptr = (struct bird *) malloc(3 * sizeof(struct bird));
c = (char *)ptr;
/*after save we read massive by symbols*/
while ((i= getc(fp))!=EOF){
*c = i;
c++;
}
/*sort the elements and printing in console*/
printf("\n%d birds in the file stored\n\n", n);
for (int k = 0; k<n; k++){
printf("%d %s %s %d %d %d %d %s %s \n", k + 1,
ptr[k].isRinged,ptr[k].nameSpecies,ptr[k].birdAgeMonths,ptr[k].homearea,
ptr[k].homeheightcm,ptr[k].homefeederquantity,ptr[k].homehasNest,ptr[k].gender);
}
free(pti);
free(ptr);
fclose(fp);
return 0;
}
At least, the save function can be untouched only because algorhytmically it does the same as the normal code.

Reading from multiple files into a struct

I am having trouble with an assignment, it involves reading from files into structures and I'm confused on how to do it here is the function with the parameters I HAVE to use.
// This function will read in size struct players from filename and add these
// the players array. The function will use index to know where to start
// writing the players to in the array.
// Parameters
//
// filename – The name of the input file
// players – a pointer to the array of player structures
// index – The index of the array to start placing players into
// size – The number of players in the input file
// Return - Nothing
void read_from_file(char* filename, Player* players, int index, int size);
This is the function I have to use to read in data from 3 DIFFERENT files that look as such:
Andrew Jackson 129 33 38 30 506
Jeremy Warden 25 24 3 9 493
Jared Welch 130 1 43 27 422
Brandon Splitter 138 38 40 7 587
Joe Gwilliams 150 23 30 25 498
Ali Mohammed 119 43 13 6 598
Dheeraj Johnson 124 79 59 36 506
Bill Clinton 121 65 12 26 449
Jesse James 87 58 8 5 464
John Doe 129 100 0 12 548
I have to read in 3 files that all have 10 players in them for a total of 30 I need to read into the structures. I have not gotten very far I know but I am very confused on what to do and how to approach this, any help would be very much appreciated! Below I have down what I have already done. Please help!! Thanks
//Brady Webb
//lab D
//HW1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct player
{
char Fname[25];
char Lname[25];
int Singles;
int Doubles;
int Triples;
int Homeruns;
int At_Bats;
float Slugging_Percentage;
} Player;
void read_from_file(char* filename, Player* players, int index, int size);
int main(int argc, char* argv[])
{
int size= atoi(*(argv+1));
char* file1 = *(argv+2);
char* file2 = *(argv+3);
char* file3 = *(argv+4);
if (argc<6 || argc>6)
{
printf("Incorrect command line arguments\n");
return 0;
}
return 0;
}
void read_from_file(char*filename, Player* players, int index, int size)
{
FILE *ptr;
int i=0;
if ((ptr=fopen(filename, "r")) == NULL)
{
return 0;
}
while (ptr != EOF)
{
}
}
The simplest approach to read file with regular structure is to use fscanf with complex format string.
fscanf("%s %s %d %d %d %d %d", Player.Fname, Player.Lname,
&Player.Singles, &Player.Doubles,
&Player.Triples, &Player.Homeruns, &Player.At_Bats);
You should make a loop to read till the and of file, and you can add the check of reading the data in the correct format, e.g.:
int check = fscanf("%s %s %d %d %d %d %d", Player.Fname, Player.Lname,
&Player.Singles, &Player.Doubles,
&Player.Triples, &Player.Homeruns, &Player.At_Bats);
if( check != 7 )
{
// stop reading and report on wrong file format
}
UPDATE:
I propose the following code as possible solution:
// This function will read in size struct players from filename and add these
// the players array. The function will use index to know where to start
// writing the players to in the array.
// Parameters
//
// filename – The name of the input file
// players – a pointer to the array of player structures
// index – The index of the array to start placing players into
// size – The number of players in the input file
// Return - number of read players (positive number)
// or error code (negarive number)
int read_from_file(char * filename, Player* players, int index, int size)
{
struct player ptmp;
FILE *fptr;
// open the file
if ((fptr = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "File %s cannot be oppened\n",filename);
return -1; // error code for "File cannot be oppened"
}
// reading from file
int position = index;
int cnt = 0;
while (!ferror(fptr) && cnt < size)
{
int check = fscanf(fptr, "%24s %24s %d %d %d %d %d", ptmp.Fname, ptmp.Lname,
&ptmp.Singles, &ptmp.Doubles, &ptmp.Triples, &ptmp.Homeruns, &ptmp.At_Bats);
if (feof(fptr) && check != 7)
{
break;
}
if (check != 7)
{
fclose(fptr);
fprintf(stderr,"Wrong data format in line %d of file %s\n", cnt+1, filename);
return -2; // error code for "File has wrong data format"
}
// copy data to players
players[index++] = ptmp;
cnt++;
}
// close the file
fclose(fptr);
return cnt;
}
Pay attention at changed type of function read_from_file - I described my idea concerning return value in the comments.
And main in my understanding should be like:
int main(int argc, char* argv[])
{
Player players[30]; // memory is allocated for particular number of data items
// check the command line arguments
if (argc < 3)
{
printf("Please run the program in the format:\n");
printf(" %s 2 firstFile.txt secondFile.txt\n", argv[0]);
printf(" where 2 is number of files given after 2 with data to be read\n");
return 0;
}
int fileNumber = 0;
if (!sscanf(argv[1], "%d", &fileNumber) || fileNumber <= 0)
{
printf("The first command line argument nust be positive number.\n");
printf("Run program without parameters to see details\n");
return 0;
}
if (fileNumber != (argc - 2))
{
printf("Command line arguments are inconsistent\n");
printf("Run program without parameters to see details\n");
return 0;
}
// file processing
int i = 0;
int total = 0;
int max = 30;
for (i = 0; i < fileNumber; i++)
{
printf("Reading from %s...\n", argv[i + 2]);
int res = read_from_file(argv[i + 2], players, total, max);
if (res > 0)
{
total += res;
max -= res;
}
}
// check data
for (i = 0; i < total; i++)
{
printf("%s %s : %d %d %d %d %d\n", players[i].Fname, players[i].Lname, players[i].Singles, players[i].Doubles, players[i].Triples, players[i].Homeruns, players[i].At_Bats);
}
return 0;
}
It is assumed that 30 players can be read any number of files, and not necessarily to 10 of each file.
The loop can be return to read one line at a time and each line can be passed to a helper function like getPlayer
char *line;
char buffer[256]; // assuming that's the longest line size
while ((line = fgets(buffer, sizeof(buffer), ptr)) != NULL) {
Player *pl = getPlayer(line);
//...
}
The above code should replace loop in the code posted as while (ptr != EOF). The getPlayer can be something along the following lines (the player can then be added to list/array etc. and make sure you free up accordingly when you are done)
Player *getPlayer(char *line) {
Player *iPlayer = (Player *)malloc(sizeof(Player));
sscanf(line, "%s %s %d %d %d %d %d %f",
iPlayer->Fname,
iPlayer->Lname,
&iPlayer->Singles,
&iPlayer->Doubles,
&iPlayer->Triples,
&iPlayer->Homeruns,
&iPlayer->At_Bats,
&iPlayer->Slugging_Percentage);
return iPlayer;
}
struct Player PlayerArr[10];
void read_from_file(char*filename, Player* players, int index, int size)
{
FILE *ptr;
int i=0;
char content[50];
memset(content, '\0', 50);
if ((ptr=fopen(filename, "r")) == NULL)
{
return 0;
}
while (ptr != EOF)
{
getline(infile,line);
memset(content,'\0',sizeof(content));
strcpy(content,line.c_str());
ReadNextConfRecord(content);
}
return 0;
}
int ReadNextConfRecord(char *content)
{
char str[50];
const char delimiter[2] = " ";
char *token;
int count =0;
int i =0;
memset(str, '\0', 50);
strcpy(str, (char*)content);
token = strtok(str, delimiter);
while( token != NULL )
{
count++;
if(count == 1)
{
strcpy(PlayerArr[i].Fname, token);
}
else if(count == 2)
{
strcpy(PlayerArr[i].Lname, token);
}
else if(count == 3)
{
PlayerArr[i].Singles= atoi(token);
}
else if(count == 4)
{
PlayerArr[i].Doubles= atoi(token);
}
else if(count == 5)
{
PlayerArr[i].Triples= atoi(token);
}
else if(count == 6)
{
PlayerArr[i].Homeruns= atoi(token);
}
else if(count == 7)
{
PlayerArr[i].At_Bats= atoi(token);
}
else if(count == 8)
{
PlayerArr[i].Slugging_Percentage= atof(token);
}
i++;
token = strtok(NULL, delimiter);
}
return 0;
}
Using tokenizer can also solve above problem

Writing a file to a struct array

Anyone know how to read a text file into a struct array? I've been trying to figure out how to do so to no avail.
Here's the function header
int getRawData(FILE* fp, struct nameRecord records[], int currSize)
where the first parameter is passed a file already open for reading, the second an array of nameRecord structs, and the third the number of records currently in that array. The function is supposed to read the data from the file into the array placing it at the end of the array. It then returns the total number of records in the array after reading the file.
I'm also at a loss at initializing the number of elements for the nameRecord struct array. We've never been taught memory allocation and the problem doesn't make any mention of how many records are within the files, making initialization an excercise in frustration. So far, I'm taking advice from someone at another forum and using malloc, but I don't even really know what it does.
Some info on the program itself to provide context:
program will ask the user to enter a name (you may assume that the
name will be no more than 30 characters long). It will then find the
popularity of the name between 1921 and 2010 and print out a chart and
graph. The program will then ask the user if they wish to do another
analysis and repeat the process.
The program will pull information from the following data sources in
determining the popularity of a name.
ontario female baby names ontario male baby names
Note that some names are considered both male and female so your
program will needs the data from both files regardless of the name
entered.
My attempt at the function:
//function that reads and places the read files into the struct arrays
int getRawData(FILE* fp, struct nameRecord records[], int currSize) {
int i;
for(i = 0; i < currSize; i++) {
fscanf(fp, "%[^,],%d,%d", records[i].name, &records[i].year, &records[i].frequency);
}
And here's the entire program:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
struct nameRecord {
char name[31];
int year;
int frequency;
};
void allCaps(char[]);
int getRawData(FILE*, struct nameRecord[], int);
void setYearTotals(struct nameRecord, int, int);
void setNameYearTotals(char, struct nameRecord, int, int);
void getPerHundredThousand(int, int, double);
void printData(double);
void graphPerHundredThousand(double);
int main(void)
{
int currSizem = 0;
int currSizef = 0;
struct nameRecord *records;
FILE* fp = NULL;
FILE* fp2 = NULL;
char name[31];
printf("Please enter your name: ");
scanf("%30[^\n]", name);
printf("your name is %s\n", name);
//opening both male and female name files and reading them in order to get the total number of records in the array
fp = fopen("malebabynames.csv", "r");
if (fp != NULL) {
printf("file opened\n");
while(3 == fscanf(fp, "%[^,],%d,%d", records[currSizem].name, &records[currSizem].year, &records[currSizem].frequency)) {
currSizem++;
}
} else {
printf("file failed to open\n");
}
if(currSizem > 0) {
records = malloc(currSizem * sizeof(struct nameRecord));
}
fp2 = fopen("femalebabynames.csv", "r");
if (fp != NULL) {
printf("file opened\n");
while(3 == fscanf(fp2, "%[^,],%d,%d", records[currSizef].name, &records[currSizef].year, &records[currSizef].frequency)) {
currSizef++;
}
} else {
printf("file failed to open\n");
}
if(currSizef > 0) {
records = malloc(currSizef * sizeof(struct nameRecord));
}
return 0;
}
//function that automatically capitalizes the users inputted name
void allCaps(char s[]) {
while(*s != '\0') {
*s = toupper((unsigned char) *s);
s++;
}
}
//function that reads and places the read files into the struct arrays
int getRawData(FILE* fp, struct nameRecord records[], int currSize) {
int i;
for(i = 0; i < currSize; i++) {
fscanf(fp, "%[^,],%d,%d", records[i].name, &records[i].year, &records[i].frequency);
}
return 0;
}
approximately as follows :
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
struct nameRecord {
char name[31];
int year;
int frequency;
};
int getRawData(FILE*, struct nameRecord[], int);
int main(void){
const char *MaleFilePath = "malebabynames.csv";
const char *FemaleFilePath = "femalebabynames.csv";
int currSizem = 0;
int currSizef = 0;
FILE* mfp = NULL;
FILE* ffp = NULL;
struct nameRecord *recordsOfMale, *recordsOfFemale;
//opening both male and female name files and reading them in order to get the total number of records in the array
mfp = fopen(MaleFilePath, "r");
if (mfp != NULL) {
int dummy;
printf("file opened\n");
//line count
while(1 == fscanf(mfp, " %*[^,],%*d,%d", &dummy)){
++currSizem;
}
} else {
printf("file(%s) failed to open\n", MaleFilePath);
exit(EXIT_FAILURE);
}
if(currSizem > 0) {
recordsOfMale = malloc(currSizem * sizeof(struct nameRecord));
if(recordsOfMale == NULL){
perror("malloc for Male records");
exit(EXIT_FAILURE);
}
}
rewind(mfp);
if(currSizem != getRawData(mfp, recordsOfMale, currSizem)){
fprintf(stderr, "I could not read a record for the specified number\n"
"at reading %s\n", MaleFilePath);
exit(EXIT_FAILURE);
}
fclose(mfp);
//Do something
free(recordsOfMale);
return 0;
}
//function that reads and places the read files into the struct arrays
int getRawData(FILE* fp, struct nameRecord records[], int currSize) {
int i;
for(i = 0; i < currSize; i++) {
if(3!=fscanf(fp, " %[^,],%d,%d", records[i].name, &records[i].year, &records[i].frequency))
break;
}
return i;
}

Resources