Reading file into structure (c)

  • (2 Pages)
  • +
  • 1
  • 2

16 Replies - 850 Views - Last Post: 13 January 2017 - 12:25 PM Rate Topic: -----

#1 gbrl378  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 27-May 15

Reading file into structure (c)

Posted 11 January 2017 - 08:34 AM

Hello,
In my code I am trying to read a text file which includes student id, name, grades etc. into a structure. My program is supposed to calculate the average grade and letter grade for each student. But in the first place, my program cannot even read the file. Can you help?

int main()
{

   struct person
{
    char name;
    char surname;
    int id;
    float quiz1;
    float quiz2;
    float midterm1;
    float midterm2;
    float hw;
    float fin;
    float ave;
    char letter;
}students[100];

   FILE *fptr;
   fptr = fopen("C:\\grades.txt","r");
   int i;
   do{
   fscanf(fptr, "%d,%c,%c,%f,%f,%f,%f,%f,%f", &students[i].id, &students[i].name, &students[i].surname, &students[i].quiz1, &students[i].quiz2, &students[i].midterm1, &students[i].midterm2, &students[i].hw, &students[i].fin);
   i++;
   }while(feof(fptr)==0);
   fclose(fptr);

   for(i=0; i<80; i++){
    students[i].ave=((students[i].quiz1)*10+(students[i].quiz2)*10+(students[i].midterm1)*15+(students[i].midterm2)*15+(students[i].hw)*10+(students[i].fin)*40)/100;
   }
    printf(" Id is: %f \n", students[0].id);
}



Text file:

00160004005 name surname 51 71 82 76 94.1 74
00160004009 name2 surname2 85 77 68 78 85.9 69
...(x80)

Is This A Good Question/Topic? 0
  • +

Replies To: Reading file into structure (c)

#2 jimblumberg  Icon User is offline

  • member icon

Reputation: 5245
  • View blog
  • Posts: 16,297
  • Joined: 25-December 09

Re: Reading file into structure (c)

Posted 11 January 2017 - 08:41 AM

After a very quick look at your code and your text file I see several problems.

First it looks like you're using incorrect data types for the type of variables you want to read from the file. For example your id, name, and surname should all be strings not an int or single characters.

Jim
Was This Post Helpful? 1
  • +
  • -

#3 gbrl378  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 27-May 15

Re: Reading file into structure (c)

Posted 11 January 2017 - 09:58 AM

Hello,
Thank you. I can understand name and surnames being strings, but why can't it hold id as integer?

However, I fixed them the way you suggested but still not working.

This post has been edited by Skydiver: 11 January 2017 - 12:02 PM
Reason for edit:: Removed unnecessary quote. No need to quote the post above yours.

Was This Post Helpful? 0
  • +
  • -

#4 jimblumberg  Icon User is offline

  • member icon

Reputation: 5245
  • View blog
  • Posts: 16,297
  • Joined: 25-December 09

Re: Reading file into structure (c)

Posted 11 January 2017 - 10:18 AM

Quote

but why can't it hold id as integer?

Look at your id: "00160004005", if you use an integer you will loose those leading zeros, and remember an int has a fixed size and you could overflow the integer with your "id" because of it's length. Not all "numbers" should be treated like numbers.

Quote

However, I fixed them the way you suggested but still not working.

Not much to go on here. Perhaps you could tell me why it't not working, and post the modified code?? If you're getting compile warnings or errors please post the complete error/warning messages (all of them) exactly as they appear in your development environment.

Jim

This post has been edited by jimblumberg: 11 January 2017 - 10:19 AM

Was This Post Helpful? 2
  • +
  • -

#5 gbrl378  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 27-May 15

Re: Reading file into structure (c)

Posted 11 January 2017 - 10:26 AM

Oh I see what you mean. But I don't mind losing the zeros since it won't really affect the program. After I posted my last reply, I realized something, I think I am making a big mistake scanning the strings. Do I have to scan every character one by one or is there an easy way that I can do this?


#include <stdio.h>
#include <stdlib.h>
//void writetofie(FILE *fptr, struct student){


//}
int main()
{

   struct person
{
    char name[15];
    char surname[15];
    int id;
    float quiz1;
    float quiz2;
    float midterm1;
    float midterm2;
    float hw;
    float fin;
    float ave;
    char letter;
}students[100];

   FILE *fptr;
   fptr = fopen("C:\\grades.txt","r");
   int i;
   do{
   fscanf(fptr, "%d,%c,%c,%f,%f,%f,%f,%f,%f", &students[i].id, &students[i].name, &students[i].surname, &students[i].quiz1, &students[i].quiz2, &students[i].midterm1, &students[i].midterm2, &students[i].hw, &students[i].fin);
   i++;
   }while(feof(fptr)==0);
   fclose(fptr);

   for(i=0; i<80; i++){
    students[i].ave=((students[i].quiz1)*10+(students[i].quiz2)*10+(students[i].midterm1)*15+(students[i].midterm2)*15+(students[i].hw)*10+(students[i].fin)*40)/100;
   }
    printf(" Id is: %f \n", students[0].id);
}


This post has been edited by Skydiver: 11 January 2017 - 12:01 PM
Reason for edit:: Removed unnecessary quote. No need to quote the post above yours.

Was This Post Helpful? 0
  • +
  • -

#6 jimblumberg  Icon User is offline

  • member icon

Reputation: 5245
  • View blog
  • Posts: 16,297
  • Joined: 25-December 09

Re: Reading file into structure (c)

Posted 11 January 2017 - 10:47 AM

Quote

Oh I see what you mean. But I don't mind losing the zeros since it won't really affect the program.

Even if loosing the zeros are not a big concern the possible overflowing of your int is a big concern. What happens if your id is "99999999999" are you sure that this value will fit into an int? (Answer = no)

Quote

I think I am making a big mistake scanning the strings.

Yes, so it seems.

Quote

Do I have to scan every character one by one or is there an easy way that I can do this?

Yes there is, have you looked at any documentation for the fscanf() function? There are several different format specifiers available perhaps you should be looking for something that handles strings instead of single characters.

By the way you should be getting several warnings that need to be fixed!
main.c||In function ‘main’:|
main.c|29|warning: format ‘%c’ expects argument of type ‘char *’, but argument 4 has type ‘char (*)[15]’ [-Wformat=]|
main.c|29|warning: format ‘%c’ expects argument of type ‘char *’, but argument 5 has type ‘char (*)[15]’ [-Wformat=]|
main.c|37|warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=]|
||=== Build finished: 0 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|


When working with the scanf() series of functions you need to be very careful to match the format specifier with the type otherwise you invoke undefined behavior (a very dangerous place to be).


Jim
Was This Post Helpful? 1
  • +
  • -

#7 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 5725
  • View blog
  • Posts: 19,336
  • Joined: 05-May 12

Re: Reading file into structure (c)

Posted 11 January 2017 - 12:01 PM

gbrl378: There is no need to quote the post directly above yours. Just use the big Reply button or the Fast reply area. If you do want to quote, focus on just specific things like Jim has done.
Was This Post Helpful? 0
  • +
  • -

#8 gbrl378  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 27-May 15

Re: Reading file into structure (c)

Posted 12 January 2017 - 09:05 AM

Hello,
Right now I am not getting an error but when I run the program it says "main.exe has stopped working". Can you give it a look?

int main()
{

   struct person
{
    char name[15];
    char surname[15];
    long id;
    float quiz1;
    float quiz2;
    float midterm1;
    float midterm2;
    float hw;
    float fin;
    float ave;
    char letter;
}students[100];

   FILE *fptr;
   fptr = fopen("C:\\grades.txt","r");
   int i;
   do{
   fscanf(fptr, "%ld,%s,%s,%f,%f,%f,%f,%f,%f", &students[i].id, students[i].name, students[i].surname, &students[i].quiz1, &students[i].quiz2, &students[i].midterm1, &students[i].midterm2, &students[i].hw, &students[i].fin);
   i++;
   }while(!feof(fptr));
   fclose(fptr);

   for(i=0; i<80; i++){
    students[i].ave=((students[i].quiz1)*10+(students[i].quiz2)*10+(students[i].midterm1)*15+(students[i].midterm2)*15+(students[i].hw)*10+(students[i].fin)*40)/100;
   }
    printf(" Id is: %ld \n", students[0].id);
}


Was This Post Helpful? 0
  • +
  • -

#9 jimblumberg  Icon User is offline

  • member icon

Reputation: 5245
  • View blog
  • Posts: 16,297
  • Joined: 25-December 09

Re: Reading file into structure (c)

Posted 12 January 2017 - 11:20 AM

Look closely at your input file format:
00160004005 name surname 51 71 82 76 94.1 74 

Now look at your fscanf() call:
 fscanf(fptr, "%ld,%s,%s,%f,%f,%f,%f,%f,%f",&students[i].id

Do you see all of those commas in your format specifier? When you put any character in a format specifier those characters must also exist in the stream. Since they don't exist in your file the fscanf() call will fail. You really should be testing the return value of this fscanf() call to insure that all the values are properly read and you should remove all the commas from the format specifier.

int status = fscanf(fptr, "%ld%s%s%f%f%f%f%f%f", &students[i].id, ...
if(status != 8)
{
   fprintf(stderr, "Failed to read line %d properly.\n", i);

return(0);
}

The cause of your "crash" is probably being caused by these lines. You never initialize i so it has an undefined value.
   int i;
   do{
...
   i++;


Also some other notes about your code. First the structure really should be moved outside of main() and you should also do something about all of those very long lines. Second I also recommend using a while() loop instead of a do/while() loop, a while() loop usually makes following the logic of the program easier, and you really should avoid using EOF to control your data entry loop.


Third and probably most important never Never NEVER use a function that retrieves C-strings that doesn't restrict the number of characters that will be retrieved to reduce the chances of buffer overflow errors. The scanf() series of functions have an optional width specifier that can be used for this purpose, but don't forget to leave room for the end of string character that this function will always place in the string.

#include <stdio.h>
#include <stdlib.h>

struct person
{
    char name[15];
    char surname[15];
    char id[20];
    float quiz1;
    float quiz2;
    float midterm1;
    float midterm2;
    float hw;
    float fin;
    float ave;
    char letter;
};

int main()
{
    struct person students[100];

    FILE *fptr = fopen("C:\\grades.txt", "r");
    int i;
    int status;
    int line_count = 0;  // Use a more descriptive name for the line counter, note the initialization.
    while((status = fscanf(fptr, "%19s%14s%14s%f%f%f%f%f%f",
                           students[line_count].id,
                           students[line_count].name,
                           students[line_count].surname,
                           &students[line_count].quiz1,
                           &students[line_count].quiz2,
                           &students[line_count].midterm1,
                           &students[line_count].midterm2,
                           &students[i].hw,
                           &students[i].fin)) == 9)
    {
        line_count++;
    }

    fclose(fptr);
    // status should be EOF because you reached the End Of File, any other
    // value means that one of the lines failed to read properly.
    if(status != EOF)
    {  
        fprintf(stderr, "Failed to read line number %d\n", line_count);
        return(1);
    }

    //for(i = 0; i < 80; i++) // Why the 80? Did you read 80 lines?
    for(i = 0; i < line_count; ++i)
    {
        students[i].ave = ((students[i].quiz1) * 10 +
                           (students[i].quiz2) * 10 +
                           (students[i].midterm1) * 15 +
                           (students[i].midterm2) * 15 +
                           (students[i].hw) * 10 +
                           (students[i].fin) * 40) / 100;
    }

    printf(" Id is: %s \n", students[0].id);
}



Jim
Was This Post Helpful? 1
  • +
  • -

#10 gbrl378  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 27-May 15

Re: Reading file into structure (c)

Posted 12 January 2017 - 11:49 AM

Thank you so much Jim. That was really helpful. One more thing, I just completed my program and this is the whole code:

#include <stdio.h>
#include <stdlib.h>
void writetofile(FILE *cfptr, struct person *students){

   while(!feof(cfptr)){
   fprintf(cfptr, "%s %s %s %f %c\n", students.id, students.name, students.surname, students.ave, students.letter);
   }
   fclose(cfptr);

    }

struct person
{
    char name[15];
    char surname[15];
    char id[20];
    float quiz1;
    float quiz2;
    float midterm1;
    float midterm2;
    float hw;
    float fin;
    float ave;
    char letter;
};

int main()
{
    struct person students[100];

    FILE *fptr = fopen("C:\\grades.txt", "r");
    int i;
    int status;
    int line_count = 0;
    while((status = fscanf(fptr, "%19s%14s%14s%f%f%f%f%f%f",
                           students[line_count].id,
                           students[line_count].name,
                           students[line_count].surname,
                           &students[line_count].quiz1,
                           &students[line_count].quiz2,
                           &students[line_count].midterm1,
                           &students[line_count].midterm2,
                           &students[i].hw,
                           &students[i].fin)) == 9)
    {
        line_count++;
    }

    fclose(fptr);

    if(status != EOF)
    {
        fprintf(stderr, "Failed to read line number %d\n", line_count);
        return(1);
    }


    for(i = 0; i < line_count; ++i)
    {
        students[i].ave = ((students[i].quiz1) * 10 +
                           (students[i].quiz2) * 10 +
                           (students[i].midterm1) * 15 +
                           (students[i].midterm2) * 15 +
                           (students[i].hw) * 10 +
                           (students[i].fin) * 40) / 100;
    }

    printf(" Id is: %s \n", students[0].id);

    for(i=0; i<line_count; i++){

        if(students[i].ave>85){

           strcpy( students[i].letter, "A");

           }
        if(students[i].ave>70 && students[i].ave<85){

           strcpy( students[i].letter, "B");

           }

           if(students[i].ave>55 && students[i].ave<70){

           strcpy( students[i].letter, "C");

           }

           if(students[i].ave>40 && students[i].ave<55){

           strcpy( students[i].letter, "D");

           }

           else{

           strcpy( students[i].letter, "F");

           }

    }

    FILE *cfptr1;
   cfptr1 = fopen("pass.txt","w");

   FILE *cfptr2;
   cfptr2 = fopen("fail.txt","w");

    for(i=0; i<line_count; i++){

        if(students[i].ave>40){

            writetofile(cfptr1,&students[i]);
        }

        else{

            writetofile(cfptr2,&students[i]);
        }
    }
}



And it gives me these errors:

main.c|6|error: request for member 'name' in something not a structure or union


Same goes for name, surname, id...

I don't understand why this is happening. Am I missing something?
Was This Post Helpful? 0
  • +
  • -

#11 jimblumberg  Icon User is offline

  • member icon

Reputation: 5245
  • View blog
  • Posts: 16,297
  • Joined: 25-December 09

Re: Reading file into structure (c)

Posted 12 January 2017 - 12:27 PM

You need to move your function implementation below the structure definition.

Also look at this snippet:
    char letter;
};

int main()
{
 ...

        if(students[i].ave>85){

           strcpy( students[i].letter, "A");

 ...


Since letter is a single character you can't use strcpy() since strcpy only works with C-strings. All you need to do is assign a value.

students[i].letter = 'A'



Jim
Was This Post Helpful? 1
  • +
  • -

#12 gbrl378  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 27-May 15

Re: Reading file into structure (c)

Posted 12 January 2017 - 01:07 PM

I just did the changes you said.

Quote

You need to move your function implementation below the structure definition.


However, it still gives me the same error even after I moved it below.
Was This Post Helpful? 0
  • +
  • -

#13 jimblumberg  Icon User is offline

  • member icon

Reputation: 5245
  • View blog
  • Posts: 16,297
  • Joined: 25-December 09

Re: Reading file into structure (c)

Posted 12 January 2017 - 02:31 PM

Look at this snippet:
void writetofile(FILE *cfptr, struct person *students){

   while(!feof(cfptr)){
   fprintf(cfptr, "%s %s %s %f %c\n", students.id, students.name, students.surname, students.ave, students.letter);
   }
   fclose(cfptr);

    }


When will the file ever reach the end of file? (Hint: Never). What is the purpose of that loop, you appear to be passing a single person to this function not the array, so why are you trying print multiple students?

Why are you passing students by pointer instead of just a "normal single instance.

This function should probably start more like:

void writeofile(FILE *outFile, struct person student)
{
   ...
}



Also in future please post the complete error messages, all of them, exactly as they appear in your development environment. These messages have important information embedded within them to aid in locating and fixing the problems.

By the way there may have been a couple of omissions in my "code", you need to make sure you're using the proper index variable for all of the items in your loops.

Jim
Was This Post Helpful? 1
  • +
  • -

#14 gbrl378  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 27-May 15

Re: Reading file into structure (c)

Posted 13 January 2017 - 10:25 AM

Thanks. I fixed the problems. Also I realized I was not scanning the values in the first place.

My final code:(but again main.exe stopped working error)

#include <stdio.h>
#include <stdlib.h>


struct person
{
    char name[15];
    char surname[15];
    char id[20];
    float quiz1;
    float quiz2;
    float midterm1;
    float midterm2;
    float hw;
    float fin;
    float ave;
    char letter;
};

void writetofile(FILE *cfptr, struct person students){


   fprintf(cfptr, "%s %s %s %f %c\n", students.id, students.name, students.surname, students.ave, students.letter);


    }
int main()
{
    struct person students[100];

    FILE *fptr = fopen("C:\\grades.txt", "r");

int i;
    int status;
    int line_count = 0;

    while(!feof(fptr)){

 fscanf(fptr, "%19s%14s%14s%f%f%f%f%f%f",
                           students[line_count].id,
                           students[line_count].name,
                           students[line_count].surname,
                           &students[line_count].quiz1,
                           &students[line_count].quiz2,
                           &students[line_count].midterm1,
                           &students[line_count].midterm2,
                           &students[line_count].hw,
                           &students[line_count].fin);
    while((status = fscanf(fptr, "%19s%14s%14s%f%f%f%f%f%f",
                           students[line_count].id,
                           students[line_count].name,
                           students[line_count].surname,
                           &students[line_count].quiz1,
                           &students[line_count].quiz2,
                           &students[line_count].midterm1,
                           &students[line_count].midterm2,
                           &students[line_count].hw,
                           &students[line_count].fin)) == 9)
    {
        line_count++;
    }}

    fclose(fptr);
    if(status != EOF)
    {
        fprintf(stderr, "Failed to read line number %d\n", line_count);
        return(1);
    }

    for(i = 0; i < line_count; ++i)
    {
        students[i].ave = ((students[i].quiz1) * 10 +
                           (students[i].quiz2) * 10 +
                           (students[i].midterm1) * 15 +
                           (students[i].midterm2) * 15 +
                           (students[i].hw) * 10 +
                           (students[i].fin) * 40) / 100;
    }


    for(i=0; i<line_count; i++){

        if(students[i].ave>85){

           students[i].letter="A";

           }
        if(students[i].ave>70 && students[i].ave<85){

           students[i].letter="B";

           }

           if(students[i].ave>55 && students[i].ave<70){

           students[i].letter="C";

           }

           if(students[i].ave>40 && students[i].ave<55){

           students[i].letter="D";

           }

           else{

           students[i].letter="F";

           }

    }

    FILE *cfptr1;
   cfptr1 = fopen("pass.txt","w");

   FILE *cfptr2;
   cfptr2 = fopen("fail.txt","w");

    for(i=0; i<line_count; i++){

        if(students[i].ave>40){

            writetofile(cfptr1,students[i]);
        }

        else{

            writetofile(cfptr2,students[i]);
        }
    }

      fclose(cfptr1);
    fclose(cfptr2);



}


Was This Post Helpful? 0
  • +
  • -

#15 gbrl378  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 27-May 15

Re: Reading file into structure (c)

Posted 13 January 2017 - 10:37 AM

Process returned -1073741819 (0xC0000005) execution time : 11.952 s
Press any key to continue.

Warnings:

||=== Build file: "no target" in "no project" (compiler: unknown) ===|
.c||In function 'main':|
.c|85|warning: assignment makes integer from pointer without a cast [enabled by default]|
.c|90|warning: assignment makes integer from pointer without a cast [enabled by default]|
.c|96|warning: assignment makes integer from pointer without a cast [enabled by default]|
.c|102|warning: assignment makes integer from pointer without a cast [enabled by default]|
.c|108|warning: assignment makes integer from pointer without a cast [enabled by default]|
||=== Build finished: 0 error(s), 5 warning(s) (0 minute(s), 1 second(s)) ===|


Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2