2016-12-07 43 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