2015-05-03 2 views
0

Итак, я читаю файл txt и сохраняю каждый элемент новой строкой в ​​массив строк. Единственная проблема: мне нужно изменить размер этого массива на 5, когда он близок к заполнению.Создайте динамический массив строк, который будет масштабироваться при заполнении

Input выглядит примерно так, за исключением того, много больше

CSE 1104 
CSE 1105 
CSE 1310 
CSE 2320 
IE 2308 
PHYS 1443 
MATH 1426 

Вот мой код

void printFileError(char *s) { 
    printf("unable to open %s\n", s); 
    exit(1); 
} 

void reallocTaken(char **taken, int *size, int newSize) { 
    (*size) = newSize; 
    taken = realloc(taken, (*size) * sizeof(char *)); 
    printf("Realocateding---- \n"); 
} 

int main(int argc, char *argv[]) { 
    char **coursesTaken; 
    int coursesTakenSize = 5; 

    int i; 

    char *filePlan, *fileMyCourses; 
    FILE *fp; 

    /* Open the file of completed courses */ 
    if((fp = fopen(argv[2], "r")) != NULL) { 
     char buffer[255]; 
     int lineCount = 0; 

     coursesTaken = malloc(sizeof(char *) * coursesTakenSize); 

     while(fgets(buffer, sizeof(buffer), fp) != NULL) { 
      char token[] = "\n"; 
      char *split = strtok(buffer, token); 

      while(split != NULL) { 

       /* Check if array is full */ 
       if((lineCount + 1) == coursesTakenSize) { 
        printf("Needs to allocate \n"); 
        /* Realoc Memory */ 
        reallocTaken(coursesTaken, &coursesTakenSize, coursesTakenSize + 5); 
       } 

       coursesTaken[lineCount] = malloc((sizeof(split) + 1) * sizeof(char)); 
       strcpy(coursesTaken[lineCount], split); 

       printf("%s\n", split); 

       lineCount++; 
       split = strtok(NULL, token); 
      } 
     } 

     /* Cut out exessive memory */ 
     reallocTaken(coursesTaken, &coursesTakenSize, lineCount); 

     printf("Line Count: %d\n", lineCount); 
     printf("Size: %d\n", coursesTakenSize); 
     printf("Final Size: %lu\n", sizeof(coursesTaken)); 
     fclose(fp); 
    } else { 
     printFileError(argv[2]); 
    } 

    for(i = 0; i < coursesTakenSize; i++) { 
     printf("%d:\t%s\n", i+1, coursesTaken[i]); 
    } 

    return 0; 
} 

План здесь был первым выделить 5 слотов памяти, и когда количество строк становится равным размеру, добавляет к нему еще 5 слотов. После того, как файл будет выполнен, измените размер всего объекта на количество строк. В то же время выделите каждый индекс массива, заполните его данными из текстового файла.

код успешно перераспределяет первые два блока, а затем выдает ошибку

a.out(9410,0x7fff7f20a300) malloc: *** error for object 0x7fcb9b404bb0: pointer being realloc'd was not allocated 

, что здесь происходит

CSE 1104 
CSE 1105 
CSE 1310 
CSE 2320 
Needs to allocate 
Realocateding---- 
IE 2308 
PHYS 1443 
MATH 1426 
MATH 1302 
MATH 1323 
Needs to allocate 

Я заметил, комментируя coursesTaken[lineCount] = malloc((sizeof(split) + 1) * sizeof(char)) программа полностью не выполняется до конца, когда печать каждый

Я не очень уверен, что здесь происходит.

+0

Вы ищете 'realloc()'. –

+0

@iharob Да, я использую это, нужно ли мне использовать это для выделения каждой строки? – cameronmoreau

ответ

1

Вы делаете путаницы между sizeof, который может дать размер одного элемента, из структуры, или массив, размер которого известен и strlen, который дает Len нуль-завершающим нулем.

Линия coursesTaken[lineCount] = malloc((sizeof(split) + 1) * sizeof(char)), действительно является виновником. Как и в следующей строке, вы копируете split в то, что вам нужно, чтобы он мог содержать все символы в split плюс завершающий нуль.

Но, как split является char *, sizeof(split) является размер указателя (то есть, например, 4 в системе на 32 бита, и 8 на 64 один).

Вы должны написать эту строку:

coursesTaken[lineCount] = malloc((strlen(split) + 1) * sizeof(char)); 
1

Вы хотите:

void reallocTaken(char ***taken, int *size, int newSize) { 
    (*size) = newSize; 
    *taken = realloc(*taken, (*size) * sizeof(char *)); 
    printf("Realocateding---- \n"); 
} 

и назвать его так:

reallocTaken(&coursesTaken, &coursesTakenSize, coursesTakenSize + 5); 

В исходном коде, вы теряете указатель к перераспределенному пространству, назначив его taken вместо *taken и в вместо этого продолжайте использовать указатель на оригинал, в этот момент освобожденное пространство. Принцип такой же, как тот, который вы правильно применили к courseTakenSize.

При повторном перераспределении этого исходного указателя появляется следующая ошибка.

Смежные вопросы