2016-12-20 18 views
-2

私は配列をシャッフルする方法を持っていますが、動作していないので、今修正する方法がわかりません。 shuffleArrayによって返された配列からmainに新しい配列を作成するにはどうすればよいのですか?シャッフルされた配列を新しい配列に割り当てることはできません。関数から返された配列から新しい配列を作成するにはどうすればよいですか?

using namespace std; 

template <class T> T min (T array, T size){ 
    int min=array[0]; 
    for(int i=1;i<size;i++){ 
     if(array[i]<min){min=array[i];} 
    } 
return min; 
} 

template <class T> T indexOf (T array[], const int size, T value){ 

    for(int i=0;i<size;i++){ 
     if(array[i]==value){return value;} 
    } 
    return -1; 
    } 

template <class T> T shuffleArray (T array[], T size){ 

    T* Array2 = new T[size]; 

    for(int i=0;i<size;i++){ 
     Array2[i]=array[i]; 
    } 

    random_shuffle(&Array2[0],&Array2[size]); 

    return *Array2; 
} 

int main(){ 

    int a[]= {1,2,3,4,5}; 
    int index = indexOf(a, 5, 3); 

    cout << endl << "The index is:" << shuffleArray(a, 5)<<endl; 
    cout << endl << "The index is:" << index<<endl; 
    return 0; 


} 
+2

なぜ関数内に配列のコピーを作成していますか?関数に渡す配列をシャッフルするだけで、コールサイトの配列に反映されます。 – NathanOliver

+0

'return * Array2;'は悪い考えです。メモリリークが残っている可能性があります。 –

+2

'using namespace std;'は習慣に慣れていないので、今すぐ止めることができれば、将来的に頭痛の種をたくさん避けることができます。 'std ::'接頭辞は理由のためにそこにあります:それはあなた自身のクラス、構造体および変数との衝突を避けます。 – tadman

答えて

0

短い答え:std::arrayとして使用のstdコンテナ、彼らは適切なコピーコンストラクタを持っているし、あなたにいくつかの頭痛の種を保存します。ちなみにstd::arrayは生の配列としてはそれほど遅くはありません(基本的には生の配列ですが、クラスでラップされ、それを扱う素晴らしいメンバー関数がいくつかあります)。

詳細回答:std::coutに印刷したいものは完全にはわかりません。しかし、ほとんどの場合、シャッフルの前後に3の位置にする必要があります。その後、コードは(constexprautoの使用をstd=c++11でコンパイルする)、次のようになります。

  • 使用のstdコンテナ:いくつかのコメントとして

    #include <iostream> 
    #include <algorithm> // std::min, std::find and std::random_shuffle 
    #include <array> // use std::array instead of raw pointers 
    
    // using namespace std; Bad idea, as tadman points out in comment 
    
    // use std::min instead of 
    // template <class T> T min (T array, T size) 
    
    // use std::find instead of 
    // template <class T> T indexOf (T array[], const int size, T value){ 
    
    // T is not the value_type of the array, but the array iteself. Works also for all other std containers with random access iterators 
    template<class T> T shuffleArray(T array) // array is copied here 
    { 
        // shuffle 
        std::random_shuffle(array.begin(), array.end()); 
    
        // return copy of array 
        return array; 
    } 
    
    int main() 
    { 
        constexpr int numberToFind = 3; // constexpr is not necessary, but the variable seems not intented to change in this code 
        // use standard container instead of raw array 
        std::array<int,5> a = {1,2,3,4,5}; 
    
        // iterator to numberToFind in a 
        auto it = std::find(a.begin(), a.end(), numberToFind); // auto deduces the type, so you do not have to write std::array<int,t>::iterator and by the way the code is more flexible for changes 
    
        // shuffle a and store result in aShuffled 
        auto aShuffled = shuffleArray(a); 
    
        // iterator to numberToFind in aShuffled 
        auto itShuffled = std::find(aShuffled.begin(), aShuffled.end(), numberToFind); 
    
        // pointer arithmetics give the index 
        std::cout << "The index before shuffling is:" << it - a.begin() << std::endl; 
        std::cout << "The index after shuffling is:" << itShuffled - aShuffled.begin() << std::endl; 
    
        return 0; 
    } 
    

    をすでに、将来のためにいくつかのヒントをあなたに伝えます生の配列の生ポインタの代わりに

  • あなたが非常に具体的なニーズを持っていなければ、標準ライブラリからよくテストされたアルゴリズムを使用してください。
  • auto make C++ 11でイテレータの型を扱うのはとても簡単です。ところで、std :: arrayの代わりにstd :: vectorを使うようにほとんど変更する必要はありません。最初の宣言で十分です。
  • いつもnewを使用する場合は、deleteにする必要があります。それ以外の場合は、メモリリークを作成します。これも、標準コンテナを使用することで一般的に回避できます。
  • リテラルの代わりに説明的な名前を使用します。これにより、コードがはっきりとわかりやすくなります。
関連する問題