2011-11-20 7 views
14
Activity solution[a][b]; 

... 

Activity **mother = solution; 

मैं 2 डी सरणी ऑब्जेक्ट्स को पॉइंटर-टू-पॉइंटर में कनवर्ट करना चाहता हूं। मैं यह कैसे कर सकता हूँ;पॉइंटर-टू-पॉइंटर

मैंने इसे Google पर खोजा। हालांकि मुझे केवल एक आयाम सरणी उदाहरण मिला।

+0

[प्रासंगिक पूछे जाने वाले प्रश्न] (http://stackoverflow.com/questions/4810664/) – fredoverflow

उत्तर

13

एक मात्र रूपांतरण आपको यहां सहायता नहीं करेगा। 2 डी सरणी प्रकार और पॉइंटर-टू-पॉइंटर प्रकार के बीच किसी भी प्रकार की कोई संगतता नहीं है। इस तरह के रूपांतरण से कोई मतलब नहीं होगा।

तुम सच में वास्तव में है कि क्या करने की जरूरत है, तो आप एक अतिरिक्त मध्यवर्ती "पंक्ति सूचकांक" सरणी है, जो 2 डी सरणी अर्थ विज्ञान और सूचक-टू-सूचक अर्थ विज्ञान

Activity solution[a][b]; 

Activity *solution_rows[a] = { solution[0], solution[1] /* and so on */ }; 

Activity **mother = solution_rows; 

अब के बीच की खाई को पाटने होगा लागू करने के लिए है mother[i][j] तक पहुंच आपको solution[i][j] तक पहुंच प्रदान करेगी।

+0

धन्यवाद। यह मेरी समस्या हल करता है –

0

आप नहीं कर सकते। वे मूल रूप से विभिन्न प्रकार हैं।

+0

आप इसे विस्तार से व्याख्या कर सकते हैं? –

+0

यदि आप 'मां' के साथ क्या करना चाहते हैं, इस बारे में अधिक जानकारी देते हैं, तो मैं आपको अपने उत्तर में एक सुझाव दे सकता हूं। –

4

मैं ऑब्जेक्ट्स के 2 डी सरणी को पॉइंटर-टू-पॉइंटर में कनवर्ट करना चाहता हूं। मैं यह कैसे कर सकता हूँ?

क्यों? क्या ऐसा इसलिए है क्योंकि एक इंटरफ़ेस पॉइंटर को पॉइंटर्स की अपेक्षा करता है?

यदि ऐसा है, तो आपको उन पॉइंटर्स वाली एक नई सरणी बनाने की आवश्यकता होगी।

Activity solution[a][b]; 

Activity* solutionPtrs[a]; 
for (int i = 0; i < a; ++i) 
    solutionPtrs[a] = solution[a]; 

Activity** mother = solutionPtrs; 

क्यों नहीं तुम सिर्फ T की एक 2 डी सरणी T** पर कास्ट कर सकते? खैर, क्योंकि उनके पास एक दूसरे के साथ कुछ लेना देना नहीं है!

आप T[a] को T* पर डाल सकते हैं क्योंकि आपको सरणी के पहले तत्व में पॉइंटर मिलता है।

साथ ही आप 2 डी सरणियों के साथ ऐसा कर सकते हैं, लेकिन अगर आप एक T[a][b] है तो यह एक (T[b])* को decays क्योंकि एक 2D सरणी संकेत की एक सरणी नहीं है, यह सरणियों की एक सरणी है।

+0

धन्यवाद। यह मेरी समस्या हल करता है –

8

कारण यह है कि आप इसे एक-आयामी सरणी के लिए कर सकते हैं और दो-आयामी सरणी को उस तरीके से नहीं करना चाहिए जिसमें वास्तविक सरणी तत्व स्मृति में संग्रहीत होते हैं। एक-आयामी सरणी के लिए, सभी तत्व लगातार संग्रहित होते हैं, इसलिए array[i] अभिव्यक्ति *(array + i) अभिव्यक्ति के समतुल्य है। जैसा कि आप देख सकते हैं, सरणी अनुक्रमणिका ऑपरेशन करने के लिए सरणी आकार की आवश्यकता नहीं है। हालांकि, द्वि-आयामी सरणी के लिए, तत्व "पंक्ति प्रमुख" क्रम में संग्रहीत होते हैं, जिसका अर्थ है कि शून्य पंक्ति में सभी तत्व पहले संग्रहित होते हैं, इसके बाद पहली पंक्ति में तत्वों के बाद, दूसरी पंक्ति में तत्वों के बाद , आदि। इसलिए, अभिव्यक्ति array[i][j]*(array + (i * ROW_SIZE) + j) के बराबर है, जहां ROW_SIZE प्रत्येक पंक्ति में तत्वों की संख्या है। इसलिए, एरे इंडेक्स ऑपरेशन करने के लिए सरणी की पंक्ति आकार की आवश्यकता होती है, और एक पॉइंटर में सरणी चर कास्टिंग उस जानकारी को खो देता है।

0

सुनिश्चित नहीं है कि आप इस तरह कुछ ढूंढ रहे हैं। आप जो हासिल करना चाहते हैं उसके बारे में आपको अधिक जानकारी प्रदान करनी चाहिए। वे मूल रूप से विभिन्न प्रकार हैं। एक समाधान नीचे है।

रिकॉर्ड के लिए, अगर किसी को यह उपयोगी पाता है:

// define matrix 
double A[3][3] = { 
    { 1, 2, 3}, 
    { 4, 5, 6}, 
    { 7, 8, 9} 
}; 

// allocate memory 
double ** A_ptr = (double **) malloc(sizeof (double *) * 3); 
for (int i = 0; i < 3; i++) 
    A_ptr[i] = (double *) malloc(sizeof (double) * 3); 

// copy matrix 
for (int i = 0; i < 3; i++) { 
    for (int j = 0; j < 3; j++) { 
     A_ptr[i][j] = A[i][j]; 
     printf(" %f ", A_ptr[i][j]); 
    } 
} 
3

यह है! सब कुछ संभव है! लेकिन यह है इसलिए इसे समझने के कुछ स्तर की आवश्यकता है। char firstName[4] = { 'J', 'o', 'n', '\0' } और char lastName[4] = { 'M', 'e', 'e', '\0' } के एक संभव स्मृति लेआउट यहाँ पर नजर डालते हैं:

+------------+-------+ 
| Address | Value | 
+------------+-------+ 
| 0x| 0x4A | <- firstName[0] - 'J' 
| 0x76543211 | 0x6F | <- firstName[1] - 'o' 
| 0x76543212 | 0x6E | <- firstName[2] - 'n' 
| 0x76543213 | 0x00 | <- firstName[3] - '\0' 
+------------+-------+ 
| 0x76543214 | 0x4D | <- lastName[0] - 'M' 
| 0x76543215 | 0x65 | <- lastName[1] - 'e' 
| 0x76543216 | 0x65 | <- lastName[2] - 'e' 
| 0x76543217 | 0x00 | <- lastName[3] - '\0' 
+------------+-------+ 

इस स्मृति लेआउट को देखते हुए अगर आप cout << firstName << ' ' << lastName तुम क्या करने थे

कि अंत करने के लिए 2 1-आयामी सरणियों का एक सरल उदाहरण के साथ शुरू करते हैं 'प्राप्त डी:

0x0x76543214

इन ar किरणें वास्तव में सिर्फ अपने पहले तत्व के लिए एक सूचक हैं! इस सूचक क्षय करने के लिए सरणी जिसे आप यहां के बारे में अधिक पढ़ सकते हैं दिखाता है: http://en.cppreference.com/w/cpp/language/array#Array-to-pointer_decay

इससे पहले कि हम ले जाने के कुछ यहाँ याद रखना आवश्यक है है पर, char रों इसलिए सरणी में प्रत्येक अनुवर्ती char का पता ठीक वैसे ही 1-बाइट तक का समय लग जाएगा बस अगला पता हो। Subscript Operator द्वारा इस तरह से लीवरेज किया गया है: firstName[1]*(firstName + 1) के बराबर है। यह char एस के लिए सच है लेकिन यह किसी अन्य प्रकार के लिए भी सच है जो 1-बाइट से अधिक लेता है। के उदाहरण के लिए लेते हैं:

+------------+--------+ 
| Address | Value | 
+------------+--------+ 
| 0x76543218 | 0x0001 | <- siArray[0] - 1 
| 0x7654321A | 0x0002 | <- siArray[1] - 2 
| 0x7654321C | 0x0003 | <- siArray[2] - 3 
| 0x7654321E | 0x0004 | <- siArray[3] - 4 
+------------+--------+ 

हालांकि cout << siArray << ' ' << &(siArray[1]) इच्छा उत्पादन:

0x76543218 0x7654321A

*(siArray + 1) अब भी एक ही होगा short siArray = { 1, 2, 3, 4 }, siArray के संभावित स्मृति लेआउट कैसा लगेगा siArray का तत्व siArray[1] के रूप में। ऐसा इसलिए है क्योंकि पॉइंटर अंकगणित पर हस्ताक्षर किए जाने वाले पते के प्रकार पर विचार किया जाता है, इस प्रकार short* में वृद्धि करने से वास्तव में sizeof(short) द्वारा पता बढ़ जाएगा। आप पॉइंटर अंकगणितीय के बारे में अधिक पढ़ सकते हैं: http://en.cppreference.com/w/cpp/language/operator_arithmetic

आखिरकार देखते हैं कि कैसे स्टोर 2-आयामी सरणी। यह देखते हुए: char name[2][4] = { { 'J', 'o', 'n', '\0' }, { 'M', 'e', 'e', '\0' } } एक संभव स्मृति लेआउट होगा:

+------------+-------+ 
| Address | Value | 
+------------+-------+ 
| 0x76543220 | 0x4A | <- name[0][0] - 'J' 
| 0x76543221 | 0x6F | <- name[0][1] - 'o' 
| 0x76543222 | 0x6E | <- name[0][2] - 'n' 
| 0x76543223 | 0x00 | <- name[0][3] - '\0' 
| 0x76543224 | 0x4D | <- name[1][0] - 'M' 
| 0x76543225 | 0x65 | <- name[1][1] - 'e' 
| 0x76543226 | 0x65 | <- name[1][2] - 'e' 
| 0x76543227 | 0x00 | <- name[1][3] - '\0' 
+------------+-------+ 

के बाद से हम जानते हैं कि एक 1-आयामी सरणी मान वास्तव में सिर्फ एक सूचक है, हम इस स्मृति लेआउट से देख सकते हैं कि name[0] एक सूचक नहीं है, यह सिर्फ है पहली सरणी का पहला अक्षर। इस प्रकार name में 2 1-आयामी सरणी पॉइंटर्स नहीं हैं, लेकिन इसमें 2 सरणी की सामग्री शामिल है। (आकस्मिक रूप से 32-बिट मशीन पर पॉइंटर्स को संग्रहीत नहीं किया जाता है, जो 8-बाइट मेमोरी बचाता है, जो 8-बाइट 2-आयामी सरणी के लिए काफी महत्वपूर्ण है।) name को char** के रूप में इलाज करने का प्रयास करने वाले वर्णों को एक सूचक।


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

const short si2DArray[2][3] = { { 11, 12, 13 }, { 21, 22, 23 } }; 
const auto psi2DPointer = reinterpret_cast<const char*>(si2DArray); 

for(auto i = 0U; i < size(si2DArray); ++i) { 
    for(auto j = 0U; j < size(*si2DArray); ++j) { 
     cout << *reinterpret_cast<const short*>(psi2DPointer + i * sizeof(*si2DArray) + j * sizeof(**si2DArray)) << '\t'; 
    } 
    cout << endl; 
} 

Live Example

ध्यान दें कि यह उदाहरण भले ही मैंने संदर्भ में si2DArray सोचा psi2DPointer: है कि हम इतना है कि जोड़ने 1 वास्तव में सिर्फ उदाहरण के लिए 1. जोड़ रहा है तो एक char* के साथ काम करने की आवश्यकता होगी ऐसा करने के लिए मैं अभी भी si2DArray से जानकारी का उपयोग कर रहा अनुक्रमण करने के लिए, अर्थात्:

  1. कितने सरणियों प्रमुख आयाम में कर रहे हैं: size(si2DArray)
  2. ,210
  3. कितने तत्वों नाबालिग आयाम में कर रहे हैं: size(*si2DArray)
  4. क्या नाबालिग आयाम की स्मृति में आकार है: sizeof(**si2DArray)

आप इस प्रकार देख सकते हैं: sizeof(*si2DArray)

  • क्या सरणी के तत्व प्रकार है कि एक सरणी से एक सूचक में कनवर्ट करने से जानकारी का नुकसान पर्याप्त है। आप तत्व प्रकार को संरक्षित करने के लिए लुभाने वाले हो सकते हैं, जिससे पॉइंटर अंकगणित को सरल बना दिया जा सके। यह नोट करना reinterpret_cast से है कि केवल char* में रूपांतरण परिभाषित व्यवहार माना जाता है फ़ायदेमंद हो सकता है: http://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing

  • +0

    धन्यवाद आपके समाधान के लिए जोनाथन बहुत है। क्या आप इस रूपांतरण से जुड़े ओवरहेड को जानते हैं? और "रूपांतरण पर्याप्त है" से आपका क्या मतलब है? – khateeb