Click here to Skip to main content
15,884,099 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello guys
I'm trying to make an array of structure in a way that i dont know the wanted size.
My goal is to take all the information from a text file and put each line in different structure.
i thought about using realloc in a while loop and if i didnt got to the end of file i will realloc one more structure.
I need help in the function "InputData".
Thanks in advance
C++

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

typedef struct
{
    char name[100];
    int** grades[2];

}student;

void Error_Msg(char*);
int InputData(student **,FILE*);
void OutputData(int,student*,FILE*);

int main()
{
    FILE *fp;
    student * arr;
    int size;

    if(!(fp=fopen("Students.txt","r")))
          Error_Msg("The input file is wrong");
    size = InputData(&arr,fp);
    
    fclose(fp);
    if(!(fp=fopen("Students.txt","w")))
        Error_Msg("The output file is wrong");
    OutputData(size,arr,fp);
    fclose(fp);
    return 0;
}


int InputData(student ** p_array, FILE * fp){
 student * temp = *p_array;
 int i=1;

 temp = (student*)malloc(sizeof(student));
 while(fscanf(fp,"%s %d %d %d",temp[i-1].name,&temp[i-1].grades[0],&temp[i-1].grades[1],&temp[i-1].grades[2])!=EOF)
 {
     temp = (student*)realloc(sizeof(student)*1);
     i++;
 }

 return i-1;
}
Posted
Comments
pasztorpisti 12-Aug-13 12:42pm    
BTW, realloc() receives two parameters, how do you compile this: temp = (student*)realloc(sizeof(student)*1);. And beware, realloc() has platform dependent behavior when size is zero. Some platforms do not release the memory block in this case (that is really stupid).

Something like this might do the trick for you;

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

typedef struct {
    char name[100];
    int gradeA;
    int gradeB;
    int gradeC;

} student;

student* read_student(FILE* file) {
    student* s = (student*)malloc(sizeof(student));

    if (fscanf(file,"%s %d %d %d", &s->name, &s->gradeA, &s->gradeB, &s->gradeC) != EOF) {
        return s;
    }
    else {
        free(s);
        return NULL;
    }
}

void print_student(student* s) {
    printf("%s %d %d %d\r\n", s->name, s->gradeA, s->gradeB, s->gradeC);
}

int main() {
    FILE* file = fopen("C:\\Temp\\grades.txt", "r");

    student* s = NULL;
    student** students;
    int count = 0;
    while((s = read_student(file))) {
        student** new_students = (student**)malloc(sizeof(student) * (count + 1));
        for(int i = 0; i < count; ++i) {
            new_students[i] = students[i];
        }

        new_students[count] = s;
        free(students);
        students = new_students;
        ++count;
    }

    fclose(file);

    for(int i = 0; i < count; ++i) {
        print_student(students[i]);
    }

    return 0;
}


Instead of realloc I've just dumped the old list and created a new every time.
I would recommend using a some form of linked list structure to track each student read instead.

Hope this helps,
Fredrik
 
Share this answer
 
v2
Comments
idobry 12-Aug-13 10:54am    
Thank you very much, i hope i could use it because i'm not supposed to modify most of the script
Fredrik Bornander 12-Aug-13 11:08am    
Cool. Note that I updated the example as the first attempt was leaking memory.
idobry 12-Aug-13 11:05am    
How this line " student* s = (student*)malloc(sizeof(student)); " helps?
How many space dose it allocate?
Fredrik Bornander 12-Aug-13 11:07am    
It allocates enough space for one.
Maciej Los 12-Aug-13 17:10pm    
+5!
Realloc is expensive operation, so calling it on each line would be more expensive then simply read the file twice: one time for counting the number of lines, the second time for reading those lines.

[EDIT #1]

Even better solution would be the one involving the change in file format. It's always a good idea to write some metadata part at the very beginning of all files. Among other things (what is that files for, what applications are used to write and/or read it), is should inform on the number of records.

On alternative approach would be using non-text (binary) mode of read/write, when records can have the same size.

[EDIT #2]

I failed to mention that the solution based on metadata is only better when the file is written programmatically. Please see the comment by pasztorpisti below.

—SA
 
Share this answer
 
v3
Comments
idobry 12-Aug-13 10:52am    
Ok, good point i'll give it a try
Sergey Alexandrovich Kryukov 12-Aug-13 11:21am    
Will you accept this answer formally (green button)?
—SA
pasztorpisti 12-Aug-13 12:39pm    
5ed. Sometimes things like this (pre-setting capacity for containers) may seem stupid (especially if it requires seemingly a lot of work) but can help not only in avoiding lot of reallocs and copying of exisiting items but it avoiding memory fragmentation. I really don't understand why someone gave a one but he has no clue about memory management for sure.
Another technique is preallocating a very large block that is an upper bound of the number of items that follow and later setting the block size to smaller. This can be more effective with custom allocators and it requires a known upper bound on the number of items.
Sergey Alexandrovich Kryukov 12-Aug-13 12:48pm    
Exactly. Thank you very much.
By the way, the file is usually buffered well enough to avoid physical addressing of hard drive sectors and redundant physical reads; even if it happens, it happens much less times than the number of reallocations, so it it would be "almost" equivalent to reading the file once. The file may be not closed by file pointer could be rewind to zero position after first read...
—SA
pasztorpisti 12-Aug-13 12:58pm    
You are right, today ram is very cheap. Windows does caching with more hundred megs and more gigs if possible. One of my workmates told me a tale about he watching film at home: after some time the media player starts playing with periodic stalls. According to him windows caches the film file so aggressively that it swaps out some parts the player itself... A restart+seek solves the problem. I didn't ask about the windows versions and the methods he used to find this out but if this is true it proves that windows file caching is quite aggressive. :-)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900