在某个时间间隔内生成随机数,但某些数字除外:EXC_BAD_ACCESS

时间:2012-03-13 18:43:50

标签: c++ xcode variadic-functions

我在Mac Os X雪豹上使用xcode 4。 我正在尝试编写一个函数来在一个区间内生成一个随机数,除了一些数字 即:

int num=5;
random(time(NULL),1,100,&num,NULL);

这必须生成1和100之间的数字,除了5。 所以我写了这段代码:

//
//  main.cpp
//  CPPTest
//
//  Created by Ramy Al Zuhouri on 3/7/12.
//  Copyright 2012 __MyCompanyName__. All rights reserved.
//

#include <iostream>
#include <exception>
#include <cstdarg>
#include <cstdlib>
#include <ctime>

using namespace std;

class cannotGenerate : public exception
{
    virtual const char* what()
    {
        return "Cannot generate any number, maybe the interval is empty, or the exluding vector is too large\n";
    }
};

// Random number generation
// min : min number (included)
// max : max number (included)
// seed : generator seed
// excp1 first argument of int pointers (the last must be NULL)
// the int pointers represent the numbers that must be excluded
// so that if such number is generated, it has to be generated again

int random(unsigned int seed=(unsigned int)time(NULL),int min=0,int max=RAND_MAX, int* excp1=NULL , ...)
{
    // variables

    int result,*ptr;
    va_list vl;
    static unsigned int count=0;

    // instructions

    srand(seed+count++);
    va_start(vl,excp1);
    do   // this do-while has the purpose to keep generating numbers until the number is correct
    {    // correct = within the [min,max] interval and not a number of the list of pointers
        result=rand()%(max-min+1)+min;
        ptr=excp1;
        do  // this do-while has the purpose to check all the va_list and to read all arguments   
        {   // passed to the function
            if(ptr!=NULL)
            {                     // here there is the exception (with gdb 6.3.50) :
                if(result==*ptr)  // Thread 1: Program received signal: "EXC_BAD_ACCESS". 
                    result=min-1;
                ptr=va_arg(vl,int*);
            }
            else
            {
                break;
            }
        }while(ptr!=NULL && (result<min || result>min));
    }while(result<min || result>max);
    va_end(vl);

    // result

    return result;
}

int main (int argc, const char * argv[])
{
    int excp[]={1,2,3,4};
    int rand;
    for(int i=0;i<100;i++)
    {
        rand=random((unsigned int)time(NULL),1,100,&excp[0],&excp[1],&excp[2],&excp[3],NULL);
        if(rand==1 || rand==2 || rand==3 || rand==4)
        {
            cerr << "error" << endl;
            break;
        }
        else
        {
            printf("%d\n",rand);
        }
    }
    return 0;
}

但是对于gdb我得到了这个例外:
线程1:编程接收信号:&#34; EXC_BAD_ACCESS&#34;。
在那个块中,ptr不能为NULL,所以我无法弄清楚这个异常的原因。

2 个答案:

答案 0 :(得分:1)

这是很多代码。试试这个:

int z = ((arc4random() % 100)+1);
if (z == 5){
   [self tryAgain]
}else {
  return z;
}

(用你的最大值替换100,用任意数量的排除变量替换5)

这将生成0到99之间的随机数,然后向其中添加一个。如果结果为5,则将其循环以获得不同的数字。 另外,请在代码中注意这一行:

}while(ptr!=NULL && (result<min || result>min));

是吗?小于或大于最低?

答案 1 :(得分:1)

问题是你没有在第一次运行后重置变量参数列表,所以它在NULL输入后最终指向内存导致异常(如果你很幸运)。

尝试使用以下内容随机替换内部循环(注意va_start和va_end的位置)。

 do {
        result=rand()%(max-min+1)+min;
        va_start(vl,excp1);           //note
        ptr=excp1;

        do 
        {
            if(ptr!=NULL)
            {
                if(result==*ptr)
                    result=min-1;
                ptr=va_arg(vl,int*);
            }
            else
            {
                break;
            }
        } while(ptr!=NULL && (result<min || result>min));

        va_end(vl); //note
    }while(result<min || result>max);