Karim13
Karim13

Reputation: 23

How to edit structure values after passing them c

Hello guys i just want to read the students from a file and then ask the user to add a new student but first I have to add it to my structur and I don't really kmow how to edite or add students to my allocated structure. Please learn me how to send the values of my struct to any other function and edite them..

struct student {
    char personnummer[11];
    char förnamn[11];
    char efternamn[10];
    char gender[7];
    char programmdife[20];
    char age[4];
    char email[30];
    //struct likaprogramms *likaprogramm;
} *personer;

void f(struct student **x)
{
    char str[200];
    int j=0;
    struct student *personer = (struct student*)malloc(j * sizeof(struct student));
    FILE* f;
    f = fopen("elever.txt", "r");

    while (fgets(str,sizeof str, f)!=NULL )
    {
        sscanf(str,"%10s %9s %9s %6s %19s %3s %29s", personer[j].personnummer,personer[j].förnamn, personer[j].efternamn, personer[j].gender, personer[j].programmdife, personer[j].age, personer[j].email);
        printf("%10s %9s %9s %6s %19s %3s %29s\n", personer[j].personnummer,personer[j].förnamn, personer[j].efternamn, personer[j].gender, personer[j].programmdife, personer[j].age, personer[j].email);
        j++;
        *x=personer;
    }

    fclose(f);
    //free(personer);
}

int i;
int main()
{
    getchar();
    printf("skriv ny personnummret\n");
    getchar();
    fgets(personer->personnummer,11,stdin);
    printf("skriv förnamn\n");
    getchar();
    fgets(personer->förnamn,50,stdin);
    printf("skriv gender\n");
    fgets(personer->gender,20,stdin);
    printf("skriv programm\n");
    fgets(personer->programmdife,50,stdin);
    printf("skriv ålder\n");
    getchar();
    fgets(personer->age,4,stdin);
    printf("skriv email\n");
    getchar();
    fgets(personer->email,40,stdin);
    // printf("%s %s %s %s %s %s %s", personnummer,förnamn,efternamn,gender,programm,age,email);

    return 0;
}

Upvotes: 0

Views: 65

Answers (1)

Sinic
Sinic

Reputation: 358

As already stated in the comments your malloc will return either NULL or a valid pointer to a buffer of 0 bytes, because j is 0 when malloc is called.
No matter which happens, your code will write to invalid memory.

Then i would strongly recommend to enable warnings (gcc/clang: -W -Wall -Wextra).

One possible solution would be to set *x = NULL at the start of your function and use realloc to increase the buffer blockwise in the while loop.

In this case the caller has to make sure to use free on the memory if it is not used anymore.

Something like this:

const int block_size = 16;
int num_allocated = 0;
*x = NULL;
while (your_condition)
{
    if (num_allocated <= j)
    {
        struct student *new_ptr = realloc(*x, (sizeof(struct student) * num_allocated) + (sizeof(struct student) * block_size));
        if (new_ptr == NULL)
        {
            // realloc failed, but ptr is still valid (or NULL if the first call to realloc failed)
            return num_allocated;
        }
        *x = new_ptr;
        num_allocated += block_size;
    }

    // use *x as array of struct student here and fill it
    // for every filled element j has to be increased
}

return number of (usable) elements

You can adjust the blocksize for your needs.

If you do not want to waste memory you can also shrink the buffer at the end to the really needed size:

struct student *new_ptr = realloc(*x, sizeof(struct student) * num_allocated);
if (new_ptr == NULL)
    return j;
*x = new_ptr;
return j;

Upvotes: 1

Related Questions