একটি সি ++ ফাংশনে একটি 2 ডি অ্যারে পাস করা


324

আমার একটি ফাংশন রয়েছে যা আমি নিতে চাই, প্যারামিটার হিসাবে, ভেরিয়েবল সাইজের 2D অ্যারে।

এখন পর্যন্ত আমার কাছে এটি রয়েছে:

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

এবং আমি আমার কোডে অন্যত্র অ্যারে ঘোষণা করেছি:

double anArray[10][10];

তবে কলিং myFunction(anArray)আমাকে ত্রুটি দেয়।

অ্যারেটি পাস করার সময় আমি অ্যারে অনুলিপি করতে চাই না in যে কোনও পরিবর্তনগুলি myFunctionএর অবস্থার পরিবর্তন করে anArray। যদি আমি সঠিকভাবে বুঝতে পারি তবে আমি কেবল 2D অ্যারেতে পয়েন্টার হিসাবে আর্গুমেন্ট হিসাবে যেতে চাই। ফাংশনটির জন্য বিভিন্ন আকারের অ্যারে গ্রহণ করা দরকার। সুতরাং উদাহরণস্বরূপ, [10][10]এবং [5][5]। কিভাবে আমি এটি করতে পারব?


1
প্যারামিটার 3 কে 'ডাবল [10] [10]' থেকে 'ডাবল **' তে রূপান্তর করতে পারে না
রজারডারউইন

3
গৃহীত উত্তর শো শুধুমাত্র 2 কৌশল [তার (2) এবং (3) একই] কিন্তু সেখানে থাকেন একটি ফাংশন করার জন্য একটি 2D অ্যারে ক্ষণস্থায়ী 4 অনন্য উপায়ে
কিংবদন্তি 2 কে

কড়া কথায় বলতে গেলে, হ্যাঁ, তারা 2 ডি অ্যারে নয়, তবে এই কনভেনশন (পয়েন্টারগুলির অ্যারে থাকার পরেও, প্রতিটি পয়েন্টার (1 ডি) অ্যারে রয়েছে) প্রচলিত বলে মনে হচ্ছে :( এমএক্সএন এর সমতল 1D অ্যারে থাকা) দৈর্ঘ্য, 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. পরামিতি পয়েন্টার সমন্বিত একটি অ্যারে is

    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
@ ওভারফ্লো আপনি এর arrayসাথে উপাদানগুলি পেতে পারেন array[i][j]:)
শেঞ্জি

14
1 ম ক্ষেত্রে, প্যারামিটার হিসাবে ঘোষণা করা যেতে পারে int (*a)[10]
জাচারি

9
২ য় ক্ষেত্রে, প্যারামিটারটি হিসাবে ঘোষণা করা যেতে পারে int **
জাচরী

1
@ জ্যাক: আপনি ঠিক বলেছেন, সেখানে দুটি মাত্র ঘটনা রয়েছে; একটি হ'ল একটি পয়েন্টার-টু-পয়েন্টার এবং অন্যটি হ'ল এন এর আকারের পূর্ণসংখ্য অ্যারেতে একক পয়েন্টার int (*a) [10]
কিংবদন্তি

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

সি ++ তে মাত্রা সম্পর্কিত তথ্য না হারিয়ে রেফারেন্স দিয়ে অ্যারে পাস করা সম্ভবত সবচেয়ে নিরাপদ, যেহেতু কলারকে একটি ভুল মাত্রা (অমিলের সময় সংকলক পতাকাগুলি) পাস করার বিষয়ে চিন্তা করার দরকার নেই। তবে গতিশীল (ফ্রিস্টোর) অ্যারে দিয়ে এটি সম্ভব নয়; এটি কেবল স্বয়ংক্রিয়ভাবে ( সাধারণত স্ট্যাক-লিভিং ) অ্যারেগুলির জন্য কাজ করে, মাত্রাটি সংকলনের সময় জানা উচিত।

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)

পরিবর্তনশীল আকার

এগুলি সি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত তবে কম নিরাপদ, সংকলকটির কাছে পরীক্ষা করার কোনও উপায় নেই, গ্যারান্টি দিয়ে যে কলার প্রয়োজনীয় মাত্রাটি পার করছে। ফাংশনটি কেবলমাত্র কলার যা মাত্রা (গুলি) হিসাবে পাস করে তার উপর ব্যাঙ্ক করে। এগুলি উপরোক্তগুলির তুলনায় আরও নমনীয় কারণ বিভিন্ন দৈর্ঘ্যের অ্যারে তাদের কাছে অবিচ্ছিন্নভাবে দেওয়া যেতে পারে।

এটি মনে রাখতে হবে যে সিতে কোনও ক্রিয়াকলাপে সরাসরি অ্যারে পাস করার মতো কোনও বিষয় নেই [সি ++ থাকা অবস্থায় এগুলি রেফারেন্স হিসাবে (1) ] পাস করা যেতে পারে ; (২) অ্যারেতে একটি পয়েন্টার দিয়ে যাচ্ছে এবং অ্যারে নিজেই নয়। সর্বদা যেমন বিন্যাসকে যেমন করা হয় তেমন পয়েন্টার-অনুলিপি অপারেশন হয়ে যায় যা অ্যারে এর বিন্দুতে ক্ষয় হওয়ার প্রকৃতি দ্বারা সহজতর হয় ।

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) হ'ল ন্যূনতম সুরক্ষিত বিকল্প কারণ এটির মধ্যে কোনও ধরণের চেক এবং খুব অসুবিধা নেই। কেউ এই ফাংশনে বৈধভাবে 2D অ্যারে পাস করতে পারবেন না; সি-এফএকিউ স্বাভাবিক ক্রিয়াকলাপটিকে নিন্দা করে 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**
}

সি ++ এ ফাংশনে গতিশীল বরাদ্দকৃত অ্যারেগুলি পাস করার বিষয়ে কী? সি 11 স্ট্যান্ডার্ডে এটি স্ট্যাটিকাল এবং ডায়নামিকভাবে বরাদ্দ করা অ্যারেগুলির জন্য করা যেতে পারে যেমন এফএন (ইন্টি করল, ইনট সারি, ইনট অ্যারে [কোল] [সারি]): স্ট্যাকওভারফ্লো / প্রশ্ন / 16004668/ … এই সমস্যার জন্য আমি প্রশ্নটি তৈরি করেছি : stackoverflow.com/questions/27457076/...
42n4

@ 42n4 কেস 4 কভার (সি ++ এর জন্যও) যেটি। গতিশীলভাবে বরাদ্দ করা অ্যারেগুলির জন্য, লুপের ভিতরে কেবল রেখাটি পরিবর্তিত হয়ে b[i] = a[i];বলবে, বলুন b[i] = new int[10];। কেউ bगतिशीलভাবে বরাদ্দও করতে পারে int **b = int *[5];এবং এটি এখনও যেমন রয়েছে তেমন কাজ করবে।
কিংবদন্তি

1
কীভাবে সম্বোধন 4 এ ফাংশনটিতে array[i][j]কাজ করে ? কারণ এটি পিটিআর থেকে পিটিআর পেয়েছে এবং শেষ মাত্রার মানটি জানে না, যা সঠিক ঠিকানার জন্য একটি শিফ্ট সম্পাদন করা প্রয়োজন?
ব্যবহারকারী 1234567

2
array[i][j]পয়েন্টার মান ঠিক পয়েন্টার এরিথমেটিক অর্থাৎ array, এটি যোগ চাই iএবং ফলাফলের dereference 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

উত্তরে উপরের জর্গ কোডটি আমি যা প্রস্তাব করেছি ঠিক তেমনটাই। এটি জিসিসি 6.3 - অনলাইন ডেমোতে কাজ করে । আপনি কি পরামিতিটি একটি রেফারেন্স তৈরি করতে ভুলে গেছেন?
কিংবদন্তি

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
এটি সঠিক উত্তর হওয়া উচিত। এটি উল্লিখিত সমস্ত সমস্যা সমাধান করে এবং কিছু যা এখানে উল্লেখ করা হয়নি। সুরক্ষা টাইপ করুন, অ্যারের সংকলনের সময় অসঙ্গতি, কোনও পয়েন্টার পাটিগণিত নেই, টাইপ কাস্টিং নেই, কোনও ডেটা অনুলিপি করা হচ্ছে না। সি এবং সি ++ এর জন্য কাজ করে।
ওপাল অ্যাপস

আচ্ছা, এটি সি ++ এর জন্য কাজ করে; সি টেমপ্লেট সমর্থন করে না। সি তে এটি করার জন্য ম্যাক্রোগুলির প্রয়োজন হবে।
গুনার

এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। ধন্যবাদ!
সুনীত গৌতম

20

আপনি এটির মতো কোনও ফাংশন টেম্পলেট তৈরি করতে পারেন:

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

তারপরে আর এবং সি এর মাধ্যমে আপনার উভয় মাত্রার আকার রয়েছে প্রতিটি প্রতিটি অ্যারের আকারের জন্য একটি পৃথক ফাংশন তৈরি করা হবে, তাই যদি আপনার ফাংশনটি বড় হয় এবং আপনি বিভিন্ন ধরণের অ্যারে আকারের সাথে এটি কল করেন তবে এটি ব্যয়বহুল হতে পারে। আপনি এটিকে কোনও ফাংশন জুড়ে মোড়ক হিসাবে ব্যবহার করতে পারেন যদিও:

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]) {
}

তবে এটি আপনাকে দশ ছাড়া অন্য শেষ মাত্রার সাথে অ্যারে পাস করতে দেবে না।

সি ++ এর সেরা সমাধানটি হ'ল std::vector<std::vector<double> >: এটি প্রায় তত দক্ষ এবং উল্লেখযোগ্যভাবে আরও সুবিধাজনক।


1
আমি এই সমাধানটি পছন্দ করি যেহেতু std গ্রন্থাগারটি খুব দক্ষ - যেভাবে আমি ড্যাসব্লিংকনলাইট পছন্দ করি; আমি ড্যাসব্লিকেনলিচ্ট ব্যবহার করতাম
মোজিলনার্ড

প্রায় দক্ষ হিসাবে? হ্যাঁ ঠিক. পয়েন্টার তাড়া করা সর্বদা পয়েন্টার ছাড়ার চেয়ে ব্যয়বহুল।
থমাস এডিং

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
আই ভ্যারিয়েবলটি অবশ্যই কলাম দ্বারা গুণিত করতে হবে, সারি দ্বারা নয় যতক্ষণ না কলাম এবং সারি এই ক্ষেত্রে সমান হয়
অ্যান্ড্রে চেরুনুখা

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

একটি ফাংশনে 2D অ্যারে পাস করার জন্য আমরা বিভিন্ন উপায় ব্যবহার করতে পারি:

  • একক পয়েন্টার ব্যবহার করে আমাদের 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;
    }
  • ডাবল পয়েন্টার ব্যবহার করে এইভাবে, আমরা 2 ডি অ্যারেও টাইপকাস্ট করি

    #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. একটি একক পয়েন্টার ব্যবহার : এই পদ্ধতিতে, ফাংশনে যাওয়ার সময় আমাদের অবশ্যই 2D অ্যারে টাইপকাস্ট করতে হবে।

`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

এটি করতে আপনি সি ++ তে টেম্পলেট সুবিধা ব্যবহার করতে পারেন। আমি এরকম কিছু করেছি:

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 ফাংশন সংজ্ঞা তৈরি করতে দুটি বার টেমপ্লেট ইনস্ট্যান্ট করে (যেখানে কোল = 3 এবং কোল = 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

N-1 মাত্রিক অ্যারেতে নির্দেশকের কাছে একটি N মাত্রিক অ্যারের ক্ষয় সি ++ স্ট্যান্ডার্ড দ্বারা অনুমোদিত , আপনি বাম দিকের মাত্রাটি হারাতে পারেন এবং এখনও এন -1 মাত্রিক তথ্য দিয়ে অ্যারে উপাদানগুলিতে সঠিকভাবে অ্যাক্সেস করতে সক্ষম হচ্ছেন।

বিস্তারিত এখানে

যদিও, অ্যারে এবং পয়েন্টার এক নয় : একটি অ্যারে একটি পয়েন্টারে ক্ষয় করতে পারে তবে পয়েন্টারটি যে বিন্দুতে এটি নির্দেশ করে সেগুলির আকার / কনফিগারেশন সম্পর্কে রাষ্ট্র বহন করে না।

char **অক্ষর পয়েন্টারযুক্ত মেমরি ব্লকের একটি পয়েন্টার , যা তারা নিজেরাই অক্ষরের মেমরি ব্লকগুলিকে নির্দেশ করে। char [][]একটি একক মেমরি ব্লক যা অক্ষর ধারণ করে। সংকলক কোডটি কীভাবে অনুবাদ করে এবং চূড়ান্ত কার্য সম্পাদন কীভাবে হবে তার উপর এটির প্রভাব রয়েছে।

সূত্র

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.