2013-07-02 47 views
15

這已經困擾了我一會。很多時候,我發現自己做了一個大緩衝區來保存「最大」的數據量。這有助於避免每次下一個數據集的大小發生變化時動態分配和釋放緩衝區。訪問一維數組作爲2D陣列中的C++

例如說我有一個數組,是其實際有用的尺寸的方式過大,但我知道有用數據的長度。

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

可以說我有一個算法我想對使用二維數組索引這個數據集運行。所以,我希望能夠訪問數據如下:

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

比方說這個算法我知道,二維數組的xlength和ylength將是:

int xlength = 3; 
int ylength = 3; 

此迭代,因爲amountOfData = 9。但是,下一次迭代的長度可能會有所不同。 IE瀏覽器。他們可能是xlength = 4ylength = 4給出amountOfData = 16

我想要做一些鑄造的,讓我投用二維數組索引的一維數組。我知道我的初始1D長度有多長,這說明我的2D xlengthylength有多長,所以如果不使用newmalloc,這應該很容易實現,只要最初的100個字節足夠長以容納任何有用的數據集對我來說。

我意識到:

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

不會起作用,因爲編譯器不知道第二個維度的尺寸。但是我會在運行時知道它是什麼!

,這是什麼是它的方式是根本原因是什麼? 是否有任何解決方法? 我錯過了什麼嗎?

+1

查看[矢量](http://en.cppreference.com/w/cpp/container/vector)。 –

+0

您期望在data1D中使用哪種類型? – Amadeus

+0

@Tomas Badan我用'char's作爲例子,但是今天出現了這個問題的一個特例,當時我想訪問'unsigned char'的一維數組作爲'unsigned short'的二維數組。一維陣列吐出專有相機軟件。我想以二維像素數據的形式訪問生成的圖像。 – dinkelk

回答

4

一旦你只知道你的數組在運行時的長度,我想這是最好不要使用二維數組來解決這個問題,但是通過使用功能模仿它。例如,在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]; 
} 

...用於治療一維數組2D。

另一件事用於2D動態C數組。

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

我可以有我的行和列,雖然混合...

像其他人一樣說,向量是好的,因爲你正在使用C++:

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

如果您正在使用C++,你可以建立一個簡單的包裝,以簡化的訪問,例如:

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

隨着C你可以做類似的事情與程序或宏。 重要的是,別忘了控制預先分配的內存(1D陣列)

2

轉換不起作用的原因是你本質上試圖將2維數組轉換爲指向指向數組的指針數組的指針的字符。

On選項是創建一對適配器類,允許您像訪問實際的二維數組那樣訪問數據。這將簡化對陣列的兩個範圍的訪問,並且可以擴展用於標準庫。

#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

@Captian Oblivious當有用的數據集只有9個長時,這項工作是否會奏效?似乎當你訪問'data2d'時,它會像100x100陣列那樣對待它,而不是3x3陣列...... – dinkelk

+0

啊,不,它不會。我已經用另一種解決方案更新了我的答案。 –