2017-08-28 63 views
0

我有這個功能,這在C++中返回一個隨機陣列:通話和打印功能,返回的數組中的C++

int* randomArray(int countOfRows){ 
    int test1 [countOfRows] = {}; 
    int insertValue; 
    int check; 
     for (int n=0; n < countOfRows; ++n){ 
      srand(time (NULL)); 
      while (test1[n] == NULL){ 
       insertValue = (rand() %100 + 1); 
       for(int i = 0; i < countOfRows; i++){ 
        if (test1[i] == insertValue){ 
         check = 1; 
         break; 
        } 
        else{ 
         check = 0; 
        } 
       } 

       if (check == 0){ 
        test1[n] = insertValue; 
       } 
      } 
     } 
    return test1; 
} 
  • 我如何可以調用數組?
  • 爲int *之間的區別和int []什麼

謝謝:)

+4

使用'std :: vector'。它將免除你即將面臨的所有陷阱。 – StoryTeller

+0

您無法返回指向堆棧中分配的數組的指針 - 只要函數返回,該數組就會立即消失。 –

+0

無關,我相當有信心while(test1 [n] == NULL)'會更好地表示爲'while(test1 [n] == 0)'。相關的,而且,如果你想'countOfRows'的唯一值在1..100之間(其中'countOfRows'最好不超過100或者這個旋轉到無窮大),你最好旋轉一個1的序列。 .100,洗牌,然後剝離前面的第一個'countOfRows'元素以獲得結果。最好的部分:你可以在一個矢量中做*全部*;在返回之前調整爲「countOfRows」。 – WhozCraig

回答

0

從我看來這個功能有問題。

它返回在堆棧中分配的test1的點,該點在randomArray範圍之外是無效的。

所以,如果你改變malloc,這是分配在堆中,那麼它仍然有效時,超出randomArray的範圍。

int *test1 = (int*) malloc(countOfRows* sizeof(int)); 

,並且可以使用TEST1 [X]讓每個整型值,肯定你應該知道test1的長度是countOfRows。

請不要忘記刪除了這一點,當它不被使用......

調用此數組是簡單

int* values = randomArray(1000); printf("%d\r\n",values[0]);

0

在功能randomArray()聲明TEST1 []作爲一個靜態的int []。 使用指針返回數組, 「迴歸測試1」 在主函數使用指針來訪問返回值 「INT * PTR = randomArray(n)的」

4

您的代碼具有四個顯著的問題,其中的一個關鍵的,一個非標準的和依賴於實現的,以及兩個通用算法問題。

首先,最重要的是,您要返回自動變量的地址,這意味着它既沒有用處,也會調用未定義的行爲以由調用方取消引用。在你的函數的頂部聲明是:

int test1 [countOfRows] = {}; 

其本身帶來了第二點,有兩個原因這種非標準:可變長度數組不被C++標準所支持,並由此推斷,初始化的說同樣不支持。然後...

return test1; 

函數調用者將收到一個地址,但該地址是無用的。它不再具體解決任何問題,因爲函數返回後test1不再存在。這可以通過很多方法來解決,考慮到這是C++,最簡單的方法是使用支持價值回報的std::vector<int>

兩個顯著的​​算法問題是

  • 你的srand播種不應該在for循環。實際上,如果您使用的是srandrand,則應在整個過程中進行播種一次
  • 如果您只是使用一種不同的算法,我將在後面介紹一個詳盡搜索以查看當前隨機選擇是否已用於避免重複的過程。

因此,你的代碼最簡單的修補程序將做到這一點:

#include <iostream> 
#include <vector> 
#include <cstdlib> 
#include <ctime> 

std::vector<int> randomArray(int countOfRows) 
{ 
    std::vector<int> test1(countOfRows); 
    int check = 0; 
    for (int n=0; n < countOfRows; ++n) 
    { 
     while (test1[n] == 0) 
     { 
      int insertValue = (rand() %100 + 1); 
      for(int i = 0; i < countOfRows; i++) 
      { 
       if (test1[i] == insertValue){ 
        check = 1; 
        break; 
       } 
       else{ 
        check = 0; 
       } 
      } 

      if (check == 0){ 
       test1[n] = insertValue; 
      } 
     } 
    } 
    return test1; 
} 

int main() 
{ 
    std::srand(static_cast<unsigned>(std::time(NULL))); 
    std::vector<int> vec = randomArray(20); 
    for (auto x : vec) 
     std::cout << x << ' '; 
    std::cout.put('\n'); 
} 

輸出(不同,很明顯)

8 50 74 59 31 73 45 79 24 10 41 66 93 43 88 4 28 30 13 70 

的有限集合算法

你真正想要在這裏生成的是一組有限的整數,範圍在1..100。也就是說,沒有重複使用的值,並且返回的項目數量也可以是1..100。要做到這一點,考慮這個算法:

  1. 生成的1..100在std::vector<int>
  2. 序列從標準庫使用僞隨機數發生器,利用洗牌std::shuffle
  3. 調整所產生的載體序列是你想要返回的元素的數量。

關於#3從上面,考慮一個小例子,假設你只需要十個元素。最初,你建立一個類似如下的順序向量:

1 2 3 4 5 6 7 8 9 10 11 12 13... ...99 100 

現在你使用std::shuffle和僞隨機數發生器像std::mt19937洗牌這一載體:(圖示爲了簡潔的前二十元):

48 39 31 44 68 84 98 40 57 76 70 16 30 93 9 51 63 65 45 81... 

現在,您只需將矢量縮小到所需的大小,在這種情況下就是十個元素:

48 39 31 44 68 84 98 40 57 

這就是您的結果。如果這聽起來很複雜,你可能會驚訝地看到它實際上多麼少的代碼需要:

代碼

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <numeric> 
#include <random> 

std::vector<int> randomSequence100(std::size_t count) 
{ 
    if (count > 100) 
     count = 100; 

    static std::random_device rd; 
    std::vector<int> result(100); 
    std::iota(result.begin(), result.end(), 1); 
    std::shuffle(result.begin(), result.end(), std::mt19937(rd())); 
    result.resize(count); 

    return result; 
} 


int main() 
{ 
    // run twenty tests of random shuffles. 
    for (int i=0; i<20; ++i) 
    { 
     auto res = randomSequence100(20); 
     for (auto x : res) 
      std::cout << x << ' '; 
     std::cout.put('\n'); 
    } 
} 

輸出

27 71 58 6 74 65 56 37 53 44 25 91 10 86 51 75 31 79 18 46 
6 61 92 74 30 20 91 89 64 55 19 12 28 13 5 80 62 71 29 43 
92 42 2 1 78 89 65 39 37 64 96 20 62 33 6 12 85 34 29 19 
46 63 8 44 42 80 70 2 68 56 86 84 45 85 91 33 20 83 16 93 
100 99 4 20 47 32 58 57 11 35 39 43 87 55 77 51 80 7 46 83 
48 39 31 44 68 84 98 40 57 76 70 16 30 93 9 51 63 65 45 81 
32 73 97 83 56 49 39 29 3 59 45 89 43 78 61 5 57 51 82 8 
21 46 25 29 48 37 77 74 32 56 87 91 94 86 57 67 33 9 23 36 
27 46 66 40 1 72 41 64 53 26 31 77 42 38 81 47 58 73 4 11 
79 77 46 48 70 82 62 87 8 97 51 99 53 43 47 91 98 81 64 26 
27 55 28 12 49 5 70 94 77 29 84 23 52 3 25 56 18 45 74 48 
95 33 25 80 81 53 55 11 70 2 38 77 65 13 27 48 40 57 87 93 
70 95 66 84 15 87 94 43 73 1 13 89 44 96 10 58 39 2 23 72 
43 53 93 7 95 6 19 89 37 71 26 4 17 39 30 79 54 44 60 98 
63 26 92 64 83 84 30 19 12 71 95 4 81 18 42 38 87 45 62 70 
78 80 95 64 71 17 14 57 54 37 51 26 12 16 56 6 98 45 92 85 
89 73 2 15 43 65 21 55 14 27 67 31 54 52 25 72 41 6 85 33 
4 87 19 95 78 97 27 13 15 49 3 17 47 10 84 48 37 2 94 81 
15 98 77 64 99 68 34 79 95 48 49 4 59 32 17 24 36 53 75 56 
78 46 20 30 29 35 87 53 84 61 65 85 54 94 68 75 43 91 95 52 

每一行上方是一組二十元素取自1..100的序列。沒有單行重複(檢查是否需要)。

買者

這種技術工程奇妙爲任一小的區域或從較大結構域結果集。但是它有其侷限性。例如:一旦您的潛在域達到重要大小(例如,1 ... 1000000中的數字)並且您只需要小的結果集(比如說不超過100個元素),則最好使用一個std::unordered_set和迭代探測類似於你現在正在做的事情。您使用的技術完全取決於您的性能目標和使用模式。反例:如果你想從一個百萬個元素的域中洗牌出五十萬個獨特的元素,那麼加載/隨機/調整大小技術就可以很好地工作。

最終你必須決定,並測量確認。


瞭解一些此處使用的東西一些有用的鏈接(書籤這個網站,因爲它是絕對的關於C的信息++):

+1

以上切割。頂尖的答案:) – StoryTeller

+0

只是好奇,應該每次創建mt19937,或者應該像random_device一樣是靜態的,還是根本不重要? –