2016-07-17 4 views
0

CでHashMapを作成していますが、ノードが初期化されているかどうかを検出できません。以下の私のコードからC - 構造体配列のインデックスが初期化されていないか確認する

抜粋:

static struct Node 
{ 
    void *key, *value; 
    struct Node *next; 
}; 


struct Node **table; 
int capacity = 4; 
table = malloc(capacity * sizeof(struct Node)); 

// At this point I should have a pointer to an empty Node array of size 4. 

if (table[0] != NULL) 
{ 
    // This passes 
} 

私はここに何ができるのか表示されません。私はこの性質の他の大量の記事を読んだことがあり、その解決策のどれも私には意味をなさない。

enter image description here

+0

'malloc'で割り当てられたメモリはゼロで初期化されません。これを行うには、['memset'](http://man7.org/linux/man-pages/man3/memset.3.html)を使うことができます。 'struct Node ** table;'はポインタの "リスト"を作るが、あなたは 'Node'sの"リスト "を割り当てた。 – Tim

答えて

1

malloc割り当てられたメモリを初期化しません。 callocを使用してメモリをゼロ初期化することができます。その後

// Not sizeof(struct Node) 
// table = calloc(capacity, sizeof(struct Node)); 
table = calloc(capacity, sizeof(*table)); 

、それを使用する意味を行います:

if (table[0] != NULL) 
{ 
    ... 
} 
+0

'calloc'を使うと、それぞれが' NULL'でしょうか? – Hatefiend

+0

@Hatefiend、はい。 –

+0

配列のサイズを2倍にする必要はありますか? 'realloc'は私を同じ問題に戻すでしょうか? – Hatefiend

-1

私はあなたがあなたが必要とする様々なメモリ操作を処理するための関数のセットを作成HashMapCollectionタイプのようなものを検討し提案します。

したがって、次のようなコードがある可能性があります。私はこれをテストしていないし、コンパイルしたこともありませんが、それは開始場所です。

下記のFreeHashMapCollection()機能は、HashMapCollectionを処理して、管理データ構造を解放する前に、その内容を解放します。これはあなたがしたいことではないかもしれないので、それはあなたが考慮すべきものです。

以下の考え方はHashMapCollection構造体のための単一のポインタを持つことであり、HashMapNode構造体の配列またはリストは管理データの直後にあるため、単一のfree()がすべてを一度に解放します。

typedef struct _TAGHashMapNode { 
    void *key, *value; 
    struct _TAGHashMapNode *next; 
} HashMapNode; 

typedef struct { 
    int iCapacity; // max number of items 
    int iSize;  // current number of items 
    HashMapNode *table; // pointer to the HashMapNode table 
} HashMapCollection; 

そして適切に初期化され、特定の容量のHashMapCollectionを割り当てる機能を有します。

HashMapCollection *AllocateHashMapCollection (int iCapacity) 
{ 
    HashMapCollection *p = malloc (sizeof(HashMapCollection) + iCapacity * sizeof(HashMapNode)); 

    if (p) { 
     p->table = (HashMapNode *)(p + 1); 
     p->iCapacity = iCapacity; 
     p->iSize = 0; 
     memset (p->table, 0, sizeof(HashMapNode) * iCapacity); 
    } 
    return p; 
} 

HashMapCollection *ReallocHashMapCollection (HashMapCollection *p, int iNewCapacity) 
{ 
    HashMapCollection *pNew = realloc (p, sizeof(HashMapCollection) + sizeof(HashMapNode) * iNewCapacity); 

    if (pNew) { 
     pNew->table = (HashMapNode *)(pNew + 1); 
     if (p == NULL) { 
      // if p is not NULL then pNew will have a copy of that. 
      // if p is NULL then this is basically a malloc() so initialize pNew data. 
      pNew->iCapacity = pNew->iSize = 0; 
     } 
     if (iNewCapacity > pNew->iCapacity) { 
      // added more memory so need to zero out that memory. 
      memset (pNew->table + iCapacity, 0, sizeof(HashMapNode) * (iNewCapacity - pNew->iCapacity)); 
     } 
     pNew->iCapacity = iNewCapacity; // set our new current capacity 
     p = pNew; // lets return our new memory allocated. 
    } 
    return p; // return either old pointer if realloc() failed or new pointer 
} 

void FreeHashMapCollection (HashMapCollection *p) 
{ 
    // go through the list of HashMapNode items and free up each pair then 
    // free up the HashMapCollection itself. 

    for (iIndex = 0; iIndex < p->iCapacity; iIndex++) { 
     if (p->table[iIndex].key) free (p->table[iIndex].key); 
     if (p->table[iIndex].value) free (p->table[iIndex].value); 
     // WARNING *** 
     // if these next pointers are actually pointers inside the array of HashMapNode items 
     // then you would not do this free as it is unnecessary. 
     // this free is only necessary if next points to some memory area 
     // other than the HashMapNode table of HashMapCollection. 
     if (p->table[iIndex].next) free (p->table[iIndex].next); 
     // even though we are going to free this, init to NULL 
     p->table[iIndex].key = NULL; 
     p->table[iIndex].value = NULL; 
     p->table[iIndex].next = NULL; 
    } 
    free (p); // free up the memory of the HashMapCollection 
} 
+0

この素晴らしいポストに感謝しています。実際、あなたのコードは[私はここに書いている](https://gist.github.com/anonymous/9970a8087a15f07f2762a2a09ea6ed94)と非常によく似ています。私が気づくのはあなたの 'FreeHashMapCollection'メソッドです。なぜあなたはいつメモリを解放する必要がありますか? – Hatefiend

+0

@Hatefiend FreeHashMapCollection関数を追加したのは、特定のデータセットを処理しているときにHashMapCollectionを解放して、新しいデータセットで新しいデータセット。あなたはそれを必要とするかもしれません。 –

+0

もう1つ質問があります。私がオンラインで見つけたハッシュコード関数は本当に良いと言われていましたが、 'unsigned char'ポインタしか取り込まれませんでした。整数を渡すと、プログラムがクラッシュします。これは、 'int'を' put'メソッドに渡すと、 'int%capacity'は' Node'を置くインデックスでなければならないのでしょうか?または、 'double'を含む可能なすべての型に対して別々の' hashcode'メソッドを取得する必要がありますか?私はjavaに慣れていて、ANYTHINGをハッシュに変換する 'hashCode()'メソッドを持っています。 – Hatefiend

関連する問題