2017-02-13 14 views
0

この割り当てのポイントは、緯度と経度の座標を含む2つの行の後に都市の状態を含むファイルから行を読み込むことです。次に、これらの座標を格納するために以下に書かれているように構造体を動的に割り当てる必要があります。最後に、ランドマークをGoogle Earthで使用されるKML形式にエクスポートします。動的サイズのcharポインタを含む構造体の配列を再配置する

この時点で、私は正しく私の構造体からKMLを書くことができます。しかし、それは私のgrow_whole関数(下記参照)でループのいくつかの汚れを取った。問題は、後ですべての割り当てられたポインタを解放するときです。 (私はそれが下に順番にそれを貼って病気の存在を信じて)。問題はヒープ破損だと私は確信しています。しかし、iveはこの方法で長時間働いており、もっとシンプルにできると感じています。

ファイル形式。 (これらの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され、ランドマークポインタはNULLに設定されます。 次に、2つのランドマーク構造体のためのスペースをmallocし、以下の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を実行した後、最初のランドマーク構造には正しく割り当てられたポインタが含まれていましたが、ファイルの終わり近くのどこかになると、都市、州、国のポインタ、緯度と経度がすべて表示されますアウトされていません。私はreallocし、正しい構造にそれらのポインタを書き換える前に、私たちのポインタのすべての配列を保存するforループを追加しました。我々上記のwhileループの後すぐに

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; 
} 

(アウト)kml_endために取得

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ファイルを適切にフォーマットしているので私は知っています)しかし、tea_partyでは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; 
} 

2つ目のランドマーク構造体で発生します。

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

と自由(陸上>状態)で起こる(私はワンセグ障害の前に最初の構造体のために、ここで1-3を参照して、ここに1-2ので。)

私がしようとした場合でもsegフォールトの直前にland-> stateを出力すると、segフォールトが上に移動します。

答えて

0

ポインタの算術演算を行うときに、オフセットをsizeof(struct landmark_t)でスケールする必要はありません。コンパイラはすでにそれを行います。

アレイにポインタpがある場合、次の配列要素はp + 1になります。それは簡単です。

また、おそらくレコードの配列を作成する必要がある場合、配列のレコードを作成するようです。しかしそれは別の問題です。

関連する問題