John Potts
John Potts

Reputation: 11

String Element of Struct not retaining assigned value

I'm having a bit of a bizarre issue with C.

I have a .c file implementing a structure, and another using it. The structure in question is basic info about a student (name and grade). The Implementation file has the functions

the main file goes as follows:

int main (void){
    char inBuff[30];
    char* name = NULL;
    int grade;
    Student Stu;

    printf("main: Please enter the name\n");
    fgets(inBuff, 30, stdin);
    name = malloc((sizeof(char)+1)*strlen(inBuff));
    strncpy (name, inBuff, 20);

    printf("main: Please enter the grade\n");
    scanf("%d", &grade);

    InitializeStudent (name, grade, &Stu);

    /*value testing*/
    printf("main: %s\n", Stu.name);
    printf("main: %d\n", Stu.grade);

    printf ("main: The student's name is %s\n", NameOfStudent(Stu));
    printf ("main: The student's grade is %d\n", GradeOfStudent(Stu));

    FreeStudent(&Stu);
    free (name);
    return 0;
}

printf() statements in the InitializeStudent() function seem to show the values being assigned correctly. However, both Stu.name and NameOfStudent(Stu) return ASCII, and Stu.Grade and GradeOfStudent(Stu) return 2675716 (which seems to be a memory address) regardless of input.

Of note is the fact that it has been specified that NameOfStudent() and GradeOfStudent() be pass-by-value rather than using a pointer (ie a copy of the struct should be made and passed in to the functions) and have char* and int return types respectively, whereas InitializeStudent() is passed a pointer and is a void function.

Also possibly important, the name field of Student is initialized as

char name[20];

rather than

char* name;

the Student struct definition is as follows:

#define MAXNAMESIZE 20
typedef struct {
    char name[MAXNAMESIZE];
    int grade;
} Student;

as requested, the code for initialize student is as follows

void InitializeStudent (char *name, int grade, Student *S) {
    printf ("InitializeStudent: entered initialization\n");
    int i = 0;
    S = malloc (sizeof(Student));
    for (i = 0; i< strlen(name); i++)
        if (name[i] == '\n')
            name[i] = '\0';
    strncpy(S->name, name, 20);
    S->grade = grade;

    printf ("InitializeStudent: %s\n", S->name);
    printf ("InitializeStudent: %d\n", S->grade);
}

Upvotes: 1

Views: 1516

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409432

The problem is that you allocate the Student structure in the InitializeStudent function, when you pass it a pointer to an already allocated structure.

And because arguments are passed by value (i.e. copied) to functions, the pointer S is a copy, so when you assign to it you only assign to your local copy in the function. That is why the structure in the main function is not initialized, because you only initialize the structure you allocate in the InitializeStudent function, not the one you pass in.

And lastly, be careful with strncpy as if the source string is longer than the length you pass to it, then the function will not add the string terminator.


Oh and by the way, there is a simpler way of removing the newline from fgets: Just "remove" the last character:

/* If `name` is not a `NULL` pointer, and the length is larger than zero
 * and the last character is a newline...
 */
if (name != NULL && strlen(name) > 0 && name[strlen(name) - 1] == '\n')
    name[strlen(name) - 1] = '\0';

Upvotes: 2

Related Questions