2015-11-28 42 views
0

如何從char**** first將所有內容複製到連續變量:char* second而不使用嵌套循環?將char ****作爲連續數據複製到char *變量

例如,我可以爲循環,即是這樣使用嵌套:

for (size_t a=0; a < sizeof(***first); a++) { 
    for (size_t b=0; b < sizeof(**first); b++) { 
     //etc 
    } 
} 

我只是想知道,如果這是可能的。

+2

我甚至不會問你爲什麼要那麼做......我只想指出,這些'sizeof'總是返回同樣的事情(指針** **類型的大小),而不是它指向的實際數據量。 – VillasV

+1

sizeof在這裏絕對沒用。您需要知道每個維度的實際元素數量。 –

+0

每一次的sizeof消耗更多的時間 –

回答

1

IFF你知道多維數組的個體大小,你可以在一個循環中將數組展平。應該指出,雖然你可能實際上並沒有看到一個循環中的數組在一個循環中展平的性能增加,而有一些嵌套循環;它可以依賴於編譯器優化(如向量化)和平臺/體系結構,如果您必須確定每個嵌套數組的大小,則會在大循環頂部發生性能問題。 YMMV,所以最好做一些小規模的基準測試來驗證它達到你想要的結果和性能。

以下是關於如何平鋪數組的一些示例代碼;請注意,在本例中我使用的是std::string類型,所以您可以運行代碼並打印到文件/標準輸出以查看陣列確實已平坦化。

#include <iostream> 
#include <string> 
#include <sstream> 

void flatten(std::string**** first, int len_a, int len_b, int len_c, int len_d, std::string* second) 
{ 
    int i, a, b, c, d; 
    int max_len = len_a * len_b * len_c * len_d; 
    a = b = c = d = -1; 
    for (i = 0; i < max_len; ++i) { 
     d = (i % len_d); 
     // if all lengths were equal, you could further optimize this loop 
     if (d == 0) { 
      ++c; 
      if ((c % len_c) == 0) { 
       c = 0; 
       ++b; 
       if ((b % len_b) == 0) { 
        b = 0; 
        ++a; 
       } 
      } 
     } 
     second[i] = first[a][b][c][d]; 
    } 
} 

int main() 
{ 
    const int len_a = 11; 
    const int len_b = 22; 
    const int len_c = 33; 
    const int len_d = 44; 
    const int max_len = len_a * len_b * len_c * len_d; 
    // create the arrays 
    std::string**** first = new std::string***[len_a]; 
    std::string* second = new std::string[max_len]; 
    for (int i1 = 0; i1 < len_a; ++i1) { 
     first[i1] = new std::string**[len_b]; 
     for (int i2 = 0; i2 < len_b; ++i2) { 
      first[i1][i2] = new std::string*[len_c]; 
      for (int i3 = 0; i3 < len_c; ++i3) { 
       first[i1][i2][i3] = new std::string[len_d]; 
       for (int i4 = 0; i4 < len_d; ++i4) { 
        std::stringstream ss; 
        ss <<"["<<i1<<"]["<<i2<<"]["<<i3<<"]["<<i4<<"]"; 
        first[i1][i2][i3][i4] = ss.str(); // or what have you 
       } 
      } 
     } 
    } 

    // flatten the multidimensional array 'first' into the array 'second' 
    flatten(first, len_a, len_b, len_c, len_d, second); 

    // print it 
    for (int i1 = 0; i1 < max_len; ++i1) { 
     std::cout<<"second["<<i1<<"] = "<<second[i1]<<std::endl; 
    } 

    // clean up 
    delete[] second; 
    for (int i1 = 0; i1 < len_a; ++i1) { 
     for (int i2 = 0; i2 < len_b; ++i2) { 
      for (int i3 = 0; i3 < len_c; ++i3) { 
       delete[] first[i1][i2][i3]; 
      } 
      delete[] first[i1][i2]; 
     } 
     delete[] first[i1]; 
    } 
    delete[] first; 
    return 0; 
} 

同樣,這顯然不是一個安全/清潔/高效的做你正在尋找的方法,但我只是想證明你可以做到這一點,我會留下進一步提高效率/實現細節給你。

我希望能有所幫助。

2

你似乎對sizeof有什麼嚴重的誤解。

sizeof(x)返回對象x字節的大小。當處理指針sizeof(*x)通常不會與相同x指向的元素的數目。

還要注意的是,在您使用的情況下,sizeof(x)是一個值在決定編譯時sizeof(*x)甚至不看什麼x指向(只看起來是什麼的的類型對象x指向:例如int *x = NULL;,表達sizeof(*x)sizeof(int)相同)。

而且你需要了解的多維陣列的int S之間的差:一個int

int x[10][10]; 

和指針的指針:

int **y; 

即使二者皆可使用相同的語法解除引用

x[1][2] = 42; 
y[1][2] = 42; 

的含義與完全不同。更具體地例如y[0]y[1]和可以指向(第一元件)的不同大小的陣列,它們可以是NULL或者可以指向單一整數(y[0]y[1]和甚至可以指向相同的對象)。

沒有辦法到指針的指針的數據結構拷貝到一個多維陣列,而不循環,因爲這兩者是在與一個完全不同類型形狀的一般對象。

+0

是的,你對'sizeof'運營商是正確的。我寫的代碼懶洋洋地和沒有太多的考慮,以便通過@txtechhelp在我實現的代碼提示,我會代替'與常量sizeof'運營商。 – benardier