0

I've been studying some C on my own and I was wondering if my segmentation fault is do to the way I'm trying to add *person to a dynamic array named students. This originally started out as a method for me trying to learn how to use dynamic arrays but I got stumped with how I am failing to get around this scanf faulting my program. I included everything I've done, but I suspect my problem is within the main, specifically the scanf.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//ARR_LEN 
#define ARR_LEN 5
#define STR_LEN 15
//STUDENT STRUCT
typedef struct{
  int ID;
  char *name;
}Student;

typedef struct{
  Student *array;
  size_t used;
  size_t size;
}Array;

void initArray(Array *a, size_t initialSize){
  //ALLOCATING INITIAL SPACE
  a->array = (Student *)malloc(initialSize * sizeof(Student));

  a->used = 0;
  a->size = initialSize;

  //INITIALIZES ALL VALUES OF THE ARRAY TO 0
  for(unsigned int i = 0; i<initialSize; i++){
    memset(&a->array[i],0,sizeof(Student));
  }
}

  //ADDING A STUDENT ELEMENT INTO ARRAY
void insertArray(Array *a,Student element){
  if(a->used == a->size){
    a->size *= 2;
    a->array = (Student *)realloc(a->array,a->size * sizeof(Student));
  }

//Copy Name
a->array[a->used].name = (char*)malloc(strlen(element.name) + 1);
strcpy(a->array[a->used].name, element.name);

//Copy ID
a->array[a->used].ID=element.ID;


a->used++;
}

void freeArray(Array *a){
 for(int i=0;i<a->used;i++){
    free(a->array[0].name);
    a->array[0].name=NULL;
 }

//Freeing the array
 free(a->array);
 a->array = NULL;

 a->used = 0;
 a->size = 0;
}




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

char choice;
Array student;
Student *person;
char* firstName;
firstName = (char *)malloc(100*sizeof(char));
int* number;
 number = (int *)malloc(10*sizeof(int));
printf("Would you like to make a list of people? (y/n): ");
scanf("%c \n",&choice);
    while(choice == 'y'){
        initArray(&student, 5);
        printf("\nPlease enter students name: ");
        scanf("%s \n",&firstName);
                printf("NAME ENTERED: %s\n",firstName);
//      fgets(firstName,100,stdin);
        printf("\nPlease enter students ID: ");
        scanf("%i \n",number);
//      fgets(number,100,stdin);
                    for(int i = 0; i<ARR_LEN;i++){
                person->name = firstName;
                person->ID = (int)number;
                        insertArray(&student,*person);
                printf("Would you like to add another? (y/n): \n");
            }
    }   
printf("Would you like to print the list of people? (y/n): ");
scanf("%c \n",&choice);
    if(choice == 'y'){
        for(int x=0;x<sizeof(student);x++){
            printf("Name: %s", student.array[x].name);
        }       
    }
}

Now to give credit where its due. I grabbed the overall Dynamic Array scheme from "Casablanca" and was seeing if I could use it to overall understand how the Array was built. His/Her post can be found here: C dynamically growing array

Community
  • 1
  • 1
Genesis
  • 159
  • 13
  • you don't use `scanf("%c \n")` or something like this, just go `scanf("%c", &c)` and the rest are similar. note no space trailing. and another tip about `//Copy Name`, is to use `strdup`, which is one line call while does everything for you. then remember to check the return value of `malloc` and `realloc`, `strdup` as well. – Jason Hu Mar 23 '15 at 20:41
  • 1
    `scanf("%s \n",&firstName)` shoule be `scanf("%[^\n]%*c",firstName)`. – Jason Hu Mar 23 '15 at 20:43
  • Thanks, these three things cleared up everything. You guys are amazing. – Genesis Mar 23 '15 at 20:49

1 Answers1

0

There is a bug is here:

void freeArray(Array *a){
    for(int i=0;i<a->used;i++){
        free(a->array[0].name);
        a->array[0].name=NULL;
    }
    ...
}

You repeatedly free the first element, but since you set it to NULL, subsequent calls to free() just do nothing. The other element names never get freed.

Change this code to:

void freeArray(Array *a) {
    for(int i = 0; i < a->used; i++) {
        free(a->array[i].name);
        a->array[i].name = NULL;
    }
    ...
}

There is another problem here:

   scanf("%s \n",&firstName);

You do not limit the intput size. This may cause a buffer overflow if the user enters a long name. Use this instead:

   scanf("%99s \n",&firstName);

A more major bug here:

    Student *person;
    ...
    for (int i = 0; i<ARR_LEN;i++) {
        person->name = firstName;
        person->ID = (int)number;
        insertArray(&student,*person);
        ...

person should be a structure, not a pointer:

    Student person;
    ...
    for (int i = 0; i<ARR_LEN;i++) {
        person.name = firstName;
        person.ID = (int)number;
        insertArray(&student, person);
        ...

Another bad one here:

    for(int x=0;x<sizeof(student);x++){
        printf("Name: %s", student.array[x].name);
    }       

You loop over sizeof(student) elements instead of student.used.

Use this instead:

    for (int x = 0; x < student.used; x++){
        printf("Name: %s\n", student.array[x].name);
    }       

There many more problems in the code: for example, you do not handle out of memory conditions.

chqrlie
  • 131,814
  • 10
  • 121
  • 189