c स्ट्रैक्ट्स के 2 डी सरणी को पास करना




pointers multidimensional-array (2)

यह सब समझने में कुछ दर्द हो सकता है, लेकिन एक बार जब आप इसके साथ आसपास प्रयोग करते हैं तो यह बहुत आसान है। आप देख सकते हैं, आप कभी भी तर्क के रूप में पूरी सरणी नहीं पारित कर सकते हैं (मेरा मतलब है कि थोड़े, हर एक तत्व को पारित कर सकते हैं, लेकिन यह बात नहीं है)। एक सरणी मूल रूप से क्रमबद्ध तालिका है यदि यह 1 डी है, तो आपके पास बक्से की एक रेखा है यदि यह 2 डी है, तो आपके पास बक्से की एक टेबल है अगर यह 3 डी है, तो आपके पास एक बाउब (ई / ओआईडी) बक्से है हालांकि आप क्या कर सकते हैं, इसका फायदा उठाया जाता है कि संख्या को स्मृति में कैसे रखा जाता है और सूचक अंकगणितीय का उपयोग किया जाता है। यह काफी सरल है

ठीक चलो चलते हैं-

मान लें कि हमारे पास एक फ़ंक्शन है, set_up_array, जो एक पैरामीटर के रूप में 2 डी सरणी के लिए एक सूचक लेता है

void set_up_array(int **array, int row_size, int column_size){
    for(int i = 0; i < row_size; i++){
        for(int j = 0; j < column_size; j++){
            *((int*)array + i*row_size + j) = i + j + k;
        }
    }
}

इससे आपको अजीब लग सकता है, लेकिन मेरे साथ यहां ठीक रहें।

अब, 2 डी सरणी की कल्पना करें कि आप एक तालिका के रूप में गुजर रहे हैं। इसके पास पंक्तियाँ हैं, और फिर इसे कॉलम मिल गया है। आप इस तरह की तालिका में अगले तत्व कैसे जाएंगे? ठीक है, आपके पास आपके तत्व का सूचक है, और आप इसे खोजते हैं, है ना? यह सही है कि हम यहाँ क्या कर रहे हैं
मैं इसे समझाकर शुरू करूँगा कि हम टाइपिंग ऐड को int * के लिए कह रहे हैं। यह काफी सरल है जब भी हम सूचक गणक करते हैं, सी संकलक हमारे काम को कम करने की कोशिश करता है (जैसे कि एक असली कली ...), इसलिए संकेतक को पता जोड़ने के बजाय, हम केवल तत्वों की संख्या जोड़ते हैं, और उस पर आधारित, सी कंपाइलर स्वचालित रूप से पता हम चाहते हैं पता होगा अब, यहां समस्या है, सी कंपाइलर आंकड़े बताते हैं कि किस प्रकार के सूचक को इंगित करता है। इसलिए, हमारे जीवन को सरल बनाने के लिए, और सी संकलक को खुश करने के लिए, हम इसे एक पूर्णांक * में परिवर्तित कर देते हैं, जिसका अर्थ है, यहां से, जो कुछ भी हम जोड़ते हैं वह प्रारंभिक पते में जोड़ देगा जैसे कि यह int * रों। अब चलो मेज सादृश्य पर वापस जाना हम पंक्ति संख्या और स्तंभ संख्या जानते हैं।

एक बात जिसे आप ध्यान में रखना चाहते हैं, यह है कि इस छवि में कॉलम और पंक्ति लेबल उलट हैं

हमारे जीवन को और भी सरल बनाने के लिए, चलो कार्टेसीयन व्यू (एक ग्राफ-एश दृश्य, एक एक्स और एआई निर्देशांक के साथ) पर स्विच करें। मान लीजिए कि x क्षैतिज है, जबकि y लंबवत है। हम तब के रूप में एरेरे लिख सकते हैं
array[y][x]
जिसका अर्थ है कि जो तत्व हम चाहते हैं, वह x*row_size + y तत्व है। जो हम मूल रूप से हमारे फ़ंक्शन में पॉइंटर में जोड़ सकते हैं, और यह dereference, जैसे कि यह किया गया है, बस वहां, हम i और j का इस्तेमाल किया।

मैं एक सरणी से कार्ड प्रकार संरचनाओं को निपटाने में हूं।

struct card deck[DECKSIZE];  //The deck is an array of cards structures

Im एक 2 डी सरणी का उपयोग कर। कार्ड प्रकार संरचनाओं के सरणियों का एक सरणी

struct card allHands[hands][cards];

मैं डेक और सरणी के पैरामीटर के रूप में सरणी के पैरामीटर के साथ गुजरने वाले इस फ़ंक्शन का उपयोग कर रहा हूँ। मैं डेक पॉइंटर के स्थान को भी बदलता हूं जिससे कार्ड खोने वाले डेक को अनुकरण के रूप में इसे खिलाड़ी को दिया जाता है

void dealHands(struct card *deck, struct card **handArray, int hands, int cards){

    int players;
    int cardCount;
    int passCard = 0;
    struct card * thisDeck;

    thisDeck = deck;

    for(players = 0; players < hands; players++){
        for(cardCount = 0; cardCount < cards; cardCount++){
            handArray[players][cardCount] = thisDeck[passCard];
            passCard++;
        }   
    }
    deck = (deck + passCard);   
}   

इसकी एक लंबी अवधि है कि मैं ग में कार्यक्रम करता हूं इसलिए मुझे लगता है कि आप प्रोटोटाइप कैसे करते हैं?

    void dealHands(struct card[], struct card*[], int, int);

यह मेरे मुख्य रूप से कंकाल की तरह है जैसे कि मैं कैसे कार्यान्वयन कर रहा हूं I

int main(int argc, char *argv[])
{
    /* Declare and initialize variables  */

    int hands = atoi(argv[HANDSINPUT]);  //How many players 
    int cards = atoi(argv[CARDSINPUT]);  //How many cards per hand  
    struct card deck[DECKSIZE];  //The deck is an array of cards structures

    struct card allHands[hands][cards];

    //Builds the deck
    //Shuffles deck with a RNG and swapping every card

    int players;
    int cardCount;
    int passCard = 0;   


    dealHands(deck, allHands, hands, cards);


}

संकलन के दौरान मुझे निम्नलिखित बयानों का ब्योरा मिलता है

चेतावनी: असंगत सूचक प्रकार [डिफ़ॉल्ट रूप से सक्षम] डीलहैंड (डेक, ऑलहाण्ड, हाथ, कार्ड) से 'सौदा होल्ड्स' का तर्क 2 पास करना; ^

नोट: अपेक्षित 'स्ट्रक्चर कार्ड **' लेकिन तर्क 'प्रकार' स्ट्रेट कार्ड ( ) [(एसआईपीटीईपी) (कार्ड)] 'शून्य डीलहैंड (स्ट्रक्चर कार्ड [], स्ट्रक्चर कार्ड [], इंट, इंट) की है; ^

जब मैं फ़ंक्शन में उन्हें कॉल करने की ज़रूरत होती है तो पॉइंटर्स और एरेज़ की बात करते समय मैं हमेशा गड़बड़ी करता हूं तो मुझे यकीन नहीं है कि मेरा तर्क कहाँ दोषपूर्ण है। कहां से मैं मूल्य की तुलना में पता या इसके विपरीत पारित कर रहा हूँ?


फ़ंक्शन आर्गुमेंट्स के रूप में एरेज़ गुजरते समय सबसे महत्वपूर्ण बात यह है कि: आप फ़ंक्शन से / से कोई सरणी नहीं दे सकते

कहा कि, निम्नलिखित बहुत सावधानीपूर्वक पढ़ें (मैं सादगी के लिए int उपयोग करूँगा, लेकिन निश्चित रूप से आप अन्य प्रकारों का भी उपयोग कर सकते हैं।)

लेकिन आप एक सरणी के "पहले तत्व को सूचक" पास कर सकते हैं। सौभाग्य से, सी स्वतः रूपांतरण करता है इससे भी ज्यादा, तीन अपवादों ( sizeof , _Alignof , & ऑपरेटर) के लिए, सी एक ऐसे सूचक का स्वचालित रूप से एक सरणी के नाम को रूपांतरित करता है इसे अक्सर "प्रथम तत्व के सूचक को सरणी देरी " कहा जाता है।

लेकिन यह क्षयकारी पुनरावर्ती नहीं है इसलिए, यदि आप फ़ंक्शन में 2 डी सरणी पास करते हैं, तो यह 1 डी सरणी के लिए एक सूचक को घटा देता है:

int a[1][2];    // 1 = outer dimension, 2 = inner

जब एक समारोह में पारित कर दिया

void f(int a[1][2]);

हो जाता है

int (*a)[2]   // pointer to array of inner dimension

वैकल्पिक रूप से कोई भी स्पष्ट रूप से सूचक वाक्यविन्यास का उपयोग कर सकता है

void f(int (*a)[2]);

सभी प्रकार के लिए a का प्रकार int (*)[2] कोष्ठकों को याद करो! जो वाक्यविन्यास आप उपयोग करते हैं वह मूल रूप से व्यक्तिगत प्राथमिकता है। मैं सभी आयामों के साथ सरणी सिंटैक्स पसंद करता हूं, क्योंकि यह दस्तावेज़ अधिक स्पष्ट रूप से इरादा रखता है।

बाहरी आकार के अलावा आपको हमेशा सभी आकारों को पार करना होगा। यह सिर्फ दस्तावेज के लिए है और आवश्यक नहीं है (उदाहरण के लिए नीचे देखें)।

फ़ंक्शन के अंदर, आप सामान्य इंडेक्स ऑपरेटर का उपयोग करते हैं:

int t, i;    // index variable for ouTer, Inner
a[t][i];

ध्यान दें कि यह उच्च आयाम सरणियों पर लागू किया जा सकता है। 1 डी सरणी के लिए, यह भी वास्तव में लागू होता है बस आंतरिक आयाम निकालें:

int a[1];

के लिए decays

int *a;

(मैं सिर्फ आयामों की संख्या के लिए 1 और 2 स्थिरांक का इस्तेमाल करता हूं; निश्चित तौर पर आप अपने इच्छित आयामों का उपयोग कर सकते हैं।)

यदि आप चर लंबाई (VLA, _variable लंबाई सरणी) के साथ एक सरणी को पारित करना चाहते हैं, तो आपको सभी को पारित करना होगा, लेकिन फ़ंक्शन के लिए बाहरीतम आयाम:

f(int inner, a[][inner]);

लेकिन जाँच के लिए बेहतर आदि सभी आयामों को पारित करना है:

f(int outer, int inner, a[outer][inner]);




struct