1

I am learning structs and I am still little confused about them and what they do. The code I have is my attempt of it and I keep getting segmentation faults. My goal for the main is to ask the user to see how many students they want to add, and each information for name and score while calling a function. I also want to print the data array off to the user.

  • For the loadStudentData() function, I want to store the newName and NewScore into the newStudent Structure.

  • For printStudentData() I want to print data for a single student

  • Then for the printStudentArray() I want to call printStudentData() function on each member for the students array.

My code is:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STUDENT_NAME_LENGTH 20

typedef struct{
char* name;
int score;
}Student;

void loadStudentData(Student *newStudent,char* newName,int newScore);
int printStudentData(Student student);
void printStudentArray(Student* students, int numStudents);


/*
 *
 */
int main(int argc, char** argv) {
int numberOfStudents;
Student *newStudent;
char* newName;
int newScore;
int student;


Student students[numberOfStudents];

printf("how many students: ");
scanf("%d", &numberOfStudents);


    loadStudentData(newStudent, newName, newScore);

    printStudentArray(students, numberOfStudents);


  return (EXIT_SUCCESS);
}

void loadStudentData( Student *newStudent, char* newName, int newScore){
 int i;
    char *studentName = (char *) malloc(STUDENT_NAME_LENGTH *  sizeof(char));
    scanf("%s", studentName);
    newStudent->name = studentName;

    int nScore;
    scanf("%d", &nScore);
    newStudent[i].score = newScore;
  }
 int printStudentData(Student student){

int i;

    printf("Student name\t%s\n",) ;
    printf("Student score\t%d\n",);

     }



 void printStudentArray(Student* students, int numStudents){
 int i;
for (i = 0; i < numStudents; i++) {
    printf("Student name\t%s\n", students[i].name);

    printf("Student score\t%d\n", students[i].score);
   } 
   }
Haris
  • 12,120
  • 6
  • 43
  • 70
Eli Yolts
  • 19
  • 3

3 Answers3

0
  • Point 1: Student students[numberOfStudents]; is invalid, as numberOfStudents is uninitialized.

  • Point 2: In your code, you're calling printStudentArray() before populating student itself.

    This function tries to access the uninitialized memory at name variable which causes undefined behaviour.

  • Point 3: In your loadStudentData() function, you're using i uninitialized . Again UB.

That said,

  1. Always check for success of malloc() before using the retuned pointer.
  2. Please do not cast the return value of malloc() and family in C.
Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • student[numberofstudents], will never work, cos numberofstudents needs to be determined at compile time. The OP needs to malloc/calloc the student array and subsequently free it before exit. – phil Jun 17 '15 at 08:19
  • @rhubarbdog is it? I'm interested. Please tell me how. (FWIW, I referred [this](http://en.wikipedia.org/wiki/Variable-length_array)). And is that the reason for the downvote? :-) – Sourav Ghosh Jun 17 '15 at 08:48
  • C doesn't have variable length arrays like that wiki discusses. At present all that statement will do is create a fixed length array of zero elements, hence you can store nothing. In c you either measure, allocate the space use it and free it. Or start with something, start populating growing (realloc) and populating, make it smaller if required, use then and finally when done free. I cannot stress you must free all memory you acquire via calloc,malloc or realloc otherwise it's a memory leak – phil Jun 17 '15 at 09:06
  • `C doesn't have variable length arrays like that wiki discusses.`.. did you consider `C99` also? :-) – Sourav Ghosh Jun 17 '15 at 09:07
  • 1
    C is the language. Things like C99 and C11 are standards. Point 4... Never cast the address returned by malloc, look it up on SO for the rationale – phil Jun 17 '15 at 09:14
  • @rhubarbdog ok then, **(1)** what are standards for, if not establishing the specifications for language? **(2)** did you miss the last line of my answer? – Sourav Ghosh Jun 17 '15 at 09:16
  • Sorry, did miss the last line of your post, my bad. I know why I never considered that tweak to C. Ages ago when I was new to C after completing my first major program. I did quite a lot of reading man pages and similar relating to C etc. That's when I learned of this new kinda cool feature of C99. My introduction to this concept was don't use in production code because... I don't remember the rationale so subsequently have never considered it a language feature. I had the opportunity to start using c over 20 years ago, so come from a cleaner 3GL background I don't use long jump, or continue – phil Jun 17 '15 at 18:38
  • They produce unprovable code. Avoid goto except how it's used in kernel standard programing. Goto is also unprovable, but limitations of c mean this is best practice and I can construct a proof for such code. Consider this, prototype struct bar foo(int arg); is perfectly valid to return a structure. But again rationale forgotten, K & R stated best practice is prototype void foo(struct bar *return_value, int arg); having the caller supply the storage for return value *ALWAYS* works. C11 formally revoked variable length arrays. It's now 15, so C11 is probably the standard to aim at. – phil Jun 17 '15 at 18:50
  • sorry for my verbose reposted comments. I have trouble with the app on my phone. And yes it is rhubarbdog, I use this name on many forums it's not an anonymous alias to hide behind. ((normal face)) – phil Jun 17 '15 at 18:56
0

You call printStudentArray before you actually initialize the array of structures. That means all the data in the array will be indeterminate and using it in any way except to initialize it will lead to undefined behavior (which is a common cause of crashes).

More specifically, the problem is probably when you try to print the name, as the name pointer could point anywhere.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

You seem to not allocate the structs you are creating. Be aware that when you declare a variable such as Student *newStudent; you first have to allocate it. Because thus far, you have only declared a variable that holds a pointer to a Student struct, but this pointer points to nowhere. So use the malloc function everywhere you expect a valid pointer:

newStudent = malloc(sizeof(newStudent));

Philipp Murry
  • 1,660
  • 9
  • 13