在不重复c ++的情况下挑选随机字符

时间:2016-12-07 10:42:50

标签: c++

我需要选择m个随机字符(字母)而不重复并且我完全卡住,我一直只收到1个随机字母。我该如何修复我的代码?有没有办法解决这个问题,或者我应该废弃这个想法,并从一些kinf od教程中寻找解决方案?

#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];
  }
}

4 个答案:

答案 0 :(得分:3)

您可以使用后缀 -

#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;
}

答案 1 :(得分: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;
}

答案 2 :(得分:0)

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

您重复随机数生成器,直到您有一个唯一的随机数。 并输出您的值使用i,因为m是常量且超出界限:

{{1}}

答案 3 :(得分: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;
}