c - 2 डी सरणी को पास करना




pointers multidimensional-array (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];

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

int a[1];

का फैसला करता है

int *a;

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

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

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

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

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

Im एक सरणी से कार्ड प्रकार संरचनाओं से निपटने।

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

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

struct card allHands[hands][cards];

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

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

यह मेरे मुख्य के कंकाल की तरह है कि कैसे इम फ़ंक्शन को लागू कर रहा है।

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 कथन मिलते हैं

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

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

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


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

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

मान लें कि हमारे पास एक फ़ंक्शन है, 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 * में परिवर्तित करते हैं, जिसका अर्थ है, यहाँ से, जो भी हम जोड़ते हैं, प्रारंभिक पते में जोड़ देंगे जैसे कि यह int * के साथ होगा रों। अब चलो तालिका के अनुरूप पर वापस जाते हैं। हम पंक्ति संख्या और स्तंभ संख्या जानते हैं।

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

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





struct