2017-02-13 4 views
0

Точка этого назначения должна считываться в строке из файла, содержащего городское состояние, за которым следуют две строки, которые содержат координаты широты и долготы. Затем нам нужно динамически выделять структуры точно так, как они написаны ниже, чтобы сохранить эти координаты. Наконец, мы экспортируем ориентиры в формат KML, используемый Google Earth.Realloc массив структур, которые содержат указатели на указатели с динамическим размером

На этом этапе я могу правильно написать KML из своих структур. Однако это заняло пару грязных для петель в моей функции grow_whole (см. Ниже). Проблема в том, что я освобождаю все выделенные указатели позже. (Поверьте мне, он существует, плохо вставьте его в порядке ниже). Я уверен, что проблема заключается в коррупции кучи. Однако я работал слишком долго, и я чувствую, что это может быть проще.

Формат файла. (Существуют как 150 из них.)

city, state 
40 30 N 
40 20 W 

Wholesome_t просто контейнер, который будет содержать информацию о количестве знаковых структур, а также указателе на первый ориентир. Landmark_t содержит указатели на символы, которые выделяются с таким количеством пространства, в котором они нуждаются, чтобы содержать их разное имя города и т. Д.

struct landmark_t { 
char *city; 
char *state; 
char *country; 
float longitude; 
float latitude; 
}; 

struct wholesome_t { 
struct landmark_t *landmarks; 
int landcount; 
int landmax; 
}; 

Ниже приведен фрагмент кода, который обрабатывает строки считывания и отправляет их в правильный синтаксический анализатор.

Первоначально здоровым является malloc'd, а указатель ориентиров установлен в NULL. Затем мы malloc-пространство для 2 ориентирных структур и начинаем цикл while ниже.

struct landmark_t *land = NULL; 
int coorflag = 0; 
int flagcount = 0; 
//Parse lines 
while(fgets(buf, LEN, in)){ 
    //Does that thing where we realloc 
    if(whole->landcount == whole->landmax){ 
     grow_whole(whole); 
    } 

    //remove trailing newline 
    buf[strcspn(buf, "\n")] = 0; 

    if(!coorflag){//Check to see if we are on a flag or coordinate 
     //set land to be the pointer to our next empty landmark struct 
     land = whole->landmarks + (sizeof(struct landmark_t) * whole->landcount); 
     set_city_state_country(buf, land); 
     coorflag = 1; //Set flag to get a coordinate line next 
    }else{//We are on a coordinate line which will use 
      //the same land struct pointer as above 
     if(!flagcount){//Have we seen a coordinate line already? 
      land->latitude = number_muncher(buf); 
      flagcount = 1; 
     }else{//We have seen a coordinate line 
      land->longitude = number_muncher(buf); 
      //We are done filling this structure. Reset flags and move to the next. 
      flagcount = 0; 
      coorflag = 0; 
      whole->landcount++; 
     } 
    } 
} 

Проблема в grow_whole. Раньше у меня была проблема, когда после запуска realloc первая наземная структура будет содержать правильно назначенные указатели, но что-нибудь после нее, пока где-нибудь ближе к концу файла все указатели на город, штат и страну, а также долготу и широту будут изгнан. Я добавил циклы for, которые сохраняют все наши указатели до массивов до того, как мы повторно выберем, а затем перепишем эти указатели обратно в правильную структуру.

void grow_whole(struct wholesome_t *whole) 
{ 
//First collect all of the pointers inside our current landmark structs. 
struct landmark_t *land = NULL; 
char *city[whole->landcount]; 
char *state[whole->landcount]; 
char *country[whole->landcount]; 
float longitude[whole->landcount]; 
float latitude[whole->landcount]; 
for (int i = 0; i < whole->landcount; i++){ 
    land = whole->landmarks + (sizeof(struct landmark_t) * i); 
    city[i] = land->city; 
    state[i] = land->state; 
    country[i] = land->country; 
    longitude[i] = land->longitude; 
    latitude[i] = land->latitude; 
} 
land = realloc(whole->landmarks, (GROW + whole->landmax) * sizeof(struct landmark_t)); 
if(land == NULL){ 
    printf("Error in grow_whole.\n"); 
    return; 
}else{whole->landmarks = land;} 
//Update landmax to represent aftergrow. 
whole->landmax = GROW + whole->landmax; 
//Refill all of the re allocated structs with their pointers. 
for (int i = 0; i < whole->landcount; i++){ 
    land = whole->landmarks + (sizeof(struct landmark_t) * i); 
    land->city = city[i]; 
    land->state = state[i]; 
    land->country = country[i]; 
    land->longitude = longitude[i]; 
    land->latitude = latitude[i]; 
} 
//Fill two new structs with blank data. 
for(int i = whole->landcount; i < whole->landmax; i++){ 
    land = whole->landmarks + (sizeof(struct landmark_t) * i); 
    empty_fill(land); 
} 
return; 
} 

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

fclose(in); 
char *s = argv[1]; 
s = strtok(s, "."); 
s = strncat(s, ".kml", 4); 
FILE *out = fopen(s, "w"); 
//Finally done lets write some KML 
kml_begin(out); 
for (int i=0; i < whole->landcount; i++){ 
    land = whole->landmarks + (sizeof(struct landmark_t) * i); 
    kml_placemark(out, i, land); 
} 
kml_end(out); 
fclose(out); 
tea_party(whole);//free land 
free(whole->landmarks); 
free(whole); 

который получает в kml_end (уходит). (Я знаю, потому что я правильно отформатирован с правильными значениями .kml file) Но во время чаепития я получаю seg_fault.

void tea_party(struct wholesome_t *whole) 
{ 
    struct landmark_t *land = NULL; 
    for (int i = 0; i < whole->landcount; i++){ 
     land = whole->landmarks + (sizeof(struct landmark_t) * i); 
     printf("here\n"); 
     free(land->city); 
     printf("here2\n"); 
     free(land->state); 
     printf("here3\n"); 
     free(land->country); 
    } 
return; 
} 

Это происходит для нашей второй ориентирной структуры.

land = whole->landmarks + sizeof(struct landmark_t) 

А бывает при свободном (земле-> состояние) (потому что я вижу здесь 1-3 для первого и структура затем здесь 1-2 перед ошибкой SEG.)

Даже если я пытаюсь print land-> state right before seg fault, он просто перемещает сегрегацию.

ответ

0

При выполнении арифметики указателя вам не нужно масштабировать смещение на sizeof(struct landmark_t) - компилятор уже делает это за вас!

Если у вас есть указатель p в массив, следующий элемент массива находится по адресу p + 1. Это так просто.

Кроме того, вы создаете запись массивов, когда вам, вероятно, следует создать массив записей. Но это другая проблема.

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