Как я могу генерировать случайные числа int в пределах заданного диапазона (без дубликатов!) Внутри конструктора класса? - PullRequest
1 голос
/ 07 ноября 2011

Я изучаю C ++ из учебника, и мне нужно решить проблему, описанную ниже.

У меня следующая структура класса:

 #include <iostream>
 #include <cstdio>
 #include <ctime> 

 using namespace std;


   class classroom{

     char name[25];
     int student_id;
     float grades[10];
     float average;
     int num_tests;
     float letter_grade;

   public:       
     void enter_name_id(void);
     void enter_grade(void);
     void average_grades(void);
     void letter_grades(void);
     void output_name_id_grade(void);
     classroom();

   };

И у меня есть следующий конструктор для вышеуказанного класса:

 classroom::classroom(){

      int i;

      srand((unsigned)time(0));
      int random_integer=0; 
      random_integer = (rand()%5) + (rand()%5); 

      num_tests=0;
      average=0.0;

      for(i=0;i<10;i++){

        grades[i]=0.0;

      }

      for(i=0;i<27;i++){

         name[i]='-';       
      }
      cout<<"\n*****************Finished*****************";
 }

В этой структуре класса будут объявлены 3 ученика, объявленные в main:

int main()
{       
  classroom students[3]; 
//and so...

}

Мне нужно сгенерировать уникальный идентификатор студента для каждого студента в конструкторе в диапазоне значений, скажем, от 0 до 10.

Я скопировал следующий фрагмент кода в конструктор. Он генерирует мое случайное число для меня в желаемом диапазоне:

srand((unsigned)time(0));
  int random_integer=0; 
  random_integer = (rand()%5) + (rand()%5);

Проблема в том, что мне нужно избавиться от любых дубликатов в диапазоне генерируемых случайных чисел.

Ответы [ 4 ]

2 голосов
/ 07 ноября 2011

Один из способов сделать это - использовать так называемую статическую переменную-член . Обычно каждый объект получает свою собственную копию переменных-членов. В вашем коде у каждого учащегося будет своя собственная копия name[25], student_id и т. Д. Но то, что вы хотите, - это то, что будет совместно использоваться каждым экземпляром класса (каждый из элементов в classroom students[3] является экземпляром classroom класса.)

Вот некоторые заметки о статических переменных-членах . Обратите внимание, что они представляют решение очень похожей проблемы - они присваивают уникальные идентификаторы каждому экземпляру класса. Единственная разница между тем, что они представляют здесь, и тем, что вы просите, заключается в том, что вы просите, чтобы это было случайным, а не последовательным.

Таким образом, вместо статической переменной-члена, отслеживающей один номер (последний назначенный), вы захотите, чтобы ваша статическая переменная-член отслеживала всех ранее назначенных идентификаторов . Должен работать std.vector или простой массив int.


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> 
#include <vector>

using namespace std;


class classroom{
    char name[25];
    int student_id;
    float grades[10];
    float average;
    int num_tests;
    float letter_grade;

    static vector<int> used;

public:       
    void enter_name_id(void);
    void enter_grade(void);
    void average_grades(void);
    void letter_grades(void);
    void output_name_id_grade(void);
    classroom();
};

vector<int> classroom::used = vector<int>();

classroom::classroom(){
    int i;
    int random_integer=0; 
    bool rand_ok;
    do
    {
        // Generate Random Integer
        random_integer = (rand()%5) + (rand()%5); 
        //cout << "Generated: " << random_integer << endl;

        rand_ok = true;
        for(i=0; i<used.size(); i++)
        {
            if(used[i] == random_integer){ rand_ok = false; break; }
        }

    } while (rand_ok == false);

    // If we get here, random_integer is not in the used vector
    // therefore accept and store as student_id
    student_id = random_integer;    
    // ... and update used vector
    used.push_back(student_id);

    num_tests=0;
    average=0.0;

    for(i=0;i<10;i++){

    grades[i]=0.0;

    }

    for(i=0;i<27;i++){

     name[i]='-';       
    }
    cout<<"*****************Finished*****************\n";
}


int main()
{       
    // You should only seed the RNG once
    srand((unsigned)time(0));
    classroom students[3]; 
}

Приведенный выше код является одним из способов сделать это, сохранив использованные идентификаторы учащихся в векторе, а затем каждый раз, когда вы создаете нового студента, убедитесь, что случайно сгенерированный идентификатор не соответствует уже назначенному идентификатору. *

Еще одно замечание: вы должны заполнять генератор случайных чисел только один раз (особенно, если ваше время - время). Поскольку вы засевали его 3 раза за такое короткое время, производимые случайные числа были одинаковыми.

2 голосов
/ 07 ноября 2011

Просто есть вектор со всеми возможными идентификаторами учеников. в вашем случае 0..Range.

сделать random_shuffle , выбрать первые три идентификатора и назначить их

Я добавил рабочий раствор.

//Only have one instance of this class.
class IdMgr
{
    std::vector<int> mIds;
    int mCurrentId;
public:
    IdMgr( int Max )
    {
        for ( int i = 0 ; i <= Max; ++i )
            mIds.push_back( i );

        std::random_shuffle( mIds.begin() , mIds.end() );

        mCurrentId = 0;
    }

    //Call this function from your class constructor
    int GetNextId()
    {
        return mIds[ mCurrentId++];
    }
};
1 голос
/ 08 ноября 2011

Для всех тех, кто хочет знать решение моей проблемы создания уникального идентификатора для каждого экземпляра класса, вот оно:

class classroom{

         char name[25];
         int student_id;
         float grades[10];
         float average;
         int num_tests;
         float letter_grade;

         **static int next_student_id;**

  public:       
         void enter_name_id(void);
         void enter_grade(void);
         void average_grades(void);
         void letter_grades(void);
         void output_name_id_grade(void);
         classroom();
  };

         **int classroom::next_student_id=1;**

Обратите внимание, новый член: staticint next_student_id был создан и использован в конструкторе, он также был инициализирован вне структуры класса.

В конструкторе я просто использовал следующий код:

student_id=next_student_id++;

Этот код создавал уникальные последовательные числа для каждого экземпляра структуры класса Class;Обратите внимание, что я знаю, что классная комната не является идеальным именем, поскольку оно конфликтует с названием класса, но я использовал это, поскольку скопировал базовое наименование из вопроса из учебника!

Я пришел к выводу, что ответ АланаВышеизложенное помогло мне больше всего и предоставило мне самое простое решение. И поэтому Алан получает от меня галочку.

Я хотел бы также поблагодарить Джедвардса, ваш ответ, если его преследовать, мог бы также стать альтернативным решением.... но, как оказалось, использование статического int было ключом, а генерация случайных чисел и создание векторов не было необходимым.

И спасибо вам также parapura rajkumar и другие участники

1 голос
/ 07 ноября 2011

Почему число должно быть случайным? Разве вы не можете просто использовать статический int, который увеличивается каждый раз, когда вам нужно сгенерировать новый номер студента?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...