2011-11-07 39 views
1

我是一个自学C++的课本,我有一个问题需要解决,下面概述。如何在一个类构造函数内的一个设定范围内(不重复!)生成随机int数?

我有下面的类结构:

#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... 

} 

我需要生成一个唯一的学生每个学生在一个值范围内的每个学生的ID,例如0到10.

我已将以下代码片段复制到构造函数中。它生成我的随机数,我所期望的范围内:

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

的问题是,我需要得到的生成随机数的范围内排除任何重复的。

+0

纠错:int random_integer = 0;应该读取int random_integer; –

+0

为什么你1)使用这2个随机数的总和(基本上*不是*给你一个在所需范围内的随机数)2)假设一个随机数可以作为一个标识符? – Tibo

+0

请注意,班级名称非常具有误导性 - 该物品似乎比“教室”更接近“学生”。你应该考虑命名你的类,就像你描述它们一样 - 在这种情况下,它们代表和包含关于学生的数据 - 所以它们应该被命名为“Student”。 – jedwards

回答

1

为什么数字需要是随机的?你不能只使用一个静态int,每次你需要生成一个新的学生号码时,这个静态int就会增加。

+0

由于类中的私有字段只能从公共成员函数访问,而不能直接从主程序访问。 –

+0

生成的任何数字都需要从该类的每个实例中携带。这比听起来容易! –

+0

构造函数在运行时并不知道该类的其他实例是否存在,直到它们在main中声明为止。无论如何,这就是我的看法。所以我相信,当你最初遇到这个问题时,它并不像听起来那么简单。 –

2

只需具有所有可能的学生ID的矢量。在你的情况下0..Range。

random_shuffle和挑头三个ID,并将它们分配

我添加了一个可行的解决方案。要做到这一点

//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++]; 
    } 
}; 
+0

这并不能解决问题。 – jedwards

+0

是的,我可以工作,我将不得不看一个随机洗牌如何在一个向量上工作。但是,这仍然会防止重复? –

+0

它会防止重复,但你不能像你问的那样在构造函数中这样做。这实际上并没有解决问题,可能是误导。 – jedwards

2

一种方法是使用所谓的静态成员变量。通常,每个对象获得自己的副本的成员变量。在你的代码中,每个学生将拥有他自己的副本name[25],student_id等。但是,你想要什么,将在每个类的实例之间共享(classroom students[3]中的每个元素都是classroom类的实例)。

以下是关于static member variables的一些注意事项。请注意,他们提出了一个非常类似的问题的解决方案 - 他们为每个类实例分配唯一的ID。他们在这里提出的和你要求的唯一区别是你要求它是随机的,而不是连续的。

因此,您不需要一个静态成员变量来跟踪一个数字(最后一个指定的数字),您将希望您的静态成员变量跟踪所有先前分配的ID。 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]; 
} 

上面的代码,你可以做到这一点,通过存储在一个向量所使用的学生证,然后每次创建一个新的学生,确保随机生成的ID不匹配的一种方式已分配的ID。

另一个需要注意的是,你只应该给随机数发生器播种一次(特别是如果你的种子是时间的话)。由于您在如此短的时间内播种了3次,因此产生的随机数是相同的。

+0

是的,谢谢,我会调查并回来... –

+0

我相信你的上面的答案是沿着我需要的线。如果我不需要生成随机数字并且只有连续的数字,那么我就可以使用连续的数字,只要我实现了我的目标:哪一个是唯一标识每个类的实例。谢谢 –

+0

我提供的代码将生成随机唯一的数字。如果你想要连续的(也是唯一的)数字,你可以改变'static vector used;'static_state_used;',改变'vector classroom :: used = vector ();'to int int classroom :: last_used = 0'并将我的解决方案的第33-53行替换为'student_id = last_used ++;'。 – jedwards

1

对于所有那些想知道解决的办法,以我一类的每个实例创建一个唯一的ID的问题,那就是:

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;** 

通知,新成员:静态INT next_student_id已在构造函数中创建并使用,它也在类结构之外初始化。

在构造我只是用下面的代码:

student_id=next_student_id++; 

此代码产生作为类教室结构的每个实例是唯一的连续号码; 请注意我知道班级课堂并不是一个理想的名字,因为它与课程名称相冲突,但我使用这个,因为我复制了课本问题的基本命名!

我得出的结论是,艾伦的回答最能帮助我,并为我提供了最简单的解决方案。因此艾伦因此得到了答案。

我也要感谢Jedwards,如果你追求的答案也可以作为替代解决方案......但事实证明,使用静态int是关键,并且生成随机数并且创建向量不是必需的。

并且还要感谢parapura rajkumar和其他贡献者

相关问题