2013-07-02 2 views
15

में 2 डी सरणी के रूप में 1 डी सरणी तक पहुंचें इसने मुझे थोड़ी देर तक परेशान किया है। कई बार मैं खुद को "अधिकतम" डेटा रखने के लिए एक बड़ा बफर बना रहा हूं। यह मुझे अगले डेटा सेट के आकार में प्रत्येक बार गतिशील रूप से आवंटित करने और एक बफर को हटाने से बचने में मदद करता है।सी ++

उदाहरण के लिए कहें कि मेरे पास एक सरणी है जो अपने वास्तविक उपयोगी आकार के लिए बहुत बड़ी है, लेकिन मुझे उपयोगी डेटा की लंबाई पता है।

int amountOfData = 9; 
char data1D[100] = some data that is only 9 bytes long stored in a 100 byte array 

आइए कहें कि मेरे पास एक एल्गोरिदम है जो मैं इस डेटा सेट पर चलाना चाहता हूं जो 2 डी सर इंडेक्सिंग का उपयोग करता है। इसलिए मैं डेटा का उपयोग करने में सक्षम होने के रूप में निम्नानुसार हैं:

int xlength = 3; 
int ylength = 3; 
इस के लिए

:

cout << "I am accessing this data as a 2D array: " << data1D[0][1] << endl; 

इस एल्गोरिथ्म के लिए कहते हैं कि मुझे पता है कि xlength और 2 डी सरणी के ylength होने जा रहे हैं की सुविधा देता है पुनरावृत्ति, क्योंकि amountOfData = 9। हालांकि, अगले पुनरावृत्ति के लिए लंबाई अलग हो सकती है। अर्थात। वे xlength = 4 और ylength = 4amountOfData = 16 दिए जा सकते हैं।

मैं कुछ प्रकार का कास्टिंग करना चाहता हूं जो मुझे 2 डी सरणी का उपयोग करके 1 डी सरणी डालने की अनुमति देता है। मुझे पता है कि मेरी शुरुआती 1 डी लंबाई कितनी देर तक है, जो मुझे बताती है कि मेरे 2 डी xlength और ylength कितने समय तक हैं, इसलिए new या malloc का उपयोग किये बिना यह करना आसान होना चाहिए जब तक प्रारंभिक 100 बाइट्स किसी भी उपयोगी डेटा सेट को पकड़ने के लिए पर्याप्त नहीं हैं मेरे लिए।

मुझे लगता है कि:

char** data2d = (char**) data1D; 

क्योंकि संकलक दूसरे आयाम के आकार पता नहीं है काम नहीं करेगा। लेकिन मुझे पता चलेगा कि रनटाइम पर क्या है!

इस तरह के लिए इसका मूल कारण क्या है? क्या कोई कामकाज है? क्या मुझे कुछ याद आ रही है?

+1

[वैक्टर] पर गौर करें (http://en.cppreference.com/w/cpp/container/vector)। –

+0

डेटा 1 डी में आप किस प्रकार के प्रकार का उपयोग करने की उम्मीद कर रहे हैं? – Amadeus

+0

@ टोमास बदन मैंने 'char' उदाहरणों के रूप में उपयोग किया, लेकिन इस समस्या का एक विशिष्ट मामला आज उठ गया जब मैं 'हस्ताक्षरित चार' की एक डीडी सरणी को 'हस्ताक्षरित शॉर्ट' के 2 डी सरणी के रूप में एक्सेस करना चाहता था। 1 डी सरणी मालिकाना कैमरा सॉफ्टवेयर से बाहर थूक गया था। मैं परिणामी छवि को 2 डी पिक्सेल डेटा के रूप में एक्सेस करना चाहता हूं। – dinkelk

उत्तर

4

एक बार जब आप केवल रनटाइम पर अपने सरणी की लंबाई पता है, मैं यह इस समस्या को हल करने के लिए एक 2 डी सरणी का उपयोग नहीं कर बेहतर है लगता है, लेकिन कार्यों का उपयोग करके इसे नकल। उदाहरण के लिए, C:

char data1D[1000] = {0}; 

unsigned int getElement(unsigned int x, unsigned int y, 
      unsigned int xMax, unsigned int yMax) 
{ 
    // Do some error tests 
    return ((unsigned int *) data1D)[x*xMax + y]; 
} 
1

आप अपनी पंक्ति/स्तंभ लंबाई पता है (पंक्ति या स्तंभ प्रमुख और नहीं क्या पर निर्भर करता है) ... मेरा मानना ​​है कि यह कुछ है की तरह ...

char get_value(char *arr, int row_len, int x, int y) { 
    return arr[x * row_len + y]; 
} 

... के रूप में एक 1 डी सरणी के इलाज के लिए 2 डी।

2 डी गतिशील सी सरणी के लिए एक और चीज।

char **arr = (char **)malloc(row_size * sizeof(char *)); 
int x; 
for (x = 0; x < row_size; ++x) { 
    arr[x] = (char *)malloc(col_size * sizeof(char)); 
} 

मैं

हर किसी की तरह ने कहा है कि मेरी स्तंभों और पंक्तियों हालांकि मिश्रित हो सकता था ..., वैक्टर अच्छा जब से तुम सी ++ का उपयोग कर रहे हैं:

auto matrix_like_thing = std::vector<std::vector<char> >(rows, std::vector<char>(cols, '\0')); 
matrix_like_thing[0][4] = 't'; 
1

आप उपयोग कर रहे हैं सी ++, आप उदाहरण के लिए एक पहुँच आसान बनाने के लिए, एक सरल आवरण का निर्माण कर सकते हैं:

template <typename T> 
class A2D { 
    T *m_buf; 
    size_t m_n; 
    size_t m_m; 
public: 
    A2D(T *buf, const size_t &n, const size_t &m) 
     : m_buf(buf), m_n(n), m_m(m) { } 
    ~A2D() { } 

    T& operator()(const size_t &i, const size_t &j) 
    { 
     return *(this->m_buf + i * this->m_m + j); 
    } 
}; 

उपयोग:

int main() 
{ 
    int *a = new int[16]; 
    for (int i = 0; i < 16; ++i) { 
     a[i] = i; 
    } 
    A2D<int> b(a, 4, 4); 

    for (int i = 0; i < 4; ++i) { 
     for (int j = 0; j < 4; ++j) { 
      std::cout << b(i, j) << ' '; 
     } 
     std::cout << '\n'; 
    } 
} 

सी के साथ आप प्रक्रियाओं या मैक्रोज़ के साथ समान चीजें कर सकते हैं। महत्वपूर्ण रूप से, पूर्व आबंटित स्मृति (1 डी सरणी) को नियंत्रित करने के लिए मत भूलना

2

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

विकल्प पर कुछ एडाप्टर कक्षाएं बनाना है जो आपको डेटा तक पहुंचने की अनुमति देता है जैसे कि यह वास्तविक दो आयामी सरणी थी। यह सरणी के दोनों विस्तारों तक पहुंच को सरल बना देगा और मानक पुस्तकालय के उपयोग के लिए बढ़ाया जा सकता है।

#include <iostream> 
#include <sstream> 
#include <utility> 

template <typename Type, size_t DataSize> 
class MDArray 
{ 
public: 

    struct SDArray 
    { 
     SDArray(Type* data, size_t size) : data_(data), size_(size) {} 
     SDArray(const SDArray& o) : data_(o.data), size_(o.size_) {} 

     size_t size() const { return size_; }; 

     Type& operator[](size_t index) 
     { 
      if(index >= size_) 
       throw std::out_of_range("Index out of range"); 

      return data_[index]; 
     } 

     Type operator[](size_t index) const 
     { 
      if(index >= size_) 
       throw std::out_of_range("Index out of range"); 

      return data_[index]; 
     } 

    private: 

     SDArray& operator=(const SDArray&); 
     Type* const  data_; 
     const size_t size_; 
    }; 

    MDArray(const Type *data, size_t size, size_t dimX, size_t dimY) 
     : dimX_(dimX), dimY_(dimY) 
    { 
     if(dimX * dimY > DataSize) 
      throw std::invalid_argument("array dimensions greater than data size"); 

     if(dimX * dimY != size) 
      throw std::invalid_argument("data size mismatch"); 

     initdata(data, size); 
    } 

    size_t size() const { return dimX_; }; 
    size_t sizeX() const { return dimX_; }; 
    size_t sizeY() const { return dimY_; }; 

    SDArray operator[](const size_t &index) 
    { 
     if(index >= dimY_) 
      throw std::out_of_range("Index out of range"); 

     return SDArray(data_ + (dimY_ * index), dimX_); 
    } 

    const SDArray operator[](const size_t &index) const 
    { 
     if(index >= dimY_) 
      throw std::out_of_range("Index out of range"); 

     return SDArray(data_ + (dimY_ * index), dimX_); 
    } 

private: 

    void initdata(const Type* data, size_t size) 
    { 
     std::copy(data, data + size, data_); 
    } 
    MDArray(const MDArray&); 
    MDArray operator=(const MDArray&); 

    Type   data_[DataSize]; 
    const size_t dimX_; 
    const size_t dimY_; 
}; 


int main() 
{ 
    char data[] = "123456789"; 
    MDArray<char, 100> md(data, 9, 3, 3); 


    for(size_t y = 0; y < md.sizeY(); y++) 
    { 
     for(size_t x = 0; x < md.sizeX(); x++) 
     { 
      std::cout << " " << md[y][x]; 
     } 
     std::cout << std::endl; 
    } 

    std::cout << "-------" << std::endl; 

    for(size_t y = 0; y < md.size(); y++) 
    { 
     const auto& sd = md[y]; 
     for(size_t x = 0; x < sd.size(); x++) 
     { 
      std::cout << " " << sd[x]; 
     } 
     std::cout << std::endl; 
    } 

    std::cout << "-------" << std::endl; 

    for(size_t y = 0; y < md.size(); y++) 
    { 
     auto sd = md[y]; 
     for(size_t x = 0; x < sd.size(); x++) 
     { 
      std::cout << " " << sd[x]; 
     } 
     std::cout << std::endl; 
    } 
} 
+0

@ कैप्टन Oblivious यह काम करेगा जब उपयोगी डेटा सेट केवल 9 लंबा है? ऐसा लगता है कि जब आप 'data2d' तक पहुंचते हैं तो यह 100x100 सरणी की तरह व्यवहार करेगा, न कि 3x3 सरणी ... – dinkelk

+0

आह, नहीं, यह नहीं होगा। मैंने एक वैकल्पिक समाधान के साथ अपना जवाब अपडेट कर दिया है। –