2012-03-13 67 views
0

我在Mac OS X雪豹上使用xcode 4。 我想寫一個函數來產生一個間隔內的隨機數,除了一些數字。
即:在一個時間間隔內產生一個隨機數,除了一些數字:EXC_BAD_ACCESS

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:編程接收信號:「EXC_BAD_ACCESS」。
在該塊中,ptr不能爲NULL,所以我找不出這個異常的原因。

回答

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); 
1

這是很多代碼。試試這個:

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

這會產生0到99之間的隨機數(與任意數量的排除變量替換100的最大值和5),然後加一個吧。如果結果爲五,則循環它以獲得不同的數字。 此外,請在您的代碼中註明以下行:

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

是嗎?小於還是大於最小值?

+1

我會用這種方法,但使用的100,我會用99,並添加一個到z如果該值> = 5。然後你不需要循環在所有和它的作品第一每次嘗試。 – lnafziger 2012-03-13 19:24:38

+0

這只是一個例子。有多個參數,所以它也可以是「從1到100,除了5,6,7和8」或任何其他 – 2012-03-13 21:38:02

+0

然後將排除的整數加載到數組中,然後將每個整數與z 。 – AMayes 2012-03-14 22:20:09

相關問題