2016-09-26 93 views
0

我需要根據用戶的輸入存儲一些數據。我的程序應該根據我從cin得到的int值創建不同的數據結構。如何用用戶指定的尺寸創建矩陣

例如,0存儲一個標量的值,1 - 矢量,2 - 2dArray,3 - 3dArray,4 - 四維陣列等等...

我的問題是,是否有可能編寫一些代碼將做到這一點。

我知道這可能聽起來很混亂,所以我會再提供一些例子。假設用戶輸入0 5,那麼我的程序應該創建一個int變量並存儲5個變量。

如果用戶輸入1 5,7,6,我的程序應該創建一個vector = {5,7,6};

如果用戶輸入2 2,3 1,2,3,4,5,6我的程序應該創建一個2d數組a [2] [3]並將值存儲在那裏。

我能想出一個解決方案,如果我知道尺寸的用戶都將有最大數量,但分配的目標是,可以指定任意數量的維度......

請幫助

+1

嗯,不,這是不可能的,除非你定義維數的限制,因爲它將無限遞歸(一個n維數組是一個(n-1)維數組的數組,所以做你的想要一個無限遞歸的類型定義,除非你指定了一個邊界)。你可以做的是使用單維數組(或矢量)和管理索引來模擬你所尋找的行爲。實際上,很少有真實應用程序需要10個或更多維度,而且這樣的陣列的內存使用量將很快超過可用內存。 – Peter

+0

我也在考慮仿真。請您詳細介紹一下嗎?你將如何實現它? – kozouu

+0

分配一個大小等於維度乘積的數組。它具有多維數組所具有的元素數目。計算一組索引和一維數組中索引之間的映射。 – Peter

回答

1

如果您放寬一些要求(「根據從cin獲得的int值創建不同的數據結構」),則可能會這樣。這裏只是一個草圖,不是一個完整的答案,但希望它能讓你走上正軌。

訪問存儲:

您需要的數字存儲在所期望的類型的單個陣列和包裹通過索引映射函數的對它們的訪問。 例如,在圖2D中,一個這樣的功能是

int indexIn2D(uint rowCol[2], int rowCount) { 
    // rowCol[0] - is row index, rowCol[1] is col index 
    return rowCol[0]*rowCount + rowCol[1]; 
} 

float* values=new float[numRows*numCols]; 

// I want the element at (i,j) 
float& myIJElement=values[indexIn2D({i,j}, numRows)]; 

轉化成n維,這將要求對

// suppose I'm storing a 3D matrix with [3 slices, 4 rows, 5 columns] 
// as a 1D array and I want the element at [x,y,z] - what's it would be 
// the position of that element in my 1D array? 
// - fill coodIndex[3] with {x,y,z} 
// - pass nDim=3 
// - the dimSignature will be {3 /*slices*/, 4 /*rows*/, 5 /*columns*} 
int indexInND(uint coordIndex[], uint numDim, uint[] dimSignature) { 
    int ret=coordIndex[0]; 
    for(uint i=0; i<numDim-; i++) { 
     ret=ret*dimSignature[i]+coordIndex[i+1]; 
    } 
    return ret; 
} 

變體樣存儲的類型的線的東西

好吧,我們已經知道我們會將整個「N-dim塊」存儲爲目標類型的unidim數組。因此,我們可以利用指針,並有我們的 「存儲」 像

​​

後備FOM變種爲std :: vector的

喜歡的東西:

template <typename NumType> class VectNStorage { 
    std::vector<NumType> storage; 
    std::vector<uint> dimSignature; 
protected: 
    size_t indexMapping(const std::vector<uint>& indices) { 
    size_t ret=indices[0]; 
    for(uint i=0; i<this->dimSignature.size()-1) { 
     ret=ret*this->dimSignature[i]+indices[i+1]; 
    } 
    return ret; 
    } 
public: 
    VectNStorage(const std::vector<uint> dimsDef) : storage(), dimSignature(dimsDef) { 
    uint howMany=1; 
    for(auto d : this->dimSignature) { 
     howMany*=d; 
    } 
    this->storage.resize(howMany); 
    std::fill(this->storage.begin(), this->storage.end(), 0); 
    } 

    NumType& at(const std::vector<uint>& indices) { 
    return this->storage[this->indexMapping(indices)]; 
    } 
} 
+0

嗯,我真的不明白你的代碼中發生了什麼...... – kozouu

+0

1.你如何將二維數組映射到一維矢量?把行放在一個接一個的位置。 2.你如何在nDim中做到這一點?好吧,拿最後兩個變暗,並像1中那樣'線性化'它們,你會得到一個nDim-1數組。重複此操作,直到完成單個1D陣列。 –

+0

@kozouu現在更清楚了嗎? –

1
  1. 你知道如何閱讀用戶輸入嗎?如果沒有,首先找出如何在C++中做到這一點。
  2. 從用戶輸入中讀取一個變量,它會告訴您要創建的結構的類型。 (提示,使用int
  3. 使用適當的檢查,看看有什麼用戶輸入(提示,使用if() {} else if() {}
  4. 根據初步類型,構建一個合適的結構,提示創建所有類型,例如,一個struct Scalar{},struct Vector{}
  5. 在您創建的每個結構中調用read()方法來讀取剩餘的用戶輸入(您將需要使用某種形式的機制來分割用戶輸入,提示:字符串標記化)
  6. 拒絕你不支持的類型
0

可使用普通std::vector適用於所有類型的用戶輸入。你需要的唯一東西是一些函數f(x),它將映射K大小的索引向量以普通數組的形式進行索引。

例如:X - K大小的索引向量,S - K大小的尺寸大小的矢量

k = 1 -> f1(x,s) = x1; 
k = 2 -> f2(x,s) = x2*s2 + x1; 
k = 3 -> f3(x,s) = x3*s3*s2 + x2*s2 + x1 = x3*s3*s2 + f2(x2,x1,s2,s1); 
k = 4 -> f4(x,s) = x4*s4*s3*s2 + f3(x3,x2,x1,s3,s2,s1); 

那裏的最後乘數座標是(K - 1)的體積尺寸的對象。 此外,我們認爲,座標的計算從0開始。

這看起來像遞歸函數,可以很容易實現。您只需計算(k-​​1)維對象的移位,從數組中彈出座標並再次調用自身的函數。

+0

這看起來很可行,但是你是什麼意思的k大小的索引向量和k大小的維度大小向量?你能更詳細地描述遞歸嗎? – kozouu

+0

@kozouu如果你的數據結構有'k'維度,那麼你需要'k'索引來解決這個結構中的元素,這是k-大小的索引,用vector來表示'k'索引是很自然的。與數據結構的大小相同。您需要確定每個維度的大小,並給出「k」個大小。而且它們也可以作爲矢量存儲。 –

+0

@SemyonBurov不需要遞歸(除了知道正在發生什麼)。索引映射的公式類似於計算多項式的值。 –