2011-11-07 38 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和其他貢獻者

相關問題