2017-03-05 114 views
2
srand(time(NULL)); 
for(i=0;i<9;i++) 
{ 
    random: temp=rand()%9; 
    for(j=0;j<=i;j++) 
    { 
     if(temp==randarr[j]) 
     { 
      goto random; 
     } 
    } 
    randarr[i]=temp; 
     // printf("%d ",randarr[i]); 
} 

我想生成0到8之間的隨機數字而不重複任何數字。我使用這個代碼,它完美的作品。但我想從我的代碼中刪除goto語句。我怎樣才能寫我的代碼沒有轉到? 謝謝!我應該用什麼來代替goto語句?

+3

要麼'break'從內循環的,或使用另一循環嵌套。 –

+0

@sinsuren:你錯了。如果你*只是*跳出內部循環,你仍然會分配給'randarr'並增加'i' –

+0

@Martinbonner我意識到我的錯誤..謝謝。 – sinsuren

回答

6

您不想隨機生成每個數字。你想以隨機順序將數字從0變爲8。

一個更簡單的方法(也消除了goto的使用)是從一個排序的數組開始,並選擇一個索引來隨機交換每次迭代。

srand(time(NULL)); 
int randarr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; 
for(int i = 0; i < 9; ++i) 
{ 
    int swap_idx = rand() % 9; 
    int temp = randarr[swap_idx]; 
    randarr[swap_idx] = randarr[i]; 
    randarr[i] = temp; 
} 

HolyBlackCat指出的,幼稚方法傾向於得到各種排列的非均勻分佈。如果這是你所關心,改善是可能的Fisher-Yates (or Knuth) shuffle

srand(time(NULL)); 
int randarr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; 
for(int i = 0; i < 9; ++i) 
{ 
    int swap_idx = i + rand() % (9 - i); 
    int temp = randarr[swap_idx]; 
    randarr[swap_idx] = randarr[i]; 
    randarr[i] = temp; 
} 
+3

我很想聽聽是什麼導致了downvote。 – StoryTeller

+0

也許你應該用Fisher-Yates shuffle來重寫它?這段代碼似乎會產生不均勻的分佈。 http://www.i-programmer.info/programming/theory/2744-how-not-to-shuffle-the-kunth-fisher-yates-algorithm.html – HolyBlackCat

+0

@HolyBlackCat - 那麼原來的那個。我沒有着手提高分銷的質量,以至於易於實施。 – StoryTeller

0
srand(time(NULL)); 
for(i=0;i<9;i++) 
{ 
    temp=rand()%9; 
    for(j=0;j<=i;j++) 
    { 
     if(temp==randarr[j]) 
     { 
      break; 
     } 
    } 
    if(j > i) 
     randarr[i]=temp; 
    else 
     i--; 
} 
-1
srand(time(NULL)); 
i = 0; 
while(i < 9) 
{ 
    temp = rand() % 9; 
    int doesExist = 0; 
    for(j = 0; j <= i; j++) 
    { 
     if(temp == randarr[j]) 
     { 
      doesExist = 1; 
      break; 
     } 
    } 

    if (doesExist == 0) 
    { 
     randarr[i] = temp; 
     i++; 
    } 
    //printf("%d ",randarr[i]); 
} 
+0

我想知道爲什麼投票! – Mehdi

+1

Didnt downvote,但這是代碼中的quickfix答案 –

1

正如其他答案提到的形式,這是一個非常可怕的方式隨機選擇號碼0-8。你應該隨機洗牌。

但是,如果您發現自己的問題似乎需要goto,您可以隨時通過設置標誌來刪除它們。因此,像:

srand(time(NULL)); // Make sure you only execute this *ONCE* per program. 
        // Do not put it inside a function called repeatedly, or a loop. 

for(i=0;i<9;) { 
    int temp=rand()%9; 
    bool matched = false; 
    for(j=0;j<=i;j++) { 
     if(temp==randarr[j]) { 
      matched = true; 
      break; 
     } 
    } 
    if (! matched) { 
     randarr[i]=temp; 
     i++; 
    } 
} 

這是一個品味的問題,這是否是更容易或更困難比goto相應的代碼閱讀。就個人而言,我很高興使用像

 // acquire resources 
    ... 

    // do work 
    ret = function(...); 
    if (ret) goto error: 
    .... 

    // release resources 
error: 
    .... 
    return ret; 

代碼,但我會避免跳躍向後(你原來的代碼一樣)。

+0

允許'goto'用於錯誤處理或b)打破嵌套循環。 (a。適用於沒有結構化錯誤處理的語言,比如C) –

+0

@PaulOgilvie:我很少發現自己打破了嵌套循環,而且無論如何設置某種標記通常很方便(或者只是'返回')。 OTOH,當我用C編寫代碼時,我總是使用goto來處理錯誤。 –

0
  • 在內部循環的條件應該是j < i,randarr [i]是尚未分配
  • 無需指標變量,您可以通過j != i內環後檢測到爆發的內循環。

for(i=0; i < 9;) { 
    int temp=urand(9); /* to be supplied */ 
    for(j=0; j < i; j++) { /* Note j< i, *NOT* j<= i */ 
     if(temp==randarr[j]) break; 
     } 
    if (j != i) continue; /* inner loop ended prematurely */ 
    randarr[i]=temp; 
    i++; 
    } 
} 

順便說一句:有ISNO需要用於臨時變量:

for(i=0; i < 9;) { 
    randarr[i] = urand(9); 
    for(j=0; j < i; j++) { 
     if(randarr[j] == randarr[i]) break; 
     } 
    if (j != i) continue; /* inner loop ended prematurely */ 
    i++; 
    } 
} 
相關問題