學習了不同儲存類別的概念後,我們來看幾個相關的程式。
首先,來看 乙個使用內部鏈結的靜態變數的函式:隨機數函式。
ansi c庫提供了rand() 函式生成隨機數。生成隨機數有多種演算法,ansi c允許c實現針對特定機器 使用最佳演算法。
然而,ansi c標準還提供了乙個可移植的標準演算法,在不 同系統中生成相同的隨機數。實際上,rand()是「偽隨機數生成器」,意思是 可**生成數字的實際序列。但是,數字在其取值範圍內均勻分布。
為了看清楚程式內部的情況,我們使用可移植的ansi版本,而不是編譯器內建的rand()函式。可移植版本的方案開始於乙個「種子」數字。該函式使用該種子生成新的數,這個新數又成為新的種子。然後,新種子可用於生 成更新的種子,以此類推。該方案要行之有效,隨機數函式必須記錄它上一 次被呼叫時所使用的種子。這裡需要乙個靜態變數。
/* rand0.c --生成隨機數*/
/* 使用 ansi c 可移植演算法 */
static
unsigned
long
int next =1;
/* 種子 */
unsigned
intrand0
(void
)
在程式清單12.7中,靜態變數next的初始值是1,其值在每次呼叫rand0() 函式時都會被修改(通過魔術公式)。該函式是用於返回乙個0~32767之間 的值。注意,next是具有內部鏈結的靜態變數(並非無鏈結)。這是為了方便稍後擴充套件本例,供同乙個檔案中的其他函式共享。
/* r_drive0.c -- 測試 rand0()函式 */
/* 與 rand0.c 一起編譯*/
#include
extern
unsigned
intrand0
(void);
intmain
(void
)
該程式也需要多檔案編譯。程式清單 12.7 和程式清單 12.8 分別使用一 個檔案。程式清單 12.8 中的extern關鍵字提醒讀者rand0()被定義在其他檔案 中,在這個檔案中不要求寫出該函式原型。輸出如下:
16838
5758
10113
17515
31051
程式輸出的數字看上去是隨機的,再次執行程式後,輸出如下:
16838
5758
10113
17515
31051
看來,這兩次的輸出完全相同,這體現了「偽隨機」的乙個方面。每次主 程式執行,都開始於相同的種子1。可以引入另乙個函式srand1()重置種子來 解決這個問題。關鍵是要讓next成為只供rand1()和srand1()訪問的內部鏈結靜態變數(srand1()相當於c庫中的srand()函式)。把srand1()加入rand1()所在 的檔案中。程式清單12.9給出了修改後的檔案。
/* s_and_r.c -- 包含 rand1() 和 srand1() 的檔案 */
/* 使用 ansi c 可移植演算法 */
static
unsigned
long
int next =1;
/* 種子 */
intrand1
(void
)void
srand1
(unsigned
int seed)
注意,next是具有內部鏈結的檔案作用域靜態變數。
這意味著rand1()和 srand1()都可以使用它,但是其他檔案中的函式無法訪問它。使用程式清單 12.10的驅動程式測試這兩個函式。
程式清單12.10 r_drive1.c驅動程式
/* r_drive1.c -- 測試 rand1() 和 srand1() */
/* 與 s_and_r.c 一起編譯 */
#include
#include
extern
void
srand1
(unsigned
int x)
;extern
intrand1
(void);
897int
main
(void
)printf
("done\n");
return0;
}
編譯兩個檔案,執行該程式後,其輸出如下:
1
16838
5758
89810113
17515
31051
please enter next seed (q to quit)
:513
20067
23475
8955
20841
15324
please enter next seed (q to quit):q
done
設定seed的值為1,輸出的結果與前面程式相同。但是設定seed的值為 513後就得到了新的結果。
注意 自動重置種子
如果 c 實現允許訪問一些可變的量(如,時鐘系統),可以用這些值 (可能會被截斷)初始化種子值。例如,ansi c有乙個time()函式返回系統 時間。雖然時間單元因系統而異,但是重點是該返回值是乙個可進行運算的 型別,而且其值隨著時間變化而變化。time()返回值的型別名是time_t,具體 型別與系統有關。這沒關係,我們可以使用強制型別轉換:
#include
/* 提供time()的ansi原型*/
srand1((
unsigned
int)
time(0
));/* 初始化種子 */
一般而言,time()接受的引數是乙個 time_t 型別物件的位址,而時間值 就儲存在傳入的位址上。當然,也可以傳入空指標(0)作為引數,這種情 況下,只能通過返回值機制來提供值。
可以把這個技巧應用於標準的ansi c函式srand()和rand()中。如果使用 這些函式,要在檔案中包含stdlib.c標頭檔案。實際上,既然已經明白了 srand1()和rand1()如何使用內部鏈結的靜態變數,你也可以使用編譯器提供 的版本。我們將在下乙個示例中這樣做。
C C 產生隨機數的函式
c語言中有可以產生隨機數的函式,需要新增 stdlib.h 標頭檔案和 time.h 標頭檔案。srand unsigned time null 初始化隨機種子 for int i 0 i 10 i printf d rand 其中,rand 函式只能產生 0,rand max 範圍內的整數 ran...
C C 生成隨機數
01 include 02 include 03 04intmain intargc,char argv 05 10return0 11 01 02上述方法產生隨機數每次不同,但每次執行時產生的順序是相同的。原因是每次的種子都相同,所以會產生相同的隨機數列。一般使用時間作為種子保證每次的種子都不同。...
C C 產生隨機數
c c 產生隨機數 c c 產生隨機數用到兩個函式rand 和 srand 一.不指定範圍產生隨機數 用到函式rand 函式原型為int rand 無引數。此時會產生乙個介於0 rand max間的整數。rand max的大小可以檢視,在include資料夾 linux在usr目錄 windows在...