您的代碼具有四個顯著的問題,其中的一個關鍵的,一個非標準的和依賴於實現的,以及兩個通用算法問題。
首先,最重要的是,您要返回自動變量的地址,這意味着它既沒有用處,也會調用未定義的行爲以由調用方取消引用。在你的函數的頂部聲明是:
int test1 [countOfRows] = {};
其本身帶來了第二點,有兩個原因這種非標準:可變長度數組不被C++標準所支持,並由此推斷,初始化的說同樣不支持。然後...
return test1;
函數調用者將收到一個地址,但該地址是無用的。它不再具體解決任何問題,因爲函數返回後test1
不再存在。這可以通過很多方法來解決,考慮到這是C++,最簡單的方法是使用支持價值回報的std::vector<int>
。
兩個顯著的算法問題是
- 你的
srand
播種不應該在for循環。實際上,如果您使用的是srand
和rand
,則應在整個過程中進行播種一次。
- 如果您只是使用一種不同的算法,我將在後面介紹一個詳盡搜索以查看當前隨機選擇是否已用於避免重複的過程。
因此,你的代碼最簡單的修補程序將做到這一點:
#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..100在
std::vector<int>
- 序列從標準庫使用僞隨機數發生器,利用洗牌
std::shuffle
- 調整所產生的載體序列是你想要返回的元素的數量。
關於#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的信息++):
使用'std :: vector'。它將免除你即將面臨的所有陷阱。 – StoryTeller
您無法返回指向堆棧中分配的數組的指針 - 只要函數返回,該數組就會立即消失。 –
無關,我相當有信心while(test1 [n] == NULL)'會更好地表示爲'while(test1 [n] == 0)'。相關的,而且,如果你想'countOfRows'的唯一值在1..100之間(其中'countOfRows'最好不超過100或者這個旋轉到無窮大),你最好旋轉一個1的序列。 .100,洗牌,然後剝離前面的第一個'countOfRows'元素以獲得結果。最好的部分:你可以在一個矢量中做*全部*;在返回之前調整爲「countOfRows」。 – WhozCraig