2012-05-30 10 views
12

की एक सरणी मैं निम्नलिखित struct है:malloc struct संकेत

typedef struct _chess { 
    int **array; 
    int size; 
    struct _chess *parent; 
} chess; 

और मेरे पास है:

typedef struct _chess *Chess; 

अब, मैं गतिशील लंबाई की एक सरणी शतरंज की ओर इशारा स्टोर करने के लिए बनाना चाहते हैं संरचना इसलिए मैं निम्नलिखित करता हूं:

Chess array [] = malloc(size * sizeof(Chess)); 

यह मुझे एक त्रुटि देता है: अवैध प्रारंभकर्ता।

और अगर मैं ड्रॉप [] और ऐसा करते हैं:

Chess array = malloc(size * sizeof(Chess)); 

यह त्रुटि के बिना संकलित लेकिन जब मैं ऐसा करके शून्य करने के लिए इस सरणी के एक तत्व के सेट करने का प्रयास:

array[i]=NULL; 

मैं एक त्रुटि प्राप्त करें: 'void *' प्रकार से 'struct _chess' टाइप करने के लिए असाइन किए जाने वाले असंगत प्रकार

कोई विचार मैं गलत क्या कर रहा हूं? धन्यवाद।

+0

संरचना टाइप करने के लिए क्यों? यह पहले से ही एक अद्वितीय प्रकार है। –

+1

@ user82238 तो टाइप का उपयोग करते समय आपको 'struct' टाइप करने की आवश्यकता नहीं है। – Tyilo

+3

पॉइंटर टाइपपीफ का उपयोग करना बंद करें, आप बस खुद को भ्रमित कर रहे हैं। 'शतरंज * सरणी = malloc (आकार * आकार * सरणी);'। –

उत्तर

33

array थोड़ा भ्रामक नाम है। पॉइंटर्स की गतिशील आवंटित सरणी के लिए, malloc मेमोरी के ब्लॉक में एक सूचक वापस कर देगा। आपको अपनी सरणी में पॉइंटर रखने के लिए Chess* और Chess[] का उपयोग करने की आवश्यकता नहीं है।

Chess *array = malloc(size * sizeof(Chess)); 
array[i] = NULL; 

और शायद बाद में:

/* create new struct chess */ 
array[i] = malloc(sizeof(struct chess)); 

/* set up its members */ 
array[i]->size = 0; 
/* etc. */ 
+0

धन्यवाद! यह मेरे लिए तय है! क्या आप कृपया व्याख्या करेंगे कि शतरंज [] क्यों काम नहीं करता है? मैं अब उलझन में हूं हालांकि मैं [] और * एक ही बात है। – MinaHany

+0

@MinaHany '[]' एक सरणी है, जिसमें वास्तविक सामग्री है। '*' सामग्री के लिए एक सूचक है। पहुंच और उपयोग समान है, लेकिन स्मृति प्रतिनिधित्व पूरी तरह से अलग है। – glglgl

0

IMHO, यह बेहतर लग रहा है:

Chess *array = malloc(size * sizeof(Chess)); // array of pointers of size `size` 

for (int i =0; i < SOME_VALUE; ++i) 
{ 
    array[i] = (Chess) malloc(sizeof(Chess)); 
} 
+0

मुझे लगता है कि मैं इसका उपयोग करूंगा यदि मैं चाहता हूं कि सरणी वास्तविक structs को पकड़ने के लिए न केवल उन्हें इंगित करे। क्या वह सही है? – MinaHany

+0

इस कोड सरणी में पॉइंटर्स हैं, ऑब्जेक्ट्स नहीं। Structs की एक सरणी बनाने के लिए 'संरचना _chess एक [10] का उपयोग करें; // तारों को छिपाने के खिलाफ 'विरुद्ध' के लिए दस structs _chess – maverik

18

वहाँ typedef का एक बहुत यहाँ चल रहा है। व्यक्तिगत रूप से मैं "तारांकन छुपा" के खिलाफ हूं, यानी typedef: पॉइंटर प्रकारों को किसी ऐसे सूचक में डालना जो सूचक की तरह नहीं दिखता है। सी में, पॉइंटर्स काफी महत्वपूर्ण हैं और वास्तव में कोड को प्रभावित करते हैं, foo और foo * के बीच बहुत अंतर है।

इस बारे में कई जवाब भी उलझन में हैं, मुझे लगता है।

Chess मूल्यों, किस प्रकार chess के मूल्यों को संकेत दिए गए हैं की एक सरणी का आपका आवंटन (फिर से, एक बहुत भ्रमित नामकरण कि मैं वास्तव में की सिफारिश नहीं कर सकते हैं) इस तरह होना चाहिए:

Chess *array = malloc(n * sizeof *array); 

उसके बाद, आप, वास्तविक उदाहरणों प्रारंभ करने की आवश्यकता पाशन द्वारा:

for(i = 0; i < n; ++i) 
    array[i] = NULL; 

इसका मतलब यह है कि आप उदाहरण के लिए किसी भी स्मृति को आबंटित नहीं करना चाहते, तो आप सिर्फ डब्ल्यू संकेत की एक सरणी चाहते हैं शुरुआत में सभी पॉइंटर्स कुछ भी नहीं पर इशारा करते हैं।

आप अंतरिक्ष आवंटित करने के लिए करना चाहता था, तो सरलतम रूप होगा:

for(i = 0; i < n; ++i) 
    array[i] = malloc(sizeof *array[i]); 

देखें कैसे sizeof उपयोग 100% अनुरूप है, और कभी नहीं शुरू होता है स्पष्ट प्रकार का उल्लेख। अपने चर में निहित प्रकार की जानकारी का उपयोग करें, और संकलक को किस प्रकार के बारे में चिंता करने दें। खुद को दोहराना मत करो।

बेशक, उपर्युक्त malloc() पर बड़ी संख्या में कॉल करता है; उपयोग पैटर्न के आधार पर उपर्युक्त सभी आकारों की गणना करने के बाद, उपरोक्त सभी को malloc() पर केवल एक कॉल के साथ करना संभव हो सकता है। फिर भी आपको बड़े ब्लॉक में इंगित करने के लिए array[i] पॉइंटर्स को प्रारंभ करने और प्रारंभ करने की आवश्यकता होगी।

+7

+1 का ऐरे। – glglgl

+0

हम्म .. मैंने शतरंज * सरणी = मॉलोक (आकार * आकार (शतरंज)) किया; और फिर (i = 0; i MinaHany

+0

हाँ, यह ठीक है, अगर आप चाहते हैं कि पॉइंटर्स की एक सरणी है जिसे आपने बाद में कुछ उदाहरणों पर सेट किया है जिन्हें आप झूठ बोल रहे हैं। मैंने डिफ़ॉल्ट केस के रूप में न्यूल-इनिट जोड़ने के लिए संशोधित किया। – unwind

0

मैं ऊपर @mverik से सहमत हूं, मैं टाइपिफ़ के साथ विवरण छिपाना पसंद नहीं करता हूं। विशेष रूप से जब आप यह समझने की कोशिश कर रहे हैं कि क्या हो रहा है। मैं आंशिक कोड स्निपेट की बजाय सब कुछ देखना पसंद करता हूं। इसके साथ, यहां एक मॉलोक और एक जटिल संरचना से मुक्त है।

कोड एमएस विजुअल स्टूडियो रिसाव डिटेक्टर का उपयोग करता है ताकि आप संभावित लीक के साथ प्रयोग कर सकें।

#include "stdafx.h" 

#include <string.h> 
#include "msc-lzw.h" 

#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h> 



// 32-bit version 
int hash_fun(unsigned int key, int try_num, int max) { 
    return (key + try_num) % max; // the hash fun returns a number bounded by the number of slots. 
} 


// this hash table has 
// key is int 
// value is char buffer 
struct key_value_pair { 
    int key; // use this field as the key 
    char *pValue; // use this field to store a variable length string 
}; 


struct hash_table { 
    int max; 
    int number_of_elements; 
    struct key_value_pair **elements; // This is an array of pointers to mystruct objects 
}; 


int hash_insert(struct key_value_pair *data, struct hash_table *hash_table) { 

    int try_num, hash; 
    int max_number_of_retries = hash_table->max; 


    if (hash_table->number_of_elements >= hash_table->max) { 
     return 0; // FULL 
    } 

    for (try_num = 0; try_num < max_number_of_retries; try_num++) { 

     hash = hash_fun(data->key, try_num, hash_table->max); 

     if (NULL == hash_table->elements[hash]) { // an unallocated slot 
      hash_table->elements[hash] = data; 
      hash_table->number_of_elements++; 
      return RC_OK; 
     } 
    } 
    return RC_ERROR; 
} 


// returns the corresponding key value pair struct 
// If a value is not found, it returns null 
// 
// 32-bit version 
struct key_value_pair *hash_retrieve(unsigned int key, struct hash_table *hash_table) { 

    unsigned int try_num, hash; 
    unsigned int max_number_of_retries = hash_table->max; 

    for (try_num = 0; try_num < max_number_of_retries; try_num++) { 

     hash = hash_fun(key, try_num, hash_table->max); 

     if (hash_table->elements[hash] == 0) { 
      return NULL; // Nothing found 
     } 

     if (hash_table->elements[hash]->key == key) { 
      return hash_table->elements[hash]; 
     } 
    } 
    return NULL; 
} 


// Returns the number of keys in the dictionary 
// The list of keys in the dictionary is returned as a parameter. It will need to be freed afterwards 
int keys(struct hash_table *pHashTable, int **ppKeys) { 

    int num_keys = 0; 

    *ppKeys = (int *) malloc(pHashTable->number_of_elements * sizeof(int)); 

    for (int i = 0; i < pHashTable->max; i++) { 
     if (NULL != pHashTable->elements[i]) { 
      (*ppKeys)[num_keys] = pHashTable->elements[i]->key; 
      num_keys++; 
     } 
    } 
    return num_keys; 
} 

// The dictionary will need to be freed afterwards 
int allocate_the_dictionary(struct hash_table *pHashTable) { 


    // Allocate the hash table slots 
    pHashTable->elements = (struct key_value_pair **) malloc(pHashTable->max * sizeof(struct key_value_pair)); // allocate max number of key_value_pair entries 
    for (int i = 0; i < pHashTable->max; i++) { 
     pHashTable->elements[i] = NULL; 
    } 



    // alloc all the slots 
    //struct key_value_pair *pa_slot; 
    //for (int i = 0; i < pHashTable->max; i++) { 
    // // all that he could see was babylon 
    // pa_slot = (struct key_value_pair *) malloc(sizeof(struct key_value_pair)); 
    // if (NULL == pa_slot) { 
    //  printf("alloc of slot failed\n"); 
    //  while (1); 
    // } 
    // pHashTable->elements[i] = pa_slot; 
    // pHashTable->elements[i]->key = 0; 
    //} 

    return RC_OK; 
} 


// This will make a dictionary entry where 
// o key is an int 
// o value is a character buffer 
// 
// The buffer in the key_value_pair will need to be freed afterwards 
int make_dict_entry(int a_key, char * buffer, struct key_value_pair *pMyStruct) { 

    // determine the len of the buffer assuming it is a string 
    int len = strlen(buffer); 

    // alloc the buffer to hold the string 
    pMyStruct->pValue = (char *) malloc(len + 1); // add one for the null terminator byte 
    if (NULL == pMyStruct->pValue) { 
     printf("Failed to allocate the buffer for the dictionary string value."); 
     return RC_ERROR; 
    } 
    strcpy(pMyStruct->pValue, buffer); 
    pMyStruct->key = a_key; 

    return RC_OK; 
} 


// Assumes the hash table has already been allocated. 
int add_key_val_pair_to_dict(struct hash_table *pHashTable, int key, char *pBuff) { 

    int rc; 
    struct key_value_pair *pKeyValuePair; 

    if (NULL == pHashTable) { 
     printf("Hash table is null.\n"); 
     return RC_ERROR; 
    } 

    // Allocate the dictionary key value pair struct 
    pKeyValuePair = (struct key_value_pair *) malloc(sizeof(struct key_value_pair)); 
    if (NULL == pKeyValuePair) { 
     printf("Failed to allocate key value pair struct.\n"); 
     return RC_ERROR; 
    } 


    rc = make_dict_entry(key, pBuff, pKeyValuePair); // a_hash_table[1221] = "abba" 
    if (RC_ERROR == rc) { 
     printf("Failed to add buff to key value pair struct.\n"); 
     return RC_ERROR; 
    } 


    rc = hash_insert(pKeyValuePair, pHashTable); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 

    return RC_OK; 
} 


void dump_hash_table(struct hash_table *pHashTable) { 

    // Iterate the dictionary by keys 
    char * pValue; 
    struct key_value_pair *pMyStruct; 
    int *pKeyList; 
    int num_keys; 

    printf("i\tKey\tValue\n"); 
    printf("-----------------------------\n"); 
    num_keys = keys(pHashTable, &pKeyList); 
    for (int i = 0; i < num_keys; i++) { 
     pMyStruct = hash_retrieve(pKeyList[i], pHashTable); 
     pValue = pMyStruct->pValue; 
     printf("%d\t%d\t%s\n", i, pKeyList[i], pValue); 
    } 

    // Free the key list 
    free(pKeyList); 

} 

int main(int argc, char *argv[]) { 

    int rc; 
    int i; 


    struct hash_table a_hash_table; 
    a_hash_table.max = 20; // The dictionary can hold at most 20 entries. 
    a_hash_table.number_of_elements = 0; // The intial dictionary has 0 entries. 
    allocate_the_dictionary(&a_hash_table); 

    rc = add_key_val_pair_to_dict(&a_hash_table, 1221, "abba"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 2211, "bbaa"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 1122, "aabb"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 2112, "baab"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 1212, "abab"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 2121, "baba"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 



    // Iterate the dictionary by keys 
    dump_hash_table(&a_hash_table); 

    // Free the individual slots 
    for (i = 0; i < a_hash_table.max; i++) { 
     // all that he could see was babylon 
     if (NULL != a_hash_table.elements[i]) { 
      free(a_hash_table.elements[i]->pValue); // free the buffer in the struct 
      free(a_hash_table.elements[i]); // free the key_value_pair entry 
      a_hash_table.elements[i] = NULL; 
     } 
    } 


    // Free the overall dictionary 
    free(a_hash_table.elements); 


    _CrtDumpMemoryLeaks(); 
    return 0; 
}