0
typedef struct school_ {
    char *name;
    char *state;
} School;

Above is the struct format I am required to use to store data from a file in the format

name, state

name2, state2

Below I was given a declaration of an array of pointers and the second line is how the function is called.

School *TOP100[school_size];

input_schools(school_info,TOP100,school_size);

In my function I need to store a dynamic string as the name for each of 100 schools.

I've written the following, however have gotten a seg fault. How can I change my function without changing the code above?

void input_schools(FILE *IN, School **Sch, int k) {
    printf("in input_schools() ... \n\n\n");

    int i, j = 0;
    char ch;

    for (i = 0; i < k; i++) {
        fscanf(IN, "%c", &ch);
        Sch[i]->name = (char *) malloc(sizeof (char));
        j = 0;
        Sch[i]->name[j] = ch;

        while (ch != ',') {
            fscanf(IN, "%c", &ch);
            j++;
            Sch[i]->name = (char *) realloc(Sch[i]->name, sizeof(char) * (j + 1));
            Sch[i]->name[j] = ch;
        }
        Sch[i]->name[j - 1] = '\0';
    }

    return;
}

While this code compiles it returns a seg fault.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • 1
    where does it segfault? have you tried debugging it? also format the new lines for the readers better please. – Bwebb Nov 13 '18 at 22:05
  • Welcome to Stack Overflow! [don't cast malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Barmar Nov 13 '18 at 22:19
  • 1
    `Sch[i]->name[j - 1] = '\0';` is wrong. You're replacing the 2nd-to-last character in the name with a null byte. You should be adding the null byte *after* the last character. But you need to `realloc()` first to make room for this. – Barmar Nov 13 '18 at 22:23
  • 1
    `TOP100` is an array of pointers. Did you ever allocate memory for each element to point to? – Barmar Nov 13 '18 at 22:25
  • Although this code misplaces the string terminators, that does mean that it avoids overrunning the bounds of the not-large-enough array, so that doesn't explain the segfault. Unless you have an empty name (no characters before the comma), in which case it tries to write before the start of the array. – John Bollinger Nov 13 '18 at 22:26
  • 1
    There's nothing here that will cause a segfault, unless there's a school with a 1-character name. The problem is most likely in the code that calls it. I'll bet you forgot to allocate memory for the school objects. – Barmar Nov 13 '18 at 22:26

1 Answers1

0

I think the easier way is to use the C library to your advantage. I don't have your input file, but this should work or at least get you a lot closer:

void input_schools(FILE *IN, School **Sch, int school_size)
{
  printf("in input_schools() ... \n\n\n");

  char *name;
  char *state;
  char *line;
  size_t line_len;

  for(int i=0; i<school_size; ++i) {
    line = NULL;
    line_len=0;

    // get line: line will contain a newly-allocated string
    // that holds a single line from the file
    if(-1 == getline(&line, &line_len, IN)) {
      // end of file reached
      break;
    }

    // make a new school
    Sch[i] = (School*)malloc(sizeof(School));

    // allocate storage for the name and state
    name = malloc(line_len); // we know that line_len is >= the size of the name
    state = malloc(line_len); // we know that line_len is >= the size of the state

    // everything before the = is the name, everything after is the state
    sscanf(line, "%[^=]s = %[^=]s", name, state);

    // free the memory getline() allocated
    free(line);

    Sch[i]->name = name;
    Sch[i]->state = state;
  } // end for all possible schools
} // end input_schools
Clay
  • 1,159
  • 1
  • 9
  • 20