An array of structures in c: gives all strings the same values ​​(with int, int works well). What can I do?

When I run the program and assign the values ​​id, name, surname, it gives them all the value of the last student. For example, if the last student's name is Anna, then all other array names are Anna. It works well with grades! I tried and didn't use the "constructor" function and had the same thing.

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


struct Student{     /*struct for student info*/
    char *id;
    char *name;
    char *surname;
    int grade;
};


struct Student* Student_new(char* id, char* name, char* surname, int grade); 
/*fuction: Student 'constructor'*/


int main(int argc, char *argv[]) {

int no; /*number of students*/
printf("Welcome! \n\nNumber of students: ");
scanf("%d", &no);

struct Student *studentArray[no]; /*arary of struct students*/

int i; /*counter*/
for(i=0; i<no; i++){

    char id[10], name[10], surname[10];
    int grade;

    printf("\n\nStudent(%d)\n", i+1);
    printf("id: ");
    scanf("%s", id);
    printf("name: ");
    scanf("%s", name);
    printf("surname: ");
    scanf("%s", surname);
    printf("grade: ");
    scanf("%d", &grade);


    studentArray[i] = Student_new(id, name, surname, grade); /*using Student 
    'constructor' to initialize the array*/
}



for(i=0; i<no; i++){
    printf("%s  %s %s %d \n", studentArray[i]->id, studentArray[i]-
    >name, studentArray[i]->surname, studentArray[i]->grade);
}

    return 0;
}


struct Student* Student_new(char* id, char* name, char* surname, int grade) 
{ 

      struct Student* st = malloc(sizeof(struct Student));
      st->id = id;
      st->name = name;
      st->surname = surname;
      st->grade = grade;
      return st;
}

      

PLEASE, HELP!

+3


source to share


3 answers


The problem is that the loop variables go out of scope after each iteration and you are left with dangling pointers in the instances Student

. What you see is the result of undefined behavior .

What is probably happening is that the same char array is passed to every student instance. Then you modify the same char array, overwriting the previous values.



You will need to make copies of the lines. Don't forget to create a function like Student_free

where you free

dynamically allocated copies.

struct Student* Student_new(char* id, char* name, char* surname, int grade) 
{ 

    struct Student* st = malloc(sizeof(struct Student));
    st->id = strndup(id, 10);
    st->name = strndup(name, 10);
    st->surname = strndup(surname, 10);
    st->grade = grade;
    return st;
}

      

+5


source


You must reserve memory for string attributes. As a hint, use a structure similar to:

#define MAX_LEN 32

struct Student{     /*struct for student info*/
    char id[MAX_LEN];
    char name[MAX_LEN];
    char surname[MAX_LEN];
    int grade;
};

      



Determine MAX_LEN

to something sensible for you and make sure the values ​​entered are no longer used. Also make sure the strcpy

input values ​​for the structure variables.

+2


source


The student structure only contains pointers to char arrays. Now the actual space in memory for strings is allocated in your loop, and its lifetime is limited to the scope of the for loop, after which it is accessed by undefined. In your case, the space in which the strings have not been reused and redefined, so you might accidentally keep the last value (such cases can also cause a segmentation fault).

You should take a look at some basic tutorial on pointers and memory models c. Allocating arrays in a structure is a good solution ( nucleon answer ). Also, the scanf function can overflow, you should limit the number of characters received according to the size of the allocated array.

+2


source







All Articles