2016-12-07 45 views
0

我需要選擇m個隨機字符(字母)而沒有重複,我完全卡住了,我只收到1個隨機字母。我如何修復我的代碼?有沒有什麼方法可以解決這個問題,或者我應該放棄這個想法並尋找一些kinf od教程的解決方案?選擇無重複的隨機字符C++

#include <iostream> 
#include <ctime> 
#include <cstdlib> 
#include <string> 

using namespace std; 

int main() 
{ 
    cout << "number below 27" << endl; 
    int m; 
    cin >> m; 

    srand(time(NULL)); 
    bool repeat = false; 
    char letters[m]; 
    char letter; 
    for(int i = 0; i < m; i++){ 
    letter = rand()%26 +97; 
    repeat = true; 
    for(int j = 0; j < m; j++){ 
     if(letters[m] == letters[j]){ 
     repeat = false; 
     break; 
     } 
    } 
    if(repeat){ 
     letters[m] = letter; 
    } 
    } 
    for (int i = 0; i < m; i++){ 
    cout << letters[m]; 
    } 
} 
+2

'char letters [m];'VLAs不是標準的C++。使用'std :: vector (m);'代替。 –

+0

多數民衆贊成我們是如何被要求解決這個問題,而我們學習的C++ – BigPaws

+1

bacics好吧,如上所述,它不是標準的C++代碼。 –

回答

3

您可以使用suffle -

#include <random> 
#include <iostream> 
#include <algorithm> 
#include <vector> 

using namespace std; 

int main() 
{ 
    char charSet[]={'a','b','c'};//You can add all the charecters 
    std::random_device rd; 
    std::mt19937 g(rd()); 
    std::shuffle(charSet,charSet+3,g); 
    for(auto c : charSet) 
    { 
    std::cout<<c; 
    } 
    std::cout<<endl; 
    return 0; 
} 
0

。在你的代碼的邏輯明顯的錯誤:當你測試重複你比較超越的結束只信,而不是所有的到目前爲止取樣。正確的測試將是

for(int i = 0; i < m; i++) { 
    bool repeating;   
    char tryletter; 
    do { 
     tryletter = rand()%26 +97; 
     repeating = false; 
     for(auto j=0; j!=i && !repeating; ++j) 
     repeating = tryletter == letters[j]; 
    } while(repeating); 
    letters[i] = tryletter; 
    } 

雖然這是不是最有效的的方式做你被要求做什麼。更有效的方法是從26個字母開始,隨機挑選一個並從集合中刪除,然後繼續挑選和刪除隨機字母。例如

std::string random_letters_without_repetition(std::size_t m) 
{ 
    std::string letters; 
    std::string all = "abcdefghijklmnopqrstuvwxyz"; 
    assert(m <= all.size()); 
    std::random_device r; 
    std::default_random_engine rng(r()); 
    while(m--) { 
    std::uniform_int_distribution<std::size_t> uni{0,all.size()-1}; 
    auto index = uni(rng); 
    letters += all[index]; 
    all.erase(index); 
    } 
    return letters; 
} 
0
bool repeat = false; 
vector<char> letters(m); 
char letter; 
for(int i = 0; i < m; i++){ 
    do 
    { 
     repeat = false; 
     letter = rand()%26 +97; // generate new random number 
     for(int j = 0; j<=i; j++) // iterate through the already generated numbers 
     { 
      if (letter == letters[j]){ // if the generated number already exists, do the while again 
       repeat = true; 
       break; 
      } 
     } 
    } while(repeat); 
    letters[i] = letter; // assign the unique number 
    cout << letter; 
    repeat = false; 
} 

,直到你有一個獨特的隨機數要重複隨機數發生器。 並輸出自己的價值觀使用我,因爲m是恆定的,超出範圍:

for (int i = 0; i < m; i++){ 
    cout << letters[i]; 
} 
+0

我想我會堅持這個解決方案,謝謝,這是有道理的! – BigPaws

+0

@BigPaws不客氣。如果這是您所選擇的答案,upvote或accept會很好;) – izlin

0

我想直接的方法是在C使用set ++。以下解決方案剛剛使用set來確保唯一性。希望這可能會有所幫助。

#include <iostream> 
#include <ctime> 
#include <set> 
#include <random> 

using namespace std; 

int main() 
{ 
    cout << "number below 27" << endl; 
    int m; 
    cin >> m; 

    srand(time(NULL)); 
    set<char> letters_set; 
    while(letters_set.size() < m){ 
     char c = rand()%26+'a'; 
     letters_set.insert(c); 
    } 
    for(auto c: letters_set) 
     cout<<c<<endl; 
} 

更有效的解決方案,它也確保每個字母具有相同的可能性。

#include <iostream> 
#include <ctime> 
#include <set> 
#include <random> 

using namespace std; 

int main() 
{ 
    cout << "number below 27" << endl; 
    int m; 
    cin >> m; 
    srand(time(NULL)); 
    vector<int> all_letters(26, 'a'); 
    for(int i = 0; i < 26; ++i) all_letters[i] += i; 
    vector<char> letters_set; 
    for(int i = 0; i < m; ++i){ 
     int select = rand()%all_letters.size(); 
     letters_set.push_back(all_letters[select]); 
     all_letters.erase(all_letters.begin()+select); 
    } 
    for(auto c: letters_set) 
     cout<<c<<endl; 
} 
+0

這是如何避免重複? – Walter

+0

@walter:用'std :: set',但是這個順序是固定的而不是隨機的。 – Jarod42

+0

@Walter第一種解決方案是使用'set'來避免重複,但效率相當低,因爲會有很多碰撞,而第二種解決方案可以進一步避免這種碰撞。 – Hearen