Reading a data file and storing into array of structures - c

I'm attempting to read a data file and to store the information into an array of course structures (or an array of pointers to course structures). This assignment requires maintaining a database using an array of pointers to the student structures.
I'm getting a segmentation fault when I attempt to scan the data file into the array. How can I properly store the information from the file into the array?
#define SIZE 30
#define fieldLength 300
#define diskFile "diskFile.dat"
#define courseFile "course.dat"
struct student
{
char name[fieldLength];
int age[fieldLength];
char course1[fieldLength];
char course2[fieldLength];
char remarks[fieldLength];
}*sp[SIZE];
struct course
{
char name[fieldLength];
char number[fieldLength];
char instructor[fieldLength];
char date[fieldLength];
char starting[fieldLength];
char ending[fieldLength];
char location[fieldLength];
};
int main(int argc, char *argv[])
{
int i, count;
struct course course_arr[SIZE]; // an array of ten structs
FILE * in; /*FILE pointer to do the stream IO*/
in = fopen(courseFile, "r+");
count = 0;
while ((fscanf(in, "%s %s %s %s %s %s %s",
&course_arr[count].name,
&course_arr[count].number,
&course_arr[count].instructor,
&course_arr[count].date,
&course_arr[count].starting,
&course_arr[count].ending,
&course_arr[count].location)) != EOF)
{
count++;
}
/* print the menu */
printf("\n-----------------------------------------------------------------\n");
printf("|\t%-20s","(N)ew record");
printf("%-20s","(U)pdate record");
printf("Swa(p) records\t|\n");
printf("|\t%-20s","(S)ort database");
printf("%-20s","(C)lear database");
printf("(D)isplay db\t|\n");
printf("|\t%-20s","(L)oad disk");
printf("%-20s","(W)rite disk");
printf("(E)mpty disk\t|\n");
printf("|\t%-20s", "(V)iew courses");
printf("%-20s","(R)emove record");
printf("(Q)uit \t|\n");
printf("-----------------------------------------------------------------\n");
printf("choose one: ");

Routine fscanf never returns EOF.
Test fscanf to be less than the number of expected fields:
count = 0;
while((fscanf(in, "%s %s %s %s %s %s %s", &course_arr[count].name, &course_arr[count].number, &course_arr[count].instructor, &course_arr[count].date, &course_arr[count].starting, &course_arr[count].ending, &course_arr[count].location)) < 7){
count++;
}

i think that it is better to work with
while(getline(string_variable,,)!=EOF).(look on the net on which argumentsto put in the getline)
Then work with the string_variable. Look at the format that the data is stored into the txt file. eg: name(blank)number(blank)instructor(blank)date(blank)starting(blank)endinglocation
Start looking for blanks in the string_variable. when you see the first blank copy the substring from position 1 to position blank-1 to the course_arr[count].name variable.then delete the substring from position 1 to position blank. Look again for the first blank and store the substring to course_arr[count].number and so on.
Sorry for my English hope u got the meaning

You should loose all the &s in the fscanf call. The char arrays are already passed as pointers. If you'd used the -Wall option on gcc (or a similar option for any other compiler) it will warn you for this as well.

Have you checked the file what you are reading is present or not.
add bellow
in = fopen(courseFile, "r+");
if(in == NULL)
{
printf("exit");
exit(0);
}
I guess it might be the problem.

Related

Read struct array in files and printf specific line on certain condition [c language]

I have learned about File processing in C programming recently. And I was given homework which
call me to read data on a .txt files and printf out the data
The problem I'm facing with is my output appear random alien word*(smth like this ╝ c 0.00
6?φ↨ê■` 0.00)* when i enter my selection.BUT I think I code it properly (fopen and fclose the files, read the files with fread) and I just don't get it why my programm come into an error. I spend almost 3 days on youtube and google everything but I still failed on it and it almost reach the due date.
can someone please help me? Rlly thank you.
also if you're free, please show me a correct code of this program so that I could make it as a reference. If you're not free its okay then :D
//Is my system flow correct , if i wanna read the files, and printf specific line from the files at certain condition. ( e.g. defining struct > open > if-else statement > do -while loop >end) ? or we have other flowchart which is more smooth
//is it possible that i read all lines of the files, but I only printf out one single specific line?if yes, how can we do this?
Here is the question
car.txt file shows variety of car maker, model, color and price. Design a program that read car maker, model, color and price from car.txt. List down the price options of for user to select from. The program will be able to display to the screen of particular car maker, model, color and price based on price range selection.
below is the .txt file
Toyota Altis Silver 120000.00
Toyota Vios Black 90000.00
Honda Accord Black 152000.00
Honda Civic Silver 118000.00
Nissan Cefiro Black 151000.00
Nissan Sylphy Silver 121000.00
Proton Perdana Black 110000.00
Proton Waja Blue 70000.00
//this was my code//
#include <stdio.h>
struct CarType
{
char carmaker[10],model[10],colour[10];
float price;
};
int main ()
{
char option;
FILE *fp;
struct CarType car[8];
if((fp = fopen("carM.txt", "r")) == NULL)
printf("file cant be open");
else
{
while (!feof(fp))
{
fread(&car[8], sizeof(struct CarType), 8, fp);
printf("\nChoose your option");
printf("\n1-List car price equal or above RM120,000");
printf("\n2-List car price RM120,000-RM149,999");
printf("\n3-List car price RM50,000-RM119,999");
printf("\n4-End program");
printf("\n>> ");
do
{
scanf("%c",&option);
if (option == '1')
{
printf("\nCar price equal or above RM120,000");
printf("\n %s %s %s %.2f",car[0].carmaker, car[0].model, car[0].colour, car[0].price);
printf("\n %s %s %s %.2f",car[2].carmaker, car[2].model, car[2].colour, car[2].price);
printf("\n %s %s %s %.2f",car[4].carmaker, car[4].model, car[4].colour, car[4].price);
printf("\n %s %s %s %.2f",car[5].carmaker, car[5].model, car[5].colour, car[5].price);
break;
}
if (option == '2')
{
printf("\nCar price RM120,000-RM149,999");
printf("\n %s %s %s %.2f",car[0].carmaker, car[0].model, car[0].colour, car[0].price);
printf("\n %s %s %s %.2f",car[5].carmaker, car[5].model, car[5].colour, car[5].price);
break;
}
if (option == '3')
{
printf("\nCar price RM50,000-RM119,999");
printf("\n %s %s %s %.2f",car[1].carmaker, car[1].model, car[1].colour, car[1].price);
printf("\n %s %s %s %.2f",car[3].carmaker, car[3].model, car[3].colour, car[3].price);
printf("\n %s %s %s %.2f",car[6].carmaker, car[6].model, car[6].colour, car[6].price);
printf("\n %s %s %s %.2f",car[7].carmaker, car[7].model, car[7].colour, car[7].price);
break;
}
if (option == '4')
{
printf("\nEnd pf Program");
}
else
{
printf("Error input");
}
}while(option!= '4');
}fclose (fp);
}
return 0;
}
This is a logical error, which just so happened to have altered the rest of your program.
fread(&car[8], sizeof(struct CarType), 8, fp);
Firstly, it is a buffer overflow. It writes memory starting at the end of the allocated buffer. You were probably thinking of this:
fread(car, sizeof(struct CarType), 8, fp);
Secondly, you are assuming each line is exactly the size of your struct (34 bytes). So, I would avoid using fread in this case, since you don't know the size of each line.
I recommend using this instead:
int fscanf(FILE *stream, const char *format, ...);
Example:
FILE* txtFile = fdopen("test.txt","r");
char a[10],b[10];
fscanf(txtFile, "%s %s\n", a, b);
To summarize, you should read one line at a time with fscanf and once you are finished parsing all the data, then you should loop through all the cars to print out all the cars that satisfy the correct pricing ranges.
Suggestion: It might be helpful to create a print function for your struct. Something with this kind of prototype:
void printCar(CarType* car);
Also, man pages are your friend. If you want more info on fscanf do man fscanf in your terminal or look up fscanf man pages on Google.
No wonder you get strange input. You are attempting a binary read of text from a file into a struct -- that won't work. Instead, you need to read a entire line of data with fgets() or POSIX getline() and then separate (parse) the needed values from the filled array with sscanf(). While your member array size of 10 will work, buy yourself a little more room. I would use 16 at a minimum.
When you declare your struct, you can add a typedef an avoid having to write struct cartype each time a type is needed, writing simply cartype instead. you could do something similar to:
#include <stdio.h>
#define MAXC 16 /* if you need a constant, #define one (or more) */
#define LINE 1024
typedef struct { /* a typedef allows you to refer to the type without struct */
char carmaker[MAXC],
model[MAXC],
colour[MAXC];
double price;
} cartype;
In main(), you need your array of struct, a counter and a buffer (character array) to hold each line read from your data file.
int main (int argc, char **argv) {
char buf[LINE]; /* buffer to hold line */
size_t n = 0; /* counter */
cartype car[MAXC] = {{.carmaker = ""}}; /* array of cartype (MAXC of them) */
(note: the declaration of int main (int argc, char **argv). Do not hardcode filenames in your code, instead pass the filename to read as an argument to your program. You should not have to recompile your code just to read from a different file)
You can read from the filename provide as the 1st argument to your program on the command line (or read from stdin by default if no argument is given) with:
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
Above, a simple ternary is used to open the file given on the command line, or assign stdin to fp by default if no argument is given. A ternary is just a shorthand if .. else .. statement with the form test ? if_true : if_false. Where the test can be any conditional, and if the condition tests true the if_true part of the statement is used, otherwise the if_false part is used.
Reading each line from the file and separating the values into your stuct members couldn't be easier. You just read a line with fgets() and then parse the values with sscanf() validating the return of sscanf() to confirm all values were successfully parsed from the line. On success, you just update your counter. You use the counter as a test condition in the while() loop to ensure you do not attempt to store more values than your array can hold, e.g.
/* while array not full, read line of input */
while (n < MAXC && fgets (buf, LINE, fp)) { /* parse values with sscanf() */
if (sscanf (buf, "%15s %15s %15s %lf", /* always use field-width */
car[n].carmaker, car[n].model,
car[n].colour, &car[n].price) == 4) { /* validate 4 conversions */
n++; /* increment counter */
}
}
(note: when using any scanf() family of functions for string input, you must use the field-width modifier to ensure you do not attempt to store more characters to an array than it can hold. Without the field-width modifier, scanf()/sscanf() are no better than gets() See: Why gets() is so dangerous it should never be used!)
That's it. All you need to do is close your input file and output your values, e.g.
if (fp != stdin) /* close file if not stdin */
fclose (fp);
for (size_t i = 0; i < n; i++)
printf ("car[%2zu] : %-16s %-16s %-16s %10.2f\n",
i, car[i].carmaker, car[i].model, car[i].colour, car[i].price);
}
Putting it altogether, you would have:
#include <stdio.h>
#define MAXC 16 /* if you need a constant, #define one (or more) */
#define LINE 1024
typedef struct { /* a typedef allows you to refer to the type without struct */
char carmaker[MAXC],
model[MAXC],
colour[MAXC];
double price;
} cartype;
int main (int argc, char **argv) {
char buf[LINE]; /* buffer to hold line */
size_t n = 0; /* counter */
cartype car[MAXC] = {{.carmaker = ""}}; /* array of cartype (MAXC of them) */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
/* while array not full, read line of input */
while (n < MAXC && fgets (buf, LINE, fp)) { /* parse values with sscanf() */
if (sscanf (buf, "%15s %15s %15s %lf", /* always use field-width */
car[n].carmaker, car[n].model,
car[n].colour, &car[n].price) == 4) { /* validate 4 conversions */
n++; /* increment counter */
}
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
for (size_t i = 0; i < n; i++)
printf ("car[%2zu] : %-16s %-16s %-16s %10.2f\n",
i, car[i].carmaker, car[i].model, car[i].colour, car[i].price);
}
Example Use/Output
With your sample input int the file dat/imports.txt, you would pass the filename on the command line as the first argument, e.g.
$ ./bin/import_cars dat/imports.txt
car[ 0] : Toyota Altis Silver 120000.00
car[ 1] : Toyota Vios Black 90000.00
car[ 2] : Honda Accord Black 152000.00
car[ 3] : Honda Civic Silver 118000.00
car[ 4] : Nissan Cefiro Black 151000.00
car[ 5] : Nissan Sylphy Silver 121000.00
car[ 6] : Proton Perdana Black 110000.00
car[ 7] : Proton Waja Blue 70000.00
Look things over and let me know if you have further questions.
If you created the file using NotePad, or any text editor for that matter, you need make sure it saved the text as ASCII or UTF-8 no-BOM. Otherwise, you'll have to deal with code point conversions, as the codes for storing text vary widely. See Wikipedia Character encoding, the history is tightly entangled with how C processes strings of text.
Your text appears to be what we call a space delimited file. That means each line is a record and each field in the record is delimited by whitespace. Your struct however is an abstraction over physical memory that defines the fields and their types. You need to read the text file and convert each record into a struct.
Read up on the following:
fgets
fscanf
strtof
strtok
strcpy
You have options. You can read each line of the file into your struct using fscanf, or read each line into a string buffer using fgets and then use strtok to iterate over each token in the buffer and either strcpy, in the case of the string fields, and strtof for the float.
You'll find lots of examples of how others have solved similar problems in these search results: https://stackoverflow.com/search?q=%5Bc%5D+convert+string+to+struct%3F
Since this is a homework assignment, I won't just hand you code. Go study, pick a path and start writing code. As soon as you run into a problem, do a quick search here for any possible answers, and start a new question if you don't find the answer.
owwwwwwwwwwwwwwwww yeahhhhhhhhhhhhh
thx everyone, My problem was solved.
and here is my code
#include <stdio.h>
#include <stdlib.h>
struct carType
{
char maker[10],model[10],colour[10];
float price;
}carType;
int main()
{
int n;
int option;
FILE *fp;
struct carType car[8];
if((fp = fopen("car.txt", "r")) == NULL)
{
printf("File can't be opened.");
}
else
{
for(n=0;n<8;n++)
{
fscanf(fp,"%s %s %s %f",car[n].maker,car[n].model,car[n].colour,&car[n].price);
}
printf("Choose your option\n");
printf("1-List car price equal or above RM120,000\n");
printf("2-List car price RM120,000 - RM149,999\n");
printf("3-List car price RM50,000 - RM119,999\n");
printf("4-End program\n");
printf("?");
while (!feof(fp))
{
do
{
scanf("%d",&option);
if (option == 1)
{
printf("\nCar price equal or above RM120,000");
for(n=0;n<8;n++)
{
if(car[n].price>=120000)
{
printf("\n%-10s %-10s %-10s %.0f",car[n].maker, car[n].model, car[n].colour, car[n].price);
}
}
printf("\n\n");
break;
}
else if (option == 2)
{
printf("\nCar price RM120,000 - RM149,999");
for(n=0;n<8;n++)
{
if(car[n].price>=120000 && car[n].price<=149999)
{
printf("\n%-10s %-10s %-10s %.0f",car[n].maker, car[n].model, car[n].colour, car[n].price);
}
}
printf("\n\n");
break;
}
else if (option == 3)
{
printf("\nCar price RM50,000 - RM119,999");
for(n=0;n<8;n++)
{
if(car[n].price>=50000 && car[n].price<=119999)
{
printf("\n%-10s %-10s %-10s %.0f",car[n].maker, car[n].model, car[n].colour, car[n].price);
}
}
printf("\n\n");
break;
}
else if (option == 4)
{
printf("End of Program\n");
return 0;
}
else
{
printf("Error input...");
}
}while(option!= 4);
}fclose (fp);
}
return 0;
}
:D

Trying to fscanf multiple values (3 strings + integer) in a single line

I need to scan 3 strings and an integer from an already existing file, and save them each as an element in an array of structures. The file is formatted as such:
string1 string2 integer string3
string1 string2 integer string3
... and so on.
when fscanf-ing for them, it correctly scans string1, the integer, and string3. However, string2 always appears to create an error when scanning it, and when any of the string2's are printed, they are either cut off short, or have some odd ASCII symbol, like a question mark in a box; it also sometimes triggers the system "bell" sound.
I've tested collecting the strings through fscanf for each different one, and it is only the second one that ever messes up.
A stripped-down version of my code, highlighting the issue
struct carinfo
{
char name[10];
char make[15];
int number;
char color[10];
}car[4];
filepointer = fopen("file.txt", "r");
while(!feof(filepointer))
{
for(i=0;i<4;i++)
{
fscanf(filepointer, "%s %s %d %s", &car[i].name[10],
&car[i].make[15], &car[i].number, &car[i].color[10]);
printf("%s\n", &car[i].make[15]);
}
}
my expected result is that the second string will scan properly, and be stored in its entirety to its element in the array of structures; instead, the value is usually cut off (at around 2-3 characters instead of 15) and contain weird ASCII symbols.
Changing fscanf() function to this, will solve your issue.
Code
fscanf(filepointer, "%s %s %d %s", car[i].name,
car[i].make, &car[i].number, car[i].color);
You can find true way of using fscanf() in cplusplus.com:
char str [80];
FILE * pFile;
pFile = fopen ("myfile.txt","w+");
fscanf (pFile, "%s", str);
But as chris-dodd stated at comment section using feof(filepointer) inside while loop not correct.
This code below i correct it by using fscanf() return value.
I obtain this way in a stack overflow answer by lio
Complete version of your program
main.c
#include <stdio.h>
struct carinfo
{
char name[10];
char make[15];
int number;
char color[10];
}car[4];
int main(){
int i=0;
FILE* filepointer = fopen("file.txt", "r");
if(!filepointer){
printf("can't open file\n");
}
int ret=0;
do {
for(i=0;i<4;i++){
ret=fscanf(filepointer, "%s %s %d %s", &car[i].name,
&car[i].make, &car[i].number, &car[i].color);
printf("%s\n", &car[i].make);
}
} while (ret != EOF);
return 0;
}
file.txt
salam beshoma 10 daram
kee innak 15 inomikhonid!

C Saving Data from a Text File into an Array of Structures

I want to ask about file processing and struct in C language. I am given an assignment where I need to have a .txt file containing: the names of basketball teams, the games they have played in total, the amount of games they have won, etc..
Here is the task:
Get data from user-specified .txt file (eg "data.txt")
Store the data in array of struct
Let the user have the ability to sort by name or the total amount of wins they have.
Here is an example, "data.txt" file:
Structure : name, games played, won at home, lost at home, won away, lost away
Fenerbahce-Dogus 25 12 0 10 3
Tofas 25 11 2 9 3
Anadolu-Efe 26 13 1 6 6
Banvit 26 9 4 8 5
Darussafaka 26 11 2 4 9
So far, I have been trying to allocate a dynamic array (of struct) and save the data from the txt file into said array. However, the program stops responding immediately whenever I try to enter the said "data.txt". as input. Could anybody inform me why this is happening and what should I do to get past this error?
Here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *name;
int games;
int winsHome, losesHome;
int winsAway, losesAway;
int winsTotal, losesTotal;
int totalPoints;
} scoreboard;
void Load_Scoreboard_Table(char *, scoreboard *);
int main(){
char fileName[40];
FILE *inputFile;
while (1){
printf("Enter the file name> ");
gets(fileName);
inputFile = fopen(fileName,"r");
if (inputFile != NULL){
break;
}
printf("ERROR: The file %s could not be opened.\n",fileName);
printf("Please verify that the file exists.\n");
}
int listLength=0;
char curChar;
while ((curChar=fgetc(inputFile))!=EOF){
if (curChar=='\n'){
listLength++;
}
}
fclose(inputFile);
scoreboard *scoreboard_table = (scoreboard *)malloc(sizeof(scoreboard) * listLength);
Load_Scoreboard_Table(fileName,scoreboard_table);
return 0;
}
void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
FILE *inputFile;
fopen(fileName,"r");
int i=0;
while (fscanf(inputFile, "%s %d %d %d %d %d\n", (scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway)!=EOF){
(scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
(scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
(scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
i++;
}
}
Update:
I have managed to read from the file and save it in struct array.(Also added a print function). However I still cannot get it to stop freezing once it finishes printing the function (it would freeze after saving data into the array before).
Note: I know many people have warned me not to use gets; but, my teacher told me to use it for now.
Note2: I decided to have a static char name inside the struct
Note3: I have only learned about data structures today, so I'm VERY new to the topic; therefore, please explain things without going into too much detail.
What could be causing the code below to freeze?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { // defining a struct here
char name[40]; // name of the sports club
//clubs containing multiple words should be written in the following format: 'name-name-name'
//ex : 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
//This is to avoid confusion when reading from .txt file
int games;
int winsHome, losesHome;
int winsAway, losesAway;
int winsTotal, losesTotal;
int totalPoints;
} scoreboard;
void Load_Scoreboard_Table(char *, scoreboard *); // reads the .txt file and saves the contents into scoreboard_table
void Display_Scoreboard_Table(scoreboard *, int); // displays scoreboard_table, also takes it's size as input
int main(void){
char fileName[40]; // the name of the file will be stored here (ex: data.txt)
FILE *inputFile; // creating a stream to read from .txt file
while (1){ // Ask user for the name of the file until said file is opened for reading
printf("Enter the file name> ");
gets(fileName); // get string input from user that supports space characters (eg: "data.txt")
inputFile = fopen(fileName,"r"); // try opening file in read mode
if (inputFile != NULL){ //if the file has succesfully opened, then break from the loop
break;
}
printf("ERROR: The file %s could not be opened.\n",fileName); //if the file was not succesfully opened, then print appropriate error message
printf("Please verify that the file exists.\n");
}
int listLength=0; //will be used to dynamically allocate memory for scoreboard_table array (array of structs)
int curChar; // I figured that fgetc returns an integer value
while ((curChar=fgetc(inputFile))!=EOF){ //get a character until EOF
if (curChar=='\n'){ //if it's a newline character then we need to allocate more memory for scoreboard_table array
listLength++;
}
}
fclose(inputFile); // close the file as it's job is done
scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * listLength); // allocating enough memory to store the contents of .txt file
Load_Scoreboard_Table(fileName,scoreboard_table); //save the contents of file on scoreboard_table
while (1){
Display_Scoreboard_Table(scoreboard_table,listLength);
break;
}
free(scoreboard_table); //freeing memory allocated for scoreboard_table
return 0;
}
void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
FILE *inputFile = fopen(fileName,"r"); // creating stream to read from file
if(inputFile == NULL ) { //checking again just in case there is a problem opening the file
printf("ERROR: The file %s could not be opened.\n",fileName);
exit(1);
}
int i=0,j,k;
//the loop below gets data from .txt file line by line until EOF and stores it in scoreboard_table array
while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) != EOF){
(scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
(scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
(scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
i++;
}
//the loop below replaces the '-' characters with ' ' in the name of every scoreboard_table array
for (j=0;j<i;j++){
for (k=0;k<40;k++){
if ((scoreboard_table+i)->name[k] == '-'){
(scoreboard_table+i)->name[k] = ' ';
}
}
}
printf("Score records file has been successfully loaded!\n");
}
void Display_Scoreboard_Table(scoreboard *scoreboard_table,int size){
printf("Team G WH LH WA LA Won Lost Points\n");
int i;
for (i=0;i<=size;i++){
printf("%-40s%5d %5d %5d %5d %5d %5d %5d %5d\n",(scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
}
}
Thank you.
Update 2 (With working code):
The issue was caused by me allocating wrong amount of memory for the array of structs called scoreboard_table. To be more specific, I was allocating memory for array that could hold 1 less line than the file.
I have updated the code again. It is working now... (For the most part, except when an unexpected input is entered(such as being fed an empty file, or user entering more characters into gets).)
This code is more than enough for my assignment as my teachers have not asked for a more detailed program(infact, they do get angry if we submit more complicated programs since we have not yet learnt about them in class - which is why I'm using gets() and not fgets() for example).
However I'm curious to hear your opinions on the matter. What do you think I should do to improve this?
By the way, I am aware of the grammar-spelling mistakes in the code. It's just because we need to strictly obey the input-output format in our assignments and typing things differently means losing points.
Code:
/* -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
~ ~ ~ ~ VERY IMPORTANT ~ ~ ~ ~
The text file containing the data should be written in the following format:
"%s %d %d %d %d %d\n" where
%s is the name of the club
If the name of the club contains more than one word, it should be written without any space characters ' '; instead place dash characters '-'
Example: 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
complete line example:
"Anadolu-Efe 26 13 1 6 6"
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- */
//including required libraries
#include <stdio.h>
#include <stdlib.h> //used to dynamically allocate memory
#include <string.h> //used for some string manipulation functions
typedef struct { // defining a struct here
char name[40]; // name of the sports club
//clubs containing multiple words should be written in the following format: 'name-name-name'
//ex : 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
//This is to avoid confusion when reading from .txt file
int games;
int winsHome, losesHome;
int winsAway, losesAway;
int winsTotal, losesTotal;
int totalPoints;
} scoreboard;
void Load_Scoreboard_Table(char *, scoreboard *); // reads the .txt file and saves the contents into scoreboard_table
void Display_Scoreboard_Table(scoreboard *, int); // displays scoreboard_table, also takes it's size as input
void Search(scoreboard *, int, char *); // searches if a team exists in the scoreboard array and if there is; it prints the stats of the team
void interactive_board(scoreboard *, int, int); // sorts the scoreboard array depending on user input, (sort by: games, points)
/*
This program reads data from a txt data, stores it in an array of structs
The program has the ability to sort the array based on either points or games
It also can search for the name inside said array of structs
*/
int main(){
char fileName[40]; // the name of the file will be stored here (ex: data.txt)
char searchTerm[40]; // search term will be stored here
FILE *inputFile; // creating a stream to read from .txt file
int i; // will be used later in a loop
while (1){ // Ask user for the name of the file until said file is opened for reading
printf("Enter the file name: ");
gets(fileName); // get string input from user that supports space characters (eg: "data.txt")
inputFile = fopen(fileName,"r"); // try opening file in read mode
if (inputFile != NULL){ //if the file has succesfully opened, then break from the loop
break;
}
printf("ERROR: The file %s could not be opened.\n",fileName); //if the file was not succesfully opened, then print appropriate error message
printf("Please verify that the file exists.\n");
}
int listLength=1; //will be used to dynamically allocate memory for scoreboard_table array (array of structs)
int curChar; // I figured that fgetc returns an integer value
while ((curChar=fgetc(inputFile))!=EOF){ //get a character until EOF
if (curChar=='\n'){ //if it's a newline character then we need to allocate more memory for scoreboard_table array
listLength++;
}
}
fclose(inputFile); // close the file as it's job is done
scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * (listLength)); // allocating enough memory to store the contents of .txt file
if (scoreboard_table == NULL){
printf("ERROR: There has been an error allocating memory for scoreboard table array.\n");
exit(1);
}
Load_Scoreboard_Table(fileName,scoreboard_table); //save the contents of file on scoreboard_table
Display_Scoreboard_Table(scoreboard_table,listLength);
while (1){
printf("Enter the name of the team (Exit - X, Sort -S): ");
gets(searchTerm);
i=0;
while (searchTerm[i]!='\0'){
searchTerm[i]=toupper(searchTerm[i]);
i++;
}
if (strcmp(searchTerm,"X")==0){
printf("Bye!\n");
free(scoreboard_table); //freeing memory allocated for scoreboard_table
return 0;
}
else if (strcmp(searchTerm,"S")==0){
printf("Sort by (G: games, P: points): ");
gets(searchTerm);
i=0;
while (searchTerm[i]!='\0'){
searchTerm[i]=toupper(searchTerm[i]);
i++;
}
if (strcmp(searchTerm,"G")==0){
interactive_board(scoreboard_table,listLength,1);
Display_Scoreboard_Table(scoreboard_table,listLength);
}
else if (strcmp(searchTerm,"P")==0){
interactive_board(scoreboard_table,listLength,2);
Display_Scoreboard_Table(scoreboard_table,listLength);
}
else{
printf("ERROR: Invalid input. There is no sort term for '%s'\n",searchTerm);
}
}
else{
Search(scoreboard_table,listLength,searchTerm);
}
}
}
void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
FILE *inputFile = fopen(fileName,"r"); // creating stream to read from file
if(inputFile == NULL ) { //checking again just in case there is a problem opening the file
printf("ERROR: The file %s could not be opened.\n",fileName);
exit(1);
}
int i=0,j,k;
//the loop below gets data from .txt file line by line until EOF and stores it in scoreboard_table array
while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) != EOF){
(scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
(scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
(scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
i++;
}
//the loop below replaces the '-' characters with ' ' in the name of every scoreboard_table array
for (j=0;j<i;j++){
for (k=0;k<40;k++){
if (*(((*(scoreboard_table+j)).name)+k) == '-' ){ //if the value of name[k] inside scoreboard_table[j] is equal to '-' character
*(((*(scoreboard_table+j)).name)+k) = ' '; //replace the value of scoreboard_table[j].name[k] to ' ' character
}
}
}
fclose(inputFile); // close the file as it's job is done
printf("Score records file has been successfully loaded!\n"); // notify the user that reading from the file has been successful
}
void Display_Scoreboard_Table(scoreboard *scoreboard_table,int size){
printf("\nTeam G WH LH WA LA Won Lost Points\n\n"); // the variables to be shown in table
int i;
for (i=0;i<size;i++){//for every element in scoreboard_table, print the variables stored
printf("%-40s%5d %5d %5d %5d %5d %5d %5d %5d\n",(scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
}
}
void Search(scoreboard *scoreboard_table, int size, char *searchTerm){ //search for name of team in scoreboard_table
int i,j; //i = index of scoreboard_table array, j = index of name array inside scoreboard_table array
char table_name[40]; // will be used to convert scoreboard_table->name to uppercase and store it
for (i=0;i<size;i++){ // for every element in scoreboard_table
for (j=0;j<40;j++){ // for every character in the name of scoreboard_table[i]->name
table_name[j]=toupper(*(((*(scoreboard_table+i)).name)+j)); //store the upper-case letter of scoreboard_table[i]->name[j] in table_name[j]
}
if (strcmp(table_name,searchTerm)==0){
//if the search term is equal to table_name (which is uppercase version of scoreboard_table[i]->name), then print the statistics and break from the loop.
printf("%s has %d win, %d lost and a total of %d points!\n",(scoreboard_table+i)->name,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
break;
}
else if(i==(size-1)){
// if it's the last element of scoreboard_table array and the search term is not equal to scoreboard_table[i]->name
// notify the user that their search term is not found in the scoreboard_table array
printf("That team is unknown! Please try again!\n");
}
}
}
void interactive_board(scoreboard *scoreboard_table, int size, int sort){
//this function sorts the scoreboard_table array using selection sort algorithm
/*
selection sort algorithm sorts an array by repeatedly finding the maximum element from unsorted part and putting it at the beginning.
*/
int i,j,index;
/*
i is used in a for loop to get ith element of scoreboard_table
j is used to determine when the sorting is complete
(ie: if you have a list containing 5 elements, you need to sort the array 4 times at most(in this case, which is selection sort algorithm);
therefore j is used in a for loop : for (j=0;j<(sizeofArray-1);j++)
j is also used to write into jth element of scoreboard_table
*/
int max; //store the max value here
scoreboard temp; //declare a struct named temp, will store temporary data when swapping variables of scoreboard_table array
if (sort==1){ // if sorting based on games
for (j=0;j<size-1;j++){ // explained above, iterate the code below (array) size-1 times
max=(scoreboard_table+size-1)->games; //set max to the last element of the array since this is the unsorted part of array...
index=size-1; //set index to index of last element of the array...
for (i=j;i<size;i++){ //no need to search elements with index less than j since they are already sorted
//therefore start searching elements from j till the last element
if (max<((scoreboard_table+i)->games)){
//if the value of current element > max, then the max value becomes this value and the index of the new max value is stored in index
max=(scoreboard_table+i)->games;
index=i;
}
if (i==(size-1)){ // swap the variables of scoreboard_table[index] with the variables of scoreboard_table[j]
//where j stands for the next unsorted member and index stands for the index of the largest variable
//copy contents of scoreboard_table[j] into temp (BACKUP)
strcpy(temp.name,(scoreboard_table+j)->name);
temp.games=(scoreboard_table+j)->games;
temp.losesAway=(scoreboard_table+j)->losesAway;
temp.losesHome=(scoreboard_table+j)->losesHome;
temp.losesTotal=(scoreboard_table+j)->losesTotal;
temp.totalPoints=(scoreboard_table+j)->totalPoints;
temp.winsAway=(scoreboard_table+j)->winsAway;
temp.winsHome=(scoreboard_table+j)->winsHome;
temp.winsTotal=(scoreboard_table+j)->winsTotal;
//copy contents of scoreboard_table[index] into scoreboard_table[j]
strcpy((scoreboard_table+j)->name,(scoreboard_table+index)->name);
(scoreboard_table+j)->games=(scoreboard_table+index)->games;
(scoreboard_table+j)->losesAway=(scoreboard_table+index)->losesAway;
(scoreboard_table+j)->losesHome=(scoreboard_table+index)->losesHome;
(scoreboard_table+j)->losesTotal=(scoreboard_table+index)->losesTotal;
(scoreboard_table+j)->totalPoints=(scoreboard_table+index)->totalPoints;
(scoreboard_table+j)->winsAway=(scoreboard_table+index)->winsAway;
(scoreboard_table+j)->winsHome=(scoreboard_table+index)->winsHome;
(scoreboard_table+j)->winsTotal=(scoreboard_table+index)->winsTotal;
//copy contents of temp (BACKUP) into scoreboard_table[index]
strcpy((scoreboard_table+index)->name,temp.name);
(scoreboard_table+index)->games=temp.games;
(scoreboard_table+index)->losesAway=temp.losesAway;
(scoreboard_table+index)->losesHome=temp.losesHome;
(scoreboard_table+index)->losesTotal=temp.losesTotal;
(scoreboard_table+index)->totalPoints=temp.totalPoints;
(scoreboard_table+index)->winsAway=temp.winsAway;
(scoreboard_table+index)->winsHome=temp.winsHome;
(scoreboard_table+index)->winsTotal=temp.winsTotal;
}
}
}
}
else{ // if sorting based on points
for (j=0;j<size-1;j++){ // explained above, iterate the code below (array) size-1 times
max=(scoreboard_table+size-1)->totalPoints; //set max to the last element of the array since this is the unsorted part of array...
index=size-1; //set index to index of last element of the array...
for (i=j;i<size;i++){ //no need to search elements with index less than j since they are already sorted
//therefore start searching elements from j till the last element
if (max<((scoreboard_table+i)->totalPoints)){
//if the value of current element > max, then the max value becomes this value and the index of the new max value is stored in index
max=(scoreboard_table+i)->totalPoints;
index=i;
}
if (i==(size-1)){ // swap the variables of scoreboard_table[index] with the variables of scoreboard_table[j]
//where j stands for the next unsorted member and index stands for the index of the largest variable
//copy contents of scoreboard_table[j] into temp (BACKUP)
strcpy(temp.name,(scoreboard_table+j)->name);
temp.games=(scoreboard_table+j)->games;
temp.losesAway=(scoreboard_table+j)->losesAway;
temp.losesHome=(scoreboard_table+j)->losesHome;
temp.losesTotal=(scoreboard_table+j)->losesTotal;
temp.totalPoints=(scoreboard_table+j)->totalPoints;
temp.winsAway=(scoreboard_table+j)->winsAway;
temp.winsHome=(scoreboard_table+j)->winsHome;
temp.winsTotal=(scoreboard_table+j)->winsTotal;
//copy contents of scoreboard_table[index] into scoreboard_table[j]
strcpy((scoreboard_table+j)->name,(scoreboard_table+index)->name);
(scoreboard_table+j)->games=(scoreboard_table+index)->games;
(scoreboard_table+j)->losesAway=(scoreboard_table+index)->losesAway;
(scoreboard_table+j)->losesHome=(scoreboard_table+index)->losesHome;
(scoreboard_table+j)->losesTotal=(scoreboard_table+index)->losesTotal;
(scoreboard_table+j)->totalPoints=(scoreboard_table+index)->totalPoints;
(scoreboard_table+j)->winsAway=(scoreboard_table+index)->winsAway;
(scoreboard_table+j)->winsHome=(scoreboard_table+index)->winsHome;
(scoreboard_table+j)->winsTotal=(scoreboard_table+index)->winsTotal;
//copy contents of temp (BACKUP) into scoreboard_table[index]
strcpy((scoreboard_table+index)->name,temp.name);
(scoreboard_table+index)->games=temp.games;
(scoreboard_table+index)->losesAway=temp.losesAway;
(scoreboard_table+index)->losesHome=temp.losesHome;
(scoreboard_table+index)->losesTotal=temp.losesTotal;
(scoreboard_table+index)->totalPoints=temp.totalPoints;
(scoreboard_table+index)->winsAway=temp.winsAway;
(scoreboard_table+index)->winsHome=temp.winsHome;
(scoreboard_table+index)->winsTotal=temp.winsTotal;
}
}
}
}
}
you have lot of problems in your code like.
Firstly, use fgets() instead of gets(). for e.g
fgets(fileName,sizeof(fileName),stdin);
Secondly, name is pointer member of scoreboard, allocate memory for it first. for e.g
scoreboard_table->name = malloc(SIZE); /* define SIZE */
Thirdly, fgetc() return type is int. check the manual page of fgetc(). So char curChar; should be int curChar;
Finally, in fscanf() while storing integers you need to provide the & address to each argument. for e.g
fscanf(inputFile,"%d",&(scoreboard_table+i)->games)
I try to explain in the comments. Here is the sample code
void Load_Scoreboard_Table(char *, scoreboard *);
int main(void){
char fileName[40], *ret = NULL;
FILE *inputFile;
while (1){
printf("Enter the file name> ");
/* make sure fileName gets correctly stored in buffer as expected */
ret = fgets(fileName,sizeof(fileName),stdin); /* use fgets() instead of gets() */
if(ret == NULL) { /* if failed, check again */
continue;
}
else {
printf("%s",ret); /* if fgets() result is as expected, control comes here */
fileName[strlen(fileName)-1] ='\0';
}
inputFile = fopen(fileName,"r");
if (inputFile != NULL){
break;
}
printf("ERROR: The file %s could not be opened.\n",fileName);
printf("Please verify that the file exists.\n");
}
int listLength=0;
int curChar; /*return type of fgetc() is int */
while ((curChar=fgetc(inputFile))!=EOF){
if (curChar=='\n'){
listLength++;
}
}
fclose(inputFile);
scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * listLength);/* no need to cast the result of malloc() */
scoreboard_table->name = malloc(100);/*name is pointer member, allocate memory for it. must */
Load_Scoreboard_Table(fileName,scoreboard_table);
/* don't forget to free dynamically allocated memory here #TODO */
return 0;
}
void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
FILE *inputFile = fopen(fileName,"r");
if(inputFile == NULL ) {
/* some mesage,, error handling #TODO*/
}
int i=0;
while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) > 0){
(scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
(scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
(scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
i++;
}
for(int j =0 ;j<i;j++) {
printf("%d %d %d \n",(scoreboard_table+j)->winsTotal,(scoreboard_table+j)->losesTotal,(scoreboard_table+j)->totalPoints);
}
}
From man 3 gets Why one shouldn't use gets() reason is here.
Never use gets(). Because it is impossible to tell without knowing
the data in advance how many characters gets() will read,
and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has
been used to break computer security. Use fgets() instead.
Pay special attention to contents of your fscanf(). Addresses of int variables have to be passed it's the one of crashing reason of the code.
while (fscanf(inputFile, "%s %d %d %d %d %d\n",
(scoreboard_table+i)->name, &(scoreboard_table+i)->games,
&(scoreboard_table+i)->winsHome, &(scoreboard_table+i)->losesHome,
&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway)!=EOF){
Moreover, you should give ear to the other comments like not using gets()
char fileName[40], *p;
fgets(fileName, sizeof fileName, stdin);
if ((p = strchr(fileName, '\n')) != NULL) {
*p = '\0'; /* remove newline */
}
By the way, an allocated memory is needed for char *name in the struct, it's the another reason for crashing, and not forget to free it.

Struct Memory Allocation from File in C, only two variables work

I have to write a program that will read text from a file, break it up into a struct, validate the sections to a certain criteria, then produce two new files; one with the clean data and one with the errors. So far i am up to the stage of breaking up the data from a file and storing it into a struct but it will only work for the first two variables.
the text is separated by colons and i need to put each section into the variables bellow
an example of the text file
0001:0002:0003:0021:CLS
here is my struct
struct packet{
int source;
int destination;
int type;
int port;
char data[50];
};
Bellow is whatworks fine, however as soon as i add another section to add data to the type variable, the program does not work.
fscanf(inFile, "%[^:]: %[^:]:", records[i].source, records[i].destination);
printf("%d - %s _ %s", i+1, records[i].source, records[i].destination);
However this does not work and i need it to. Well i need to expand upon it.
fscanf(inFile, "%[^:]: %[^:]: %[^:]:", records[i].source, records[i].destination, records[i].type);
printf("%d - %s _ %s _ %s", i+1, records[i].source, records[i].destination, records[i].type);
}
if i printf without inputting anything to the struct it displays null as i would expect because nothing is being stored so im thinking that there is something wrong with the fscanf function. As it works for the first two, i dont think that it is a syntax issue so it must be a memory issue. I have used malloc and realloc but ive gotten confused with it and im sure that i have not done it right.
Full Code Listing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//declaration of function which will print my name and student number
const char * myname();
//declaration of a function that will prompt a user to enter a file and open it if it exists
int openfile();
struct packet{
int source;
int destination;
int type;
int port;
char data[50];
};
int main()
{
int recordCount = 0;
struct packet *records;
records =malloc(sizeof(struct packet));
// printing the my name and student number via the myname function
printf("%s\n", myname());
//executing the openfile function that will open a function
openfile(recordCount, records);
return 0;
}
const char * myname()
{
const char *x = "*************************\nUSERNAME\nUSER NUMBER\nCONTACT NUMBER\n*************************\n";
return x;
}
int openfile(int rCount, struct packet *records)
{
//file pointer which will keep track of the file being accessed
FILE *inFile ;
//creating variable that will hold what the user has entered for a filename to open
char inFileName[100] = { '\0'};
printf("Please Enter the File to open:");
//getting the users input and storing it into the variable just created
scanf("%s", inFileName);
//if the file does not exist, display an appropriate error message
if ((inFile = fopen(inFileName, "r")) == NULL)
{
printf("Cannot Open File **%s**\n", inFileName) ;
exit(1) ;
}
else {
//if the file does exist, process the data
while(fgets(inFileName, 100, inFile)!=NULL)
{
int i =0;
for (i=0; i<30;i++)
{
fscanf(inFile, "%[^:]: %[^:]: %[^:]:", records[i].source, records[i].destination, records[i].type);
printf("%d - %s _ %s _ %s", i+1, records[i].source, records[i].destination, records[i].type);
}
}
//close the file
fclose(inFile);
return 0;
}
};
You're doing it wrong:
fscanf(inFile, "%[^:]: %[^:]:", records[i].source, records[i].destination);
The %[] conversion specifier is for string, but you're passing the values of integers as if they were character pointers. Undefined behavior!
You should be getting heaps of warnings for this from any modern compiler, i.e. one that validates formatting strings.
There's no point in parsing integers as if they were strings, I don't understand why you're not just doing
fscanf(inFile, "%d:%d", &records[i].source, &records.destination);
for the first case.
Also, do note that it's much better to read in whole lines using fgets(), then parsing the line once read using sscanf(), than trying to combine the two steps with fscanf().
Last, you should check the return value of the conversion call to know how many conversion succeeded.

Passing fscanf to struct

I'm trying to open a file and pass to struct, I'm using fscanf() with a loop, but it only saves one the struct the last read:
Imagine a file:
JR John Rambo 24353432
JL John Lennon 6435463
I'm using this code:
typedef struct people{
char code[10];
char name[100];
long telephone;
}PEOPLE;
int read(PEOPLE people[], int n_p){
char temp;
FILE *fp;
fp=fopen("example.txt","r");
if(fp==NULL){
printf("Error\n");
return -1;
}
while(!feof(fp)){
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].name,
&people[n_p].telephone);
}
}
The Problem is that he only saves the last line of the file...Should I do a if cicle??
Another question is how can I separate a similar file but with ";"
First of all, you are scanning for 3 strings (%s) and one int (%d) when you pass only 3 parameters in your fscanf(). You could add a char first_name[50]; in your struct and then do:
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].first_name,
people[n_p].name, &people[n_p].telephone);
You always fscanf() the file until you have nothing more to read (due to the !feof(fp) because of the while. So in the last people[n_p] variable the last line of the file will be saved.
You could remove the while from read() and also add the FILE * as a parameter to the function so that you don't open the file each time you call read().
Something like this maybe:
main()
{
FILE* fp = fopen("example.txt", "r");
int i = 0;
while (!feof(fp)) {
read(people, i, fp);
i++;
}
}
int read(PEOPLE people[], int n_p, FILE* fp){
char temp;
if(fp==NULL){
printf("Error\n");
return -1;
}
fscanf(fp,"%s %s %s %d\n", people[n_p].code,people[n_p].first_name,
people[n_p].name, &people[n_p].telephone);
}
For using the ; as a separator you can change fscanf() to this:
fscanf(fp, "%[^;]; %[^;]; %d\n", people[n_p].code,people[n_p].name,
&people[n_p].telephone);
EDIT I wrote the above code which can be found here and it works fine with this example.txt file as input.
It looks like you're not changing the n_p variable. You need some sort of variable to keep track of which index of the people[] array you're updating.
Additionally, hopefully you've got a large enough people array to hold all the entries in the file.

Resources