0

I was tasked as an assignment to build a function to build an array of students and hold some values using a linked list. The task is to take some info from a txt file about said students, building said a university struct type which will hold an array of students and printing the info on a new txt file, now the max characters in the student string name can be 99 but must be dynamic allocated after giving the name length. All the other variables like integer values and characters are moved successfully but when is all done the string name in all the students just disappear upon (Changes to "Invalid characters in string as soon as I use the university struct) entering a different function.

The structs

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

typedef struct stud
{
    char* name;
    int long ID;
    float mtmGrade;
    char gradesStr[6];
    char approved;
    struct stud* next;
}stud;

typedef struct uni
{
    stud* studentsArray;
    int studentNum;
}uni;

void studentInput(uni* university, stud* students, FILE* in);

Main


void main()
{
    FILE* in, * out;
    uni* Uni = (uni*)malloc(sizeof(uni));
    stud* students = NULL;

    in = fopen("input.txt", "rt");
    if (!in) Error_Msg("File not found!");
    out = fopen("output.txt", "w");
    if (!out) Error_Msg("File not found!");

    Uni->studentsArray = (stud*)malloc(sizeof(stud));  // FREE THIS
    studentInput(Uni, students, in);

    fclose(in);
    fclose(out);

}

The function

void studentInput(uni* university, stud* students, FILE* in)
{
    stud* temp;
    char maxName[99];
    university->studentNum = 0;

    while (feof(in) == 0)
    {
        university->studentsArray = (stud*)realloc(university->studentsArray, sizeof(stud));
        university->studentNum++;
        temp = (stud*)malloc(sizeof(stud));
        // Name input //
        fscanf(in, "%s", maxName);
        temp->name = (char*)malloc((strlen(maxName) + 1) * sizeof(char));
        if (!(temp->name)) Error_Msg("Not enough memory found");
        temp->name = maxName;
        // ID and matam grade input //
        fscanf(in, "%d%f%s", &temp->ID, &temp->mtmGrade,temp->gradesStr);

        temp->next = students;
        students = temp;
    }

    university->studentsArray = students;
}
Tommy Mei
  • 13
  • 2
  • 1
    You will want to start with [**Why is while ( !feof (file) ) always wrong?**](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong) You need to do more than warn on an allocation failure, e.g. `if (!(temp->name)) Error_Msg("Not enough memory found");` You also need to add the *field-width* modifier to `%s` (e.g. `%5s`) in `fscanf(in, "%d%f%s", &temp->ID, &temp->mtmGrade,temp->gradesStr);` to protect your array bounds. – David C. Rankin May 07 '20 at 01:41
  • 1
    `temp->name = maxName` -> `strcpy(temp->name, maxName)` – kaylum May 07 '20 at 01:44
  • If you are not in a *freestanding environment* (no OS), `void main()` is wrong. – David C. Rankin May 07 '20 at 01:47

1 Answers1

0

Please notice maxName is a local variable in function studentInput, it's only valid inside the function. After:

temp->name = maxName;

temp->name will point to the local memory, and the content may be modified after the function exit.

So, you can use strcpy or strdup instead:

void studentInput(uni* university, stud* students, FILE* in)
{
    stud* temp;
    char maxName[99];
    university->studentNum = 0;

    while (feof(in) == 0)
    {
        university->studentsArray = (stud*)realloc(university->studentsArray, sizeof(stud));
        university->studentNum++;
        temp = (stud*)malloc(sizeof(stud));
        // Name input //
        fscanf(in, "%s", maxName);
        temp->name = strdup(maxName);

        if (!(temp->name)) Error_Msg("Not enough memory found");

        // ID and matam grade input //
        fscanf(in, "%d%f%s", &temp->ID, &temp->mtmGrade,temp->gradesStr);

        temp->next = students;
        students = temp;
    }

    university->studentsArray = students;
}

P.S.

use

int main()

better conforms to the C standard than

void main()
tgarm
  • 473
  • 3
  • 8