在c ++中返回数组的调用和打印函数

时间:2017-08-28 05:46:37

标签: 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 []
  • 之间的区别是什么
谢谢你:)

3 个答案:

答案 0 :(得分: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. std::vector<int>
  2. 中生成1..100的序列
  3. 使用标准库中的伪随机生成器,使用std::shuffle
  4. 对序列进行洗牌
  5. 将结果向量的大小调整为要返回的元素数。
  6. 关于上面的#3,考虑一个小例子,假设你只想要十个元素。最初,您构建一个如下所示的序列向量:

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

    现在,您使用std::shuffle和伪随机生成器(如std::mt19937)对此向量进行混洗:(为简洁起见,显示的前20个元素):

    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 
    

    上面的每一行都是一组20个元素,取自1..100的序列。没有单行有重复(检查是否需要)。

    <强>买者

    此技术适用于较小域或来自较大域的大型结果集。但它有其限制需要考虑。

    例如:一旦您的潜在域达到了显着大小的点(例如,数字在1 ... 1000000中)并且您只想要小的结果集(例如,不超过100个元素),那么您的状态会更好使用std::unordered_set和迭代探测类似于您现在正在做的事情。您使用的技术完全取决于您的性能目标和使用模式。

    反例:如果你想要从一个百万元素域中移植50万个唯一元素,那么load / shuffle / resize技术就可以正常工作。

    最终,你必须做出决定并进行衡量以确认。

    这里使用的一些有用的链接(将此网站加入书签,因为它是绝对的 gold 以获取有关C ++的信息):

答案 1 :(得分:0)

从我看来,这个功能有问题。

它返回test1的点,它在栈中分配,在randomArray的范围之外是无效的。

因此,如果你改为malloc,这是在堆中分配的,那么当它超出randomArray的范围时它仍然有效。

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

你可以使用test1 [x]来获取每个int的值,你肯定应该知道test1的长度是countOfRows。

请勿忘记在未使用时删除此点...

调用此数组很简单

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

答案 2 :(得分:0)

在函数randomArray()中将test1 []声明为静态int []。 使用指针返回数组, &#34; return test1&#34; 在main函数中使用指针来访问返回值 &#34; int * ptr = randomArray(n)&#34;