C ++ फ़ंक्शन के लिए 2 डी सरणी पास करना


324

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

अब तक मेरे पास यह है:

void myFunction(double** myArray){
     myArray[x][y] = 5;
     etc...
}

और मैंने अपने कोड में कहीं और एक ऐरे की घोषणा की है:

double anArray[10][10];

हालाँकि, कॉलिंग myFunction(anArray)मुझे एक त्रुटि देता है।

मैं सरणी जब मैं इसे पारित कॉपी करने के लिए नहीं करना चाहती। में किए गए परिवर्तन myFunctionकी स्थिति में परिवर्तन करना चाहिए anArray। अगर मैं सही ढंग से समझूं, तो मैं केवल एक तर्क के रूप में एक 2 डी सरणी के पास जाना चाहता हूं। फ़ंक्शन को विभिन्न आकारों के सरणियों को भी स्वीकार करने की आवश्यकता है। उदाहरण के लिए, [10][10]और [5][5]। मैं यह कैसे कर सकता हूँ?


1
पैरामीटर 3 को 'डबल [10] [10]' से 'डबल **' में परिवर्तित नहीं कर सकते
रोजरडर्विन

3
स्वीकार किए जाते हैं जवाब से पता चलता है केवल 2 तकनीक [अपने (2) और (3) एक ही हैं] लेकिन वहाँ रहे हैं एक समारोह के लिए एक 2 डी सरणी में उत्तीर्ण होने की 4 अनूठे तरीके
लीजेंड्स 2

कड़ाई से बोलते हुए, हाँ, वे 2 डी सरणियां नहीं हैं, लेकिन यह सम्मेलन (UB के लिए अग्रणी) एक व्यूह की एक सरणी है, प्रत्येक (1D) सरणी की ओर इशारा करते हुए, प्रचलित प्रतीत होता है :( mxn के एक fl11D सरणी होने लंबाई, 2 डी सरणी का अनुकरण करने के लिए सहायक कार्यों / वर्ग के साथ शायद बेहतर है।
किंवदंतियां 2

EASIEST - func(int* mat, int r, int c){ for(int i=0; i<r; i++) for(int j=0; j<c; j++) printf("%d ", *(mat+i*c+j)); }। जैसे यह कॉलint mat[3][5]; func(mat[0], 3, 5);
मिन्हास कमल

जवाबों:


413

किसी फ़ंक्शन के लिए 2D सरणी पास करने के तीन तरीके हैं:

  1. पैरामीटर एक 2 डी सरणी है

    int array[10][10];
    void passFunc(int a[][10])
    {
        // ...
    }
    passFunc(array);
  2. पैरामीटर एक सरणी है जिसमें पॉइंटर्स होते हैं

    int *array[10];
    for(int i = 0; i < 10; i++)
        array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    {
        // ...
    }
    passFunc(array);
  3. पैरामीटर एक पॉइंटर को पॉइंटर है

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
        array[i] = new int[10];
    void passFunc(int **a)
    {
        // ...
    }
    passFunc(array);

4
@Overflowh आप के arrayसाथ तत्व पा सकते हैं array[i][j]:)
shengy

14
1 मामले के लिए, पैरामीटर के रूप में घोषित किया जा सकता है int (*a)[10]
जुक्री

9
दूसरे मामले के लिए, पैरामीटर के रूप में घोषित किया जा सकता है int **
जकरी

1
@ जैक: आप सही कह रहे हैं, केवल दो ही मामले हैं; एक एक पॉइंटर-टू-पॉइंटर है और दूसरा एक पॉइंटर है जिसका आकार एन के पूर्णांक सरणी में है int (*a) [10]
लीजेंड 2k

3
केस 2 और 3 डी 2 डी सरणियां नहीं हैं, इसलिए यह उत्तर भ्रामक है। इसे देखें
लुंडिन

178

निर्धारित माप

1. संदर्भ द्वारा पास

template <size_t rows, size_t cols>
void process_2d_array_template(int (&array)[rows][cols])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

C ++ में आयाम की जानकारी को खोए बिना संदर्भ द्वारा सरणी को पारित करना शायद सबसे सुरक्षित है, क्योंकि एक कॉलर को एक गलत आयाम (कंपाइलर फ़्लैग जब मिसमैचिंग) से गुजरने की चिंता नहीं है। हालाँकि, यह डायनेमिक (फ्रीस्टोर) सरणियों के साथ संभव नहीं है; यह केवल स्वचालित ( आमतौर पर स्टैक-लिविंग ) सरणियों के लिए काम करता है अर्थात संकलन समय पर आयामीता को जाना जाना चाहिए।

2. सूचक द्वारा पास

void process_2d_array_pointer(int (*array)[5][10])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < 5; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << (*array)[i][j] << '\t';
        std::cout << std::endl;
    }    
}

पिछली पद्धति के बराबर सी पॉइंटर द्वारा सरणी पास कर रहा है। यह सरणी के क्षयकारी सूचक प्रकार (3) से गुजरने के साथ भ्रमित नहीं होना चाहिए , जो कि सामान्य, लोकप्रिय विधि है, यद्यपि यह एक से कम सुरक्षित है लेकिन अधिक लचीला है। जैसा (1) , इस विधि का उपयोग जब सभी सरणी के आयाम तय की और संकलन समय पर जाना जाता है। ध्यान दें कि फ़ंक्शन को कॉल करते समय सरणी का पता पास होना चाहिए process_2d_array_pointer(&a)न कि क्षय द्वारा पहले तत्व का पताprocess_2d_array_pointer(a)

चर आकार

ये C से विरासत में मिले हैं, लेकिन कम सुरक्षित हैं, संकलक के पास जाँच का कोई तरीका नहीं है, यह गारंटी देते हुए कि कॉलर आवश्यक आयामों को पार कर रहा है। फ़ंक्शन केवल उस फोन पर होता है जो कॉलर आयाम (ओं) के रूप में गुजरता है। ये ऊपर वाले की तुलना में अधिक लचीले होते हैं क्योंकि विभिन्न लंबाई के सरणियों को उनके पास पर्याप्त रूप से पारित किया जा सकता है।

यह याद रखना चाहिए कि सी में एक समारोह में सीधे एक सरणी पास करने जैसी कोई चीज नहीं है [जबकि सी ++ में उन्हें एक संदर्भ (1) के रूप में पारित किया जा सकता है ; (2) सरणी के लिए एक सूचक पारित कर रहा है और सरणी को ही नहीं। हमेशा एक सरणी को पास करते-करते एक पॉइंटर-कॉपी ऑपरेशन बन जाता है, जो व्यूअर में आकर क्षय होने की सरणी की प्रकृति द्वारा सुगम होता है ।

3. क्षय प्रकार के लिए एक सूचक द्वारा (मान) पास करें

// int array[][10] is just fancy notation for the same thing
void process_2d_array(int (*array)[10], size_t rows)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

यद्यपि int array[][10]अनुमति दी गई है, मैं उपरोक्त सिंटैक्स पर इसकी अनुशंसा नहीं करूंगा क्योंकि उपरोक्त सिंटैक्स यह स्पष्ट करता है कि पहचानकर्ता array10 पूर्णांक वाले सरणी के लिए एक एकल पॉइंटर है, जबकि यह सिंटैक्स ऐसा लगता है कि यह एक 2D व्यूह है लेकिन समान पॉइंटर है 10 पूर्णांकों की एक सरणी। यहां हम एक पंक्ति में तत्वों की संख्या जानते हैं (यानी स्तंभ का आकार, यहां 10) लेकिन पंक्तियों की संख्या अज्ञात है और इसलिए इसे एक तर्क के रूप में पारित किया जाना चाहिए। इस मामले में कुछ सुरक्षा है क्योंकि कंपाइलर फ़्लैग कर सकता है जब एक पॉइंटर को दूसरे आयाम के साथ एक सरणी में रखा जाए जो 10 के बराबर नहीं है। पहला आयाम अलग हिस्सा है और छोड़ा जा सकता है। औचित्य के लिए यहां देखें कि केवल पहले आयाम को छोड़ने की अनुमति क्यों है।

4. एक पॉइंटर को पॉइंटर से पास करें

// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(int **array, size_t rows, size_t cols)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '\t';
        std::cout << std::endl;
    }
}

फिर से एक वैकल्पिक वाक्यविन्यास है int *array[10]जो कि जैसा है int **array। इस सिंटैक्स में [10]इसे नजरअंदाज कर दिया जाता है क्योंकि यह एक पॉइंटर में बदल जाता है int **array। शायद यह कॉलर के लिए सिर्फ एक संकेत है कि पारित सरणी में कम से कम 10 कॉलम होने चाहिए, फिर भी पंक्ति गणना आवश्यक है। किसी भी मामले में कंपाइलर किसी भी लम्बाई / आकार के उल्लंघन के लिए ध्वजांकित नहीं करता है (यह केवल जांचता है कि पास किया गया प्रकार पॉइंटर पॉइंटर है), इसलिए पैरामीटर के रूप में पंक्ति और स्तंभ दोनों की आवश्यकता होती है।

नोट: (4) सबसे कम सुरक्षित विकल्प है क्योंकि इसमें किसी भी प्रकार की जांच और सबसे असुविधाजनक है। कोई इस समारोह में वैध रूप से 2 डी सरणी नहीं दे सकता है; सी-एफएक्यू करने के सामान्य वर्कअराउंड की निंदा करता है int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);क्योंकि यह संभावित रूप से अपरिभाषित व्यवहार का कारण बन सकता है सरणी के चपटे होने के कारण कारण । इस पद्धति में एक सरणी को पास करने का सही तरीका हमें असुविधाजनक भाग में लाता है अर्थात हमें इसके प्रत्येक तत्व के साथ एक अतिरिक्त (सरोगेट) सरणी की आवश्यकता होती है जो वास्तविक, से-पास किए गए सरणी की संबंधित पंक्ति को इंगित करता है; यह सरोगेट तब फ़ंक्शन को दिया जाता है (नीचे देखें); यह सब उपरोक्त विधियों के समान कार्य करने के लिए है जो अधिक सुरक्षित, स्वच्छ और शायद अधिक तेज़ हैं।

उपरोक्त कार्यों का परीक्षण करने के लिए यहां एक ड्राइवर प्रोग्राम है:

#include <iostream>

// copy above functions here

int main()
{
    int a[5][10] = { { } };
    process_2d_array_template(a);
    process_2d_array_pointer(&a);    // <-- notice the unusual usage of addressof (&) operator on an array
    process_2d_array(a, 5);
    // works since a's first dimension decays into a pointer thereby becoming int (*)[10]

    int *b[5];  // surrogate
    for (size_t i = 0; i < 5; ++i)
    {
        b[i] = a[i];
    }
    // another popular way to define b: here the 2D arrays dims may be non-const, runtime var
    // int **b = new int*[5];
    // for (size_t i = 0; i < 5; ++i) b[i] = new int[10];
    process_pointer_2_pointer(b, 5, 10);
    // process_2d_array(b, 5);
    // doesn't work since b's first dimension decays into a pointer thereby becoming int**
}

C ++ में फ़ंक्शन के लिए गतिशील रूप से आवंटित सरणियों को पारित करने के बारे में क्या? C11 मानक में इसे सांख्यिकीय रूप से और गतिशील रूप से आवंटित सरणियों के लिए किया जा सकता है, जैसे कि fn (int col, int row, int array [col] [row]): stackoverflow.com/questions/16004668/… मैंने इस समस्या पर सवाल किया है : stackoverflow.com/questions/27457076/…
42n4

@ 42n4 केस 4 कवर (C ++ के लिए भी)। गतिशील रूप से आवंटित सरणियों के लिए, बस लूप के अंदर की रेखा से b[i] = a[i];, कहने के लिए, बदल जाएगी b[i] = new int[10];। एक भी bगतिशील रूप से आवंटित किया जा सकता है int **b = int *[5];और यह अभी भी काम करेगा।
किंवदंतियां 2

1
4array[i][j] में फ़ंक्शन को संबोधित करना कैसे काम करता है ) ? क्योंकि इसने ptr को ptr पर प्राप्त किया है और अंतिम आयाम का मूल्य नहीं जानता है, जो सही पते के लिए एक बदलाव करने के लिए आवश्यक है?
user1234567

2
array[i][j]सिर्फ पॉइंटर अंकगणित है यानी पॉइंटर के मान के लिए array, यह iपरिणाम को जोड़ देगा और उस के रूप में int*इसे jघटा देगा, जिससे यह उस स्थान को जोड़ देगा और उसे हटा देगा int। तो, नहीं, इसके लिए किसी आयाम की जरूरत नहीं है। लेकिन, यह पूरी बात है! कंपाइलर प्रोग्रामर के शब्द को विश्वास में लेता है और यदि प्रोग्रामर गलत था, तो अपरिभाषित व्यवहार नहीं करता है। यही कारण है कि मैंने उल्लेख किया कि केस 4 सबसे कम सुरक्षित विकल्प है।
किंवदंतियों 2

ऐसे मामलों में एक संरचना आपकी अच्छी सेवा कर सकती है।
Xofo

40

शेंगनी के पहले सुझाव के लिए एक संशोधन, आप फ़ंक्शन को बहु-आयामी सरणी चर को स्वीकार करने के लिए टेम्पलेट्स का उपयोग कर सकते हैं (बजाय एक सरणी के संकेत को प्रबंधित करने और हटाने के लिए):

template <size_t size_x, size_t size_y>
void func(double (&arr)[size_x][size_y])
{
    printf("%p\n", &arr);
}

int main()
{
    double a1[10][10];
    double a2[5][5];

    printf("%p\n%p\n\n", &a1, &a2);
    func(a1);
    func(a2);

    return 0;
}

प्रिंट स्टेटमेंट यह दिखाने के लिए हैं कि एरे को संदर्भ द्वारा (चर के पतों को प्रदर्शित करके) पास किया जा रहा है


2
आपको %pएक पॉइंटर को प्रिंट करने के लिए उपयोग करना चाहिए , और फिर भी, आपको इसे डालना होगा void *, अन्यथा printf()अपरिभाषित व्यवहार को आमंत्रित करता है। इसके अलावा, आपको &फ़ंक्शन को कॉल करते समय पता ( ) ऑपरेटर का उपयोग नहीं करना चाहिए , क्योंकि फ़ंक्शन प्रकार के तर्क की अपेक्षा करते हैं double (*)[size_y], जबकि आप वर्तमान में उन्हें पास करते हैं double (*)[10][10]और double (*)[5][5]

यदि आप टेम्प्लेट का उपयोग कर दोनों आयामों को टेम्प्लेट के रूप में ले रहे हैं तो अधिक उपयुक्त है और बेहतर है क्योंकि निम्न-स्तर के पॉइंटर एक्सेस को पूरी तरह से टाला जा सकता है।
लीजेंड्स 2

3
यह केवल तभी काम करता है जब सरणी का आकार संकलन समय पर जाना जाता है।
jeb_is_a_mess 16

उत्तर में @Georg कोड ठीक वही है जो मैंने सुझाया था। यह जीसीसी 6.3 में काम करता है - ऑनलाइन डेमो । क्या आप पैरामीटर को संदर्भ बनाना भूल गए?
लेजेंड्स 2k

21

हैरानी की बात है कि किसी ने भी अभी तक इसका उल्लेख नहीं किया है, लेकिन आप बस कुछ भी 2D [] [] शब्दार्थ का समर्थन कर सकते हैं।

template <typename TwoD>
void myFunction(TwoD& myArray){
     myArray[x][y] = 5;
     etc...
}

// call with
double anArray[10][10];
myFunction(anArray);

यह किसी भी 2D "एरे-लाइक" डेटास्ट्रक्चर के साथ काम करता है, जैसे कि std::vector<std::vector<T>>, या कोड को पुनः उपयोग करने के लिए एक उपयोगकर्ता परिभाषित प्रकार।


1
यह सही उत्तर होना चाहिए। यह वर्णित सभी समस्याओं को हल करता है और कुछ जिनका उल्लेख यहां नहीं किया गया है। प्रकार की सुरक्षा, सरणियों का समय असंगतता, कोई सूचक अंकगणित, कोई प्रकार की कास्टिंग, कोई डेटा कॉपी नहीं। C और C ++ के लिए काम करता है।
ओपलऐप्स

खैर, यह सी ++ के लिए काम करता है; C टेम्पलेट का समर्थन नहीं करता है। इसे C में करने से मैक्रोज़ की आवश्यकता होगी।
गुन्नार

20

आप इस तरह एक समारोह टेम्पलेट बना सकते हैं:

template<int R, int C>
void myFunction(double (&myArray)[R][C])
{
    myArray[x][y] = 5;
    etc...
}

फिर आपके पास R और C. के माध्यम से दोनों आयाम आकार हैं। प्रत्येक सरणी आकार के लिए एक अलग फ़ंक्शन बनाया जाएगा, इसलिए यदि आपका फ़ंक्शन बड़ा है और आप इसे विभिन्न सरणी आकारों के साथ कहते हैं, तो यह महंगा हो सकता है। आप इसे इस तरह से एक समारोह में एक आवरण के रूप में उपयोग कर सकते हैं:

void myFunction(double * arr, int R, int C)
{
    arr[x * C + y] = 5;
    etc...
}

यह एरे को एक आयामी मानता है, और अंकगणित का उपयोग अनुक्रमित के ऑफसेट का पता लगाने के लिए करता है। इस स्थिति में, आप इस तरह से टेम्पलेट को परिभाषित करेंगे:

template<int C, int R>
void myFunction(double (&myArray)[R][C])
{
    myFunction(*myArray, R, C);
}

2
size_tकी तुलना में सरणी अनुक्रमित के लिए बेहतर प्रकार है int
एंड्रयू टॉमाज़ोस

13

anArray[10][10]एक पॉइंटर को पॉइंटर नहीं है, यह एक संकलित मेमोरी है जो टाइप डबल के 100 मानों को संग्रहीत करने के लिए उपयुक्त है, जो कंपाइलर जानता है कि पता कैसे करें क्योंकि आपने आयाम निर्दिष्ट किए हैं। आपको इसे सरणी के रूप में फ़ंक्शन में पास करना होगा। आप निम्न आयाम के आकार को छोड़ सकते हैं, इस प्रकार है:

void f(double p[][10]) {
}

हालांकि, यह आपको दस के अलावा अंतिम आयाम के साथ सरणियों को पारित नहीं करने देगा।

C ++ में सबसे अच्छा समाधान उपयोग करना है std::vector<std::vector<double> >: यह लगभग कुशल है, और काफी सुविधाजनक है।


1
मैं इस समाधान को पसंद करता हूं क्योंकि एसटीडी लाइब्रेरी बहुत ही कुशल है - वैसे मुझे दासब्लिंकलाइट पसंद है; मैंने dasblikenlicht
mozillanerd

लगभग कुशल के रूप में? हाँ सही। पॉइंटर चेज़िंग हमेशा नॉन-पॉइंटर चेज़िंग की तुलना में अधिक महंगा होता है।
थॉमस ईडिंग सेप

8

एकल आयामी सरणी सरणी में पहले तत्व की ओर इशारा करते हुए एक पॉइंटर पॉइंटर का फैसला करता है। जबकि एक 2 डी सरणी पहली पंक्ति की ओर इशारा करते हुए एक पॉइंटर का फैसला करती है। तो, फ़ंक्शन प्रोटोटाइप होना चाहिए -

void myFunction(double (*myArray) [10]);

मैं std::vectorकच्ची सरणियों को प्राथमिकता दूंगा।


8

आप ऐसा कुछ कर सकते हैं ...

#include<iostream>

using namespace std;

//for changing values in 2D array
void myFunc(double *a,int rows,int cols){
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            *(a+ i*rows + j)+=10.0;
        }
    }
}

//for printing 2D array,similar to myFunc
void printArray(double *a,int rows,int cols){
    cout<<"Printing your array...\n";
    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
            cout<<*(a+ i*rows + j)<<"  ";
        }
    cout<<"\n";
    }
}

int main(){
    //declare and initialize your array
    double a[2][2]={{1.5 , 2.5},{3.5 , 4.5}};

    //the 1st argument is the address of the first row i.e
    //the first 1D array
    //the 2nd argument is the no of rows of your array
    //the 3rd argument is the no of columns of your array
    myFunc(a[0],2,2);

    //same way as myFunc
    printArray(a[0],2,2);

    return 0;
}

आपका आउटपुट निम्नानुसार होगा ...

11.5  12.5
13.5  14.5

1
एकमात्र कारण मैं इस बात को लेकर आ सकता हूं कि कोई इस मामले में एरे को कैसे मंगाएगा, इसका कारण यह है कि किसी को एरे पॉइंट पॉइंट के बारे में ज्ञान की कमी है।
लुंडिन

3
i चर को स्तंभों से गुणा करना चाहिए, न कि पंक्तियों से जब तक कि स्तंभ और पंक्तियाँ इस मामले में समान हों
Andrey Chernukha

4

यहाँ वेक्टर वेक्टर उदाहरण का एक वेक्टर है

#include <iostream>
#include <vector>
using namespace std;

typedef vector< vector<int> > Matrix;

void print(Matrix& m)
{
   int M=m.size();
   int N=m[0].size();
   for(int i=0; i<M; i++) {
      for(int j=0; j<N; j++)
         cout << m[i][j] << " ";
      cout << endl;
   }
   cout << endl;
}


int main()
{
    Matrix m = { {1,2,3,4},
                 {5,6,7,8},
                 {9,1,2,3} };
    print(m);

    //To initialize a 3 x 4 matrix with 0:
    Matrix n( 3,vector<int>(4,0));
    print(n);
    return 0;
}

उत्पादन:

1 2 3 4
5 6 7 8
9 1 2 3

0 0 0 0
0 0 0 0
0 0 0 0

2

हम एक समारोह में 2 डी सरणी पास करने के लिए कई तरीकों का उपयोग कर सकते हैं:

  • सिंगल पॉइंटर का उपयोग करके हमें 2D सरणी टाइप करना होगा।

    #include<bits/stdc++.h>
    using namespace std;
    
    
    void func(int *arr, int m, int n)
    {
        for (int i=0; i<m; i++)
        {
           for (int j=0; j<n; j++)
           {
              cout<<*((arr+i*n) + j)<<" ";
           }
           cout<<endl;
        }
    }
    
    int main()
    {
        int m = 3, n = 3;
        int arr[m][n] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        func((int *)arr, m, n);
        return 0;
    }
  • डबल पॉइंटर का उपयोग करना इस तरह, हम 2d सरणी टाइप करते हैं

    #include<bits/stdc++.h>
    using namespace std;

   void func(int **arr, int row, int col)
   {
      for (int i=0; i<row; i++)
      {
         for(int j=0 ; j<col; j++)
         {
           cout<<arr[i][j]<<" ";
         }
         printf("\n");
      }
   }

  int main()
  {
     int row, colum;
     cin>>row>>colum;
     int** arr = new int*[row];

     for(int i=0; i<row; i++)
     {
        arr[i] = new int[colum];
     }

     for(int i=0; i<row; i++)
     {
         for(int j=0; j<colum; j++)
         {
            cin>>arr[i][j];
         }
     }
     func(arr, row, colum);

     return 0;
   }

1

बहुआयामी सरणियों को पारित करने के लिए एक महत्वपूर्ण बात यह है:

  • First array dimension निर्दिष्ट करने की आवश्यकता नहीं है।
  • Second(any any further)dimension निर्दिष्ट किया जाना चाहिए।

1. जब केवल दूसरा आयाम वैश्विक रूप से उपलब्ध हो (या तो स्थूल या वैश्विक स्थिरांक के रूप में)

`const int N = 3;

`void print(int arr[][N], int m)
{
int i, j;
for (i = 0; i < m; i++)
  for (j = 0; j < N; j++)
    printf("%d ", arr[i][j]);
}`

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(arr, 3);
return 0;
}`

2. एकल सूचक का उपयोग करना : इस विधि में, हमें कार्य करने के लिए 2 डी सरणी टाइप करना होगा।

`void print(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
  for (j = 0; j < n; j++)
    printf("%d ", *((arr+i*n) + j));
 }

`int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;

// We can also use "print(&arr[0][0], m, n);"
print((int *)arr, m, n);
return 0;
}`

0

आप ऐसा करने के लिए C ++ में टेम्पलेट सुविधा का उपयोग कर सकते हैं। मैंने कुछ इस तरह किया:

template<typename T, size_t col>
T process(T a[][col], size_t row) {
...
}

इस दृष्टिकोण के साथ समस्या यह है कि आपके द्वारा प्रदान की जाने वाली कॉल के प्रत्येक मूल्य के लिए, टेम्पलेट का उपयोग करके एक नई फ़ंक्शन परिभाषा को तत्काल दिया जाता है। इसलिए,

int some_mat[3][3], another_mat[4,5];
process(some_mat, 3);
process(another_mat, 4);

2 फ़ंक्शन परिभाषाओं का उत्पादन करने के लिए दो बार टेम्प्लेट करता है (एक जहां col = 3 और एक जहाँ col = 5)।


0

आप पास करना चाहते हैं int a[2][3]के लिए void func(int** pp)इस प्रकार के रूप में आप सहायक चरणों की जरूरत है।

int a[2][3];
int* p[2] = {a[0],a[1]};
int** pp = p;

func(pp);

जैसा कि पहले [2]स्पष्ट रूप से निर्दिष्ट किया जा सकता है, इसे और भी सरल बनाया जा सकता है।

int a[][3];
int* p[] = {a[0],a[1]};
int** pp = p;

func(pp);

0

मामले में आप एक फ़ंक्शन के लिए डायनामिक आकार 2-डी सरणी पास करना चाहते हैं, कुछ पॉइंटर्स का उपयोग करना आपके लिए काम कर सकता है।

void func1(int *arr, int n, int m){
    ...
    int i_j_the_element = arr[i * m + j];  // use the idiom of i * m + j for arr[i][j] 
    ...
}

void func2(){
    ...
    int arr[n][m];
    ...
    func1(&(arr[0][0]), n, m);
}

0

आपको बाईं ओर के आयाम को छोड़ देने की अनुमति है और इसलिए आप दो विकल्पों के साथ समाप्त होते हैं:

void f1(double a[][2][3]) { ... }

void f2(double (*a)[2][3]) { ... }

double a[1][2][3];

f1(a); // ok
f2(a); // ok 

बिंदुओं के साथ भी ऐसा ही है:

// compilation error: cannot convert ‘double (*)[2][3]’ to ‘double***’ 
// double ***p1 = a;

// compilation error: cannot convert ‘double (*)[2][3]’ to ‘double (**)[3]’
// double (**p2)[3] = a;

double (*p3)[2][3] = a; // ok

// compilation error: array of pointers != pointer to array
// double *p4[2][3] = a;

double (*p5)[3] = a[0]; // ok

double *p6 = a[0][1]; // ok

एन -1 आयामी सरणी के लिए एक सूचक के लिए एक आयामी सरणी के क्षय की अनुमति C ++ मानक द्वारा दी जाती है , क्योंकि आप बाएं आयाम को खो सकते हैं और अभी भी N-1 आयाम जानकारी के साथ सरणी तत्वों को सही ढंग से एक्सेस करने में सक्षम हैं।

में विवरण यहाँ

हालांकि, सरणियाँ और संकेत समान नहीं हैं : एक सरणी एक सूचक में क्षय हो सकती है, लेकिन एक संकेतक उस डेटा के आकार / कॉन्फ़िगरेशन के बारे में राज्य नहीं करता है जिसके लिए वह इंगित करता है।

A char **एक मेमोरी ब्लॉक के लिए एक पॉइंटर होता है जिसमें कैरेक्टर पॉइंटर्स होते हैं , जो खुद ही कैरेक्टर्स के मेमोरी ब्लॉक की ओर इशारा करते हैं। A char [][]एकल मेमोरी ब्लॉक है जिसमें वर्ण होते हैं। यह इस बात पर प्रभाव डालता है कि कंपाइलर कोड का अनुवाद कैसे करता है और अंतिम प्रदर्शन कैसा होगा।

स्रोत

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.