程序設(shè)計實踐w線程模塊化時間函數(shù)和設(shè)計問題_第1頁
程序設(shè)計實踐w線程模塊化時間函數(shù)和設(shè)計問題_第2頁
程序設(shè)計實踐w線程模塊化時間函數(shù)和設(shè)計問題_第3頁
程序設(shè)計實踐w線程模塊化時間函數(shù)和設(shè)計問題_第4頁
程序設(shè)計實踐w線程模塊化時間函數(shù)和設(shè)計問題_第5頁
已閱讀5頁,還剩72頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、模塊化設(shè)計問題1提綱1. 使用線程實現(xiàn)任務(wù)并發(fā)2. 模塊化和工程3. 概要設(shè)計要點4. 時間控制函數(shù)5. 有限狀態(tài)自動機(jī)解題21.使用線程實現(xiàn)任務(wù)并發(fā)問題的引出:以電梯控制系統(tǒng)為例目前能想到的程序主體結(jié)構(gòu) main() while (1) state_trans(); /計算此刻電梯的狀態(tài) print_message(); /輸出電梯此刻的狀態(tài),包括動畫 get_input(); /接收當(dāng)前時刻的新輸入(包括新目 標(biāo)和新呼叫) control(); /*根據(jù)控制策略確定下一目標(biāo)樓層, 在state_trans()中要用到 */ time_count(); /時間片推進(jìn)一個 思考:上述結(jié)構(gòu)不合理

2、之處? 31.使用線程實現(xiàn)任務(wù)并發(fā)上述結(jié)構(gòu)不合理之處:計算和輸出電梯狀態(tài)與接收服務(wù)請求是串行的,與現(xiàn)實中的電梯運行不符!程序結(jié)構(gòu)的改進(jìn):從上述代碼中刪除get_input(),從而實現(xiàn)每隔一小段時間就刷新電梯當(dāng)前狀態(tài) main() while (1) state_trans(); /計算此刻電梯的狀態(tài) print_message(); /輸出電梯此刻的狀態(tài) control(); /*根據(jù)控制策略確定下一目標(biāo)樓層,這 在state_trans()中要用到 */ time_count(); /時間片推進(jìn)一個 41.使用線程實現(xiàn)任務(wù)并發(fā)但是,程序必須要能接收電梯服務(wù)請求,如何處理服務(wù)請求的輸入?理想

3、狀態(tài):電梯服務(wù)請求的接收和電梯狀態(tài)的計算輸出能同時進(jìn)行,互不影響但是,能否實現(xiàn)?答案是:使用線程電梯狀態(tài)計算和輸出共享內(nèi)存區(qū)接收服務(wù)請求51.使用線程實現(xiàn)任務(wù)并發(fā)進(jìn)程一個正在運行的程序的實例,是一個程序在其自身的地址空間中的一次執(zhí)行活動,例如用字處理軟件編輯文稿時,同時打開mp3播放程序聽音樂,這兩個獨立的程序在同時運行,稱為兩個進(jìn)程進(jìn)程是資源申請、調(diào)度和獨立運行的單位61.使用線程實現(xiàn)任務(wù)并發(fā)線程線程是系統(tǒng)分配處理器時間資源的基本單元。對于操作系統(tǒng)而言,其調(diào)度單元是線程(為線程提供時間片,線程在自己的時間片內(nèi)運行)。一個程序中多段代碼同時并發(fā)執(zhí)行,稱為多線程譬如用word同時打開多個文檔進(jìn)行

4、編輯,用IE瀏覽器同時訪問多個網(wǎng)站通過多線程,一個進(jìn)程表面上看同時可以執(zhí)行一個以上的任務(wù)并發(fā)7線程(續(xù))一個進(jìn)程至少包括一個線程(稱為主線程)。一個進(jìn)程從主線程的執(zhí)行開始進(jìn)而創(chuàng)建一個或多個附加線程,就是所謂基于多線程的多任務(wù)。線程自己不擁有系統(tǒng)資源,但它可與同屬一個進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源81.使用線程實現(xiàn)任務(wù)并發(fā)在C程序中要創(chuàng)建線程,可以調(diào)用Windows操作系統(tǒng)提供的創(chuàng)建線程的函數(shù)CreateThread :HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPT

5、HREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); LPVOID是一個Void類型的指針,也就是說你可以將任意類型的指針賦值給LPVOID類型的變量。DWORD是32位無符號整數(shù)。91.使用線程實現(xiàn)任務(wù)并發(fā)lpThreadAttributes表示創(chuàng)建線程的安全屬性,NT下有用。可賦值為NULL。dwStackSize指定線程棧的尺寸,如果為0則與進(jìn)程主線程棧相同。lpStartAddress指定線程開始運行的地址。賦值為指向函數(shù)的指針,即函數(shù)名。該

6、函數(shù)的名稱任意,但函數(shù)類型必須遵照下述聲明形式:DWORD WINAPI ThreadProc(LPVOID lpParameter);否則需要進(jìn)行強(qiáng)制類型轉(zhuǎn)換lpParameter表示傳遞給線程的32位的參數(shù)(數(shù)值或指針)。 若無參數(shù)則賦值為NULL。dwCreationFlags表示是否創(chuàng)建后掛起線程(取值CREATE_SUSPENDED表示掛起,取值0表示創(chuàng)建后立即運行),掛起后調(diào)用ResumeThread繼續(xù)執(zhí)行。若不掛起則賦值為0。lpThreadId用來存放返回的線程ID。 DWORD ThreadID1 = 1; HANDLE hRead1 = CreateThread(NULL

7、,0,(LPTHREAD_START_ROUTINE)getInput, NULL,0,&ThreadID1);10#include#includeDWORD WINAPI Fun1Proc(LPVOID lpParameter);int main()HANDLE hThreadl;/hThreadl=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); /CloseHandle(hThreadl); /printf(main thread is runningn); /return 0;11DWORD WINAPI Fun1Proc(LPVOID lpPara

8、meter)printf(hThreadl is runningn);return 0;例112#include#includeDWORD WINAPI Fun1Proc(LPVOID lpParameter)int main()HANDLE hThreadl;/hThreadl=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); /CloseHandle(hThreadl); /printf(main thread is runningn); / Sleep(10);/讓線程睡眠10毫秒return 0;例2#include#includeint index

9、=0;DWORD WINAPI Fun1Proc(LPVOID lpParameter);int main()HANDLE hThreadl;/hThreadl=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); /CloseHandle(hThreadl); /while(index+1000)printf(main thread is runningn); /return 0;13例3DWORD WINAPI Fun1Proc(LPVOID lpParameter)while(index+1000)printf(hThreadl is runningn);

10、return 0;1415#include#includeint tickets=100;DWORD WINAPI Fun1Proc(LPVOID pPararneter)while(tickets0)printf(“thread1 sell ticket : %dn”,tickets-);return 0;DWORD WINAPI Fun2Proc(LPVOID pPararneter) while(tickets0) printf(“thread2 sell ticket : %dn”,tickets-); return 0;int main()HANDLE hThread1=Create

11、Thread(NULL,0,Fun1Proc,NULL,0,NULL);HANDLE hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);CloseHandle(hThread1);CloseHandle(hThread2);Sleep(4000);return 0;1617線程的同步利用互斥對象(mutex)實現(xiàn)線程的同步,互斥對象能夠確保線程擁有對單個資源的互斥訪問權(quán)。3個操作互斥對象的創(chuàng)建互斥對象的釋放互斥對象的請求18互斥對象的創(chuàng)建HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttri

12、butes ,BOOL binitialOwner,LPCTSTR lpNarne)lpMutexAttributes:可以給該參數(shù)傳遞 NULL值,讓互斥對象使用默認(rèn)的安全性binitialOwner:BOOL類型,指定互斥對象初始的擁有者。如果該值為真,則創(chuàng)建這個互斥對象的線程獲得該對象的所有權(quán);否則,該線程將不獲得所創(chuàng)建的互斥對象的所有權(quán)。lpName:指定互斥對象的名稱。如果此參數(shù)為 NULL.則創(chuàng)建一個匿名的互斥對象。如果調(diào)用成功,該函數(shù)將返回所創(chuàng)建的互斥對象的句柄19互斥對象的釋放BOOL ReleaseMutex ( HANDLE hMutex );ReleaseMutex函數(shù)只

13、有一個HANDLE類型的參數(shù),即需要釋放的互斥對象的句柄。該函數(shù)的返回值是BOOL類型,如果函數(shù)調(diào)用成功,返回非0值;否則返回0值。20互斥對象的請求DWORD WaitForSingleObject( HANDLE hHandle , DWORD dwMilliseconds );Handle:所請求的互斥對象的句柄。一旦互斥對象處于有信號狀態(tài),則該函數(shù)就返回。如果該互斥對象始終處于無信號狀態(tài),即未通知的狀態(tài),則該函數(shù)就會一直等待,這樣就會暫停線程的執(zhí)行。dwMilliseconds:指定等待的時間間隔,以毫秒為單位。如果指定的時間間隔己過,即使所請求的對象仍處于無信號狀態(tài),WaitForS

14、ingleObject函數(shù)也會返回。如果將此參數(shù)設(shè)置為0,那么 WaitForSingleObject函數(shù)將測試該對象的狀態(tài)并立即返回;如果將此參數(shù)設(shè)置為INFINITE, 則該函數(shù)會永遠(yuǎn)等待,直到等待的對象處于有信號狀態(tài)才會返回。調(diào)用WaitForSingleObject函數(shù)后,該函數(shù)會一直等待,只有在以下兩種情況下才會返回: 1)指定的對象變成有信號狀態(tài)。2)指定的等待時間間隔己過。21HANDLE hMutex;int tickets=100;DWORD WINAPI Fun1Proc(LPVOID pPararneter)while(tickets0)WaitForSingleObje

15、ct(hMutex,INFINITE);if(tickets0)printf(thread1 sell ticket : %dn,tickets-);ReleaseMutex(hMutex);return 0;22DWORD WINAPI Fun2Proc(LPVOID pPararneter)while(tickets0)WaitForSingleObject(hMutex,INFINITE);if(tickets0) printf(thread2 sell ticket : %dn,tickets-);ReleaseMutex(hMutex);return 0;23int main()HA

16、NDLE hThread1,hThread2;hMutex=CreateMutex(NULL,FALSE,NULL);hThread1=CreateThread(NULL,0,Fun1Proc,NULL ,0,NULL);hThread2=CreateThread(NULL,0,Fun2Proc,NULL ,0,NULL);CloseHandle(hThread1);CloseHandle(hThread2);Sleep(4000);return 0;24線程在電梯控制系統(tǒng)中的使用考慮現(xiàn)實中安裝在電梯上的軟件:接收電梯服務(wù)請求和計算電梯狀態(tài)、從而控制電梯的運行是并行的因此我們可以考慮在模擬電梯

17、控制系統(tǒng)中設(shè)計一個線程專門用于接收電梯服務(wù)請求,另一個線程實行電梯的狀態(tài)計算和狀態(tài)輸出電梯狀態(tài)計算和輸出線程共享內(nèi)存區(qū)接收服務(wù)請求電梯狀態(tài)計算和輸出:從共享內(nèi)存區(qū)讀取電梯請求,計算下一目標(biāo)樓層,從而確定電梯的下一狀態(tài)。接收服務(wù)請求:接收電梯請求,將請求保存到內(nèi)存。25/主線程main() DWORD ThreadID ; /創(chuàng)建線程(對應(yīng)于函數(shù)input(),用于接收電梯輸入; HANDLE hRead = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput,NULL,0,&ThreadID); /進(jìn)行變量初始化工作 線程在電梯控制系統(tǒng)中的

18、使用26while (1) state_trans(); ();/根據(jù)自動機(jī)模型決定此刻電梯的狀態(tài) print_message();/*輸出電梯此刻的狀態(tài)*/ control(); /*根據(jù)控制策略確定下一目標(biāo)樓層,這在 state_trans()中要用到 */ time_count(); /*時間片推進(jìn)一個*/ 線程在電梯控制系統(tǒng)中的使用27/接收輸入線程void getInput(void) char ch; while(1) ch=getchar(); /加入代碼:將ch翻譯成相應(yīng)請求并保存; time_count();/時間片推進(jìn)一個; 線程在電梯控制系統(tǒng)中的使用28提綱1. 使用線程

19、實現(xiàn)任務(wù)并發(fā)2. 軟件設(shè)計和模塊化3. 概要設(shè)計要點4. 時間控制函數(shù)5. 有限狀態(tài)自動機(jī)解題296.1 軟件設(shè)計概述軟件設(shè)計在開發(fā)階段中的重要性需求分析模型中的每一個成份都提供了建立設(shè)計模型所需的信息。根據(jù)數(shù)據(jù)、功能和行為模型來表示的軟件需求,采用某種設(shè)計方法進(jìn)行數(shù)據(jù)設(shè)計、系統(tǒng)結(jié)構(gòu)設(shè)計和過程設(shè)計。軟件需求分析:(1)問題的信息域必須被表示和理解。(數(shù)據(jù)模型)(2)軟件將完成的功能必須被定義。(功能模型)(3)軟件的行為(作為外部事件的結(jié)果)必須被表示。 (行為模型)31數(shù)據(jù)模型問題的信息域包含三個不同的數(shù)據(jù)和控制視圖:(1)信息內(nèi)容和關(guān)系信息內(nèi)容表示了個體數(shù)據(jù)和控制對象,它們可和其他的數(shù)據(jù)和

20、控制對象關(guān)聯(lián)。(2)信息流信息流表示了數(shù)據(jù)和控制在系統(tǒng)中流動時變化的方式。(3)信息結(jié)構(gòu)信息結(jié)構(gòu)表示了各種數(shù)據(jù)和控制項的內(nèi)部組織。 功能模型對進(jìn)入軟件的信息和數(shù)據(jù)進(jìn)行變換和處理的模塊,它必須至少完成三個常見功能:輸入、處理和輸出。功能模型從頂層的語境層模型開始,經(jīng)過一系列的細(xì)化迭代,越來越多的功能細(xì)節(jié)被發(fā)現(xiàn),直至得到所有系統(tǒng)功能。 4.3 軟件需求分析建模的原則和方法行為模型大多數(shù)軟件對來自外界的事件做出反應(yīng),這種刺激反應(yīng)特征形成了行為模型的基礎(chǔ)。一個計算機(jī)程序總是處于某個狀態(tài):一種外部可觀測的行為模式(如等待、運行),它僅當(dāng)某事件發(fā)生時才被改變。6.1 軟件設(shè)計概述 分析模型轉(zhuǎn)換為軟件設(shè)計的

21、映射關(guān)系6.1 軟件設(shè)計概述數(shù)據(jù)設(shè)計將實體關(guān)系圖中描述的對象和關(guān)系,以及數(shù)據(jù)詞典中描述的詳細(xì)數(shù)據(jù)內(nèi)容轉(zhuǎn)化為數(shù)據(jù)結(jié)構(gòu)的定義。系統(tǒng)結(jié)構(gòu)設(shè)計定義軟件系統(tǒng)各主要成份之間的關(guān)系。接口設(shè)計根據(jù)數(shù)據(jù)流圖定義軟件內(nèi)部各成份之間、軟件與其它協(xié)同系統(tǒng)之間以及軟件與用戶之間的交互機(jī)制。過程設(shè)計則是把結(jié)構(gòu)成份轉(zhuǎn)換成軟件的過程性描述。在編碼階段,根據(jù)這種過程性描述,生成源程序代碼,最終通過測試得到完整有效的軟件。6.1 軟件設(shè)計概述軟件設(shè)計是開發(fā)階段中最重要的步驟,它是軟件開發(fā)過程中質(zhì)量得以保證的關(guān)鍵步驟。軟件設(shè)計又是將用戶要求準(zhǔn)確地轉(zhuǎn)化成為最終的軟件產(chǎn)品的唯一途徑。軟件設(shè)計是后續(xù)開發(fā)步驟及軟件維護(hù)工作的基礎(chǔ)。軟件設(shè)計

22、對后期開發(fā)的質(zhì)量影響6.1 軟件設(shè)計概述軟件設(shè)計的過程從工程管理角度來看,軟件設(shè)計分兩步完成。概要設(shè)計:將軟件需求轉(zhuǎn)化為數(shù)據(jù)結(jié)構(gòu)和軟件的系統(tǒng)結(jié)構(gòu)模塊;決定每個模塊的功能;決定模塊之間的調(diào)用關(guān)系,即模塊間傳遞的數(shù)據(jù);決定模塊的接口。詳細(xì)設(shè)計:在概要設(shè)計基礎(chǔ)上確定如何實現(xiàn)各模塊的內(nèi)部細(xì)節(jié),即對模塊內(nèi)部的算法和數(shù)據(jù)結(jié)構(gòu)進(jìn)行設(shè)計,產(chǎn)生詳細(xì)設(shè)計文檔。在后續(xù)的編碼階段就可以完全按照詳細(xì)設(shè)計的細(xì)節(jié)過程來映射到代碼,最終實現(xiàn)整個系統(tǒng)2.模塊化和工程將復(fù)雜問題分解為若干較小問題,然后再去求解,有助于控制問題的復(fù)雜性,利于問題的解決。模塊化:把程序劃分成獨立命名且可獨立訪問的模塊,每個模塊完成一個子功能(解決一個

23、子問題),所有模塊集成起來構(gòu)成的整體可完成用戶的所有需求。高層模塊從整體上把握問題, 隱蔽細(xì)節(jié)。低層模塊解決細(xì)節(jié)問題。模塊化意義降低了系統(tǒng)的復(fù)雜性,使系統(tǒng)容易修改和重用;推動系統(tǒng)各部分的并行開發(fā),提高開發(fā)效率。復(fù)雜問題 較小問題分解392.模塊化和工程模塊的定義一般把用一個名字就可調(diào)用的一段程序稱為“模塊”,如子程序、函數(shù)等。函數(shù)是最小的模塊,若干個緊密相關(guān)的函數(shù)可以組成更大的模塊源文件。模塊的基本屬性:功能:描述該模塊實現(xiàn)什么功能邏輯:描述模塊內(nèi)部怎么做狀態(tài):該模塊使用時的環(huán)境和條件402.模塊化和工程除了基本屬性,還需描述模塊的內(nèi)部和外部特性模塊的外部特性:模塊的模塊名、參數(shù)表模塊的內(nèi)部特

24、性:完成其功能的程序代碼和僅供該模塊內(nèi)部使用的數(shù)據(jù)通常是先確定模塊的外部特性(概要設(shè)計的任務(wù)),再確定其內(nèi)部特性(詳細(xì)設(shè)計的任務(wù))。怎么樣對系統(tǒng)進(jìn)行模塊劃分才是好的劃分?412.模塊化和工程 模塊劃分得越細(xì)越好嗎?模塊大小、模塊數(shù)目與費用的關(guān)系2.模塊化和工程信息隱藏如何分解一個軟件才能得到最佳的模塊組合?需要了解什么是“信息隱藏”。Parnas:每個模塊的實現(xiàn)細(xì)節(jié)對于其它模塊來說是隱蔽的。就是說,模塊中所包含的信息(包括數(shù)據(jù)和過程)不允許其它不需要這些信息的模塊使用。信息隱藏使得在將來修改軟件時偶然引入錯誤所造成的影響可以局限在一個或幾個模塊內(nèi)部,不致波及到軟件的其它部分。6.4 軟件設(shè)計原

25、則4. 模塊的獨立性模塊獨立性是指軟件系統(tǒng)中每個模塊只涉及軟件要求的具體的子功能,而和軟件系統(tǒng)中其它的模塊的接口是簡單的。一般采用兩個準(zhǔn)則度量模塊獨立性,即模塊間耦合和模塊內(nèi)聚。(1978年Meyer)耦合是模塊之間的互相連接的緊密程度的度量。內(nèi)聚是模塊功能強(qiáng)度(一個模塊內(nèi)部各個元素彼此結(jié)合的緊密程度)的度量。模塊獨立性比較強(qiáng)的模塊應(yīng)是高內(nèi)聚低耦合的模塊。2.模塊化和工程(1) 內(nèi)聚性(Cohesion)內(nèi)聚是模塊功能強(qiáng)度(一個模塊內(nèi)部各個元素彼此結(jié)合的緊密程度)的度量。一個內(nèi)聚程度高的模塊(在理想情況下)應(yīng)當(dāng)只做一件事。一般模塊的內(nèi)聚性分為七種類型。模塊的內(nèi)聚度量2.模塊化和工程(2) 耦合

26、性(Coupling)耦合是模塊之間的相對獨立性(互相連接的緊密程度)的度量。它取決于各個模塊之間接口的復(fù)雜程度、調(diào)用模塊的方式以及哪些信息通過接口。一般模塊之間可能的連接方式有七種,構(gòu)成耦合性的七種類型。模塊的耦合性度量2.模塊化和工程C語言中的分塊開發(fā)C語言允許一個程序由多個源文件組成。當(dāng)程序規(guī)模比較大時,可以根據(jù)模塊化原則將程序分成多個.c源文件,每個源文件看作是一個模塊,每個源文件中可包含一個或多個功能連接緊密的函數(shù)。在編譯該程序時,可以以源文件為單位分別進(jìn)行編譯,產(chǎn)生對應(yīng)的目標(biāo)文件,然后再用鏈接程序?qū)⒍鄠€目標(biāo)文件鏈接成一個可執(zhí)行文件。C語言的這種編譯過程稱為分塊編譯,這種開發(fā)方法稱為

27、分塊開發(fā)47C程序由后綴為.c的源文件和后綴為.h的頭文件組成。前者包含實際的程序代碼,后者為.c源文件提供輔助性信息。在確定一個程序要劃分成幾個源文件,每一個源文件要包含哪些函數(shù)時,需要以提高模塊獨立性為原則,將相關(guān)的功能放在一起,形成一個源文件。通常,輸入和輸出有關(guān)的函數(shù)放在一個文件中;主函數(shù)單獨建立一個文件,其中也可以包含少數(shù)與它關(guān)系密切的其他函數(shù)的定義48頭文件的確定把所有公用的類型定義(結(jié)構(gòu)、聯(lián)合或枚舉聲明),公用的宏定義放在適當(dāng)?shù)念^文件中,供各個文件參考。如果在許多地方都使用一個(些)標(biāo)準(zhǔn)頭文件,或者某個頭文件本身需要,則可以把標(biāo)準(zhǔn)頭文件包含到一個自己定義的頭文件里供使用。如果只有

28、一個源文件需要某個標(biāo)準(zhǔn)頭文件,則不要將它放在公共的頭文件中,而是讓這個源文件直接包含它,以提高編譯效率。對于所有在一個源文件里定義、而在其他文件中使用的東西(函數(shù)原型或者變量的外部聲明),都需要在某個頭文件中聲明,以方便使用。49源文件設(shè)計時要注意以下問題:每個源文件只包含必要的頭文件,不用的東西盡量不包含。如果源文件既要包含標(biāo)準(zhǔn)頭文件,又要包含自定義頭文件,則應(yīng)將標(biāo)準(zhǔn)頭文件寫在前面,以防止本程序的局部定義影響標(biāo)準(zhǔn)庫文件里的定義。在一個源文件中,所有局部的東西都寫在各自的函數(shù)中;所有只在本文件范圍內(nèi)使用的外部變量和函數(shù),都使用static關(guān)鍵字定義為外部靜態(tài)的。對于多個函數(shù)都需要訪問的變量,應(yīng)

29、該根據(jù)誰使用誰管理的歸屬原則,分別定義為不同源文件里的外部變量。在許多文件中都使用的全局變量,一般在主程序文件里定義。502.模塊化和工程實例:猴子選大王如何模塊化linkNode.h:提供鏈表結(jié)點listNode、別名LISTNODE和LISTNODEPTR的定義link.c: 提供鏈表處理相關(guān)函數(shù)link.h:提供link.c中函數(shù)的函數(shù)原型main.c: 實現(xiàn)選大王算法2.模塊化和工程VC6.0下工程的創(chuàng)建模塊之間的交互:數(shù)據(jù)共享、函數(shù)調(diào)用如何實現(xiàn)不同模塊之間的數(shù)據(jù)共享和函數(shù)調(diào)用?-再論函數(shù)52提綱1. 使用線程實現(xiàn)任務(wù)并發(fā)2. 模塊化和工程3. 概要設(shè)計要點4. 時間控制函數(shù)5. 有限

30、狀態(tài)自動機(jī)解題533.概要設(shè)計要點概要設(shè)計的目的:全局把握程序結(jié)構(gòu):進(jìn)行程序的模塊劃分,設(shè)計模塊之間如何相互調(diào)用來完成程序要求的功能。定義關(guān)鍵變量,用來存儲各模塊共享的數(shù)據(jù);定義常量。設(shè)計關(guān)鍵的算法,主要是控制策略,提前對關(guān)鍵的、較難解決的問題進(jìn)行處理。543.概要設(shè)計要點概要設(shè)計主要從以下5個方面考慮:用戶界面:界面友好,要能從界面提示信息了解電梯/火車/銀行的狀態(tài)和請求。自動機(jī)模型:電梯/火車/營業(yè)窗口的行為可以用自動機(jī)模型來描述。繪制狀態(tài)遷移圖,圖上需要描述引起狀態(tài)遷移的條件,并且要在文檔中附加說明進(jìn)入某狀態(tài)要做的動作。全局變量:較全面地給出了各個函數(shù)要共享的數(shù)據(jù)。程序模塊化:函數(shù)接口說

31、明,函數(shù)調(diào)用關(guān)系說明。調(diào)度算法:給出電梯、小火車調(diào)度或者銀行調(diào)度的算法。55 3-1 用戶界面(1)點評:界面上增加各層向上向下請求對應(yīng)的字符,以便于操作;電梯請求展示區(qū)需要再細(xì)化,分別顯示:向上請求、向下請求,電梯內(nèi)請求。 很漂亮,不過展示的信息太少563-1 用戶界面(2)電梯內(nèi)部描述573-2 自動機(jī)模型思考:該圖存在的問題?583-3 全局變量函數(shù)之間如何通信?全局變量或者參數(shù)線程之間如何通信?全局變量或者參數(shù)全局變量設(shè)計考慮要全面;應(yīng)明確給出定義,如:int destLayer;/記錄電梯下一目標(biāo)服務(wù)樓層593-4 程序模塊化應(yīng)該說明程序的模塊結(jié)構(gòu),包括:整個程序分成哪幾個文件?每一

32、個文件里面包含哪些函數(shù)?函數(shù)原型說明?圖示說明函數(shù)調(diào)用關(guān)系。要考慮策略可切換的問題:如何設(shè)計模塊,使得當(dāng)增加一個新的策略時,對現(xiàn)有代碼的修改盡量少?進(jìn)行清楚的描述。603-5 關(guān)鍵算法給出調(diào)度算法設(shè)計算法思路要有助于進(jìn)一步設(shè)計,不能很粗略61提綱1. 使用線程實現(xiàn)任務(wù)并發(fā)2. 模塊化和工程3. 概要設(shè)計要點4. 時間控制函數(shù)5. 有限狀態(tài)自動機(jī)解題624.1-計時函數(shù)while (1) state_trans(); ();/根據(jù)自動機(jī)模型決定此刻電梯的狀態(tài) print_message();/*輸出電梯此刻的狀態(tài)*/ control(); /*根據(jù)控制策略確定下一目標(biāo)樓層,這在 state_tr

33、ans()中要用到 */ time_count(); /*時間片推進(jìn)一個*/ 634.1-計時函數(shù)clock_t clock( void );ANSI標(biāo)準(zhǔn)庫中的time.h頭文件,其中定義了日期和時間的處理函數(shù)。 這個函數(shù)返回從“啟動程序”到“程序中調(diào)用clock()函數(shù)”之間的CPU時鐘計時單元(clock tick)數(shù),在MSDN中稱之為掛鐘時間(wal-clock)。其中clock_t是用來保存時間的數(shù)據(jù)類型,長整型。clock tick:CPU時鐘計時單元,時間長短由CPU控制。一個clock tick不是CPU的一個時鐘周期,而是C/C+的一個基本計時單位。常量CLOCKS_PER_

34、SEC,它表示一秒鐘會有多少個時鐘計時單元 。 可以使用公式clock()/CLOCKS_PER_SEC來計算一個進(jìn)程自身的運行時間。644.1-計時函數(shù)#include “stdio.h”#include “stdlib.h”#include “time.h”int main( void )longi = 10000000L;clock_t start, finish;doubleduration;/* 測量一個事件持續(xù)的時間*/printf( “Time to do %ld empty loops is ”, i );start = clock();while( i- );/什么都不做 f

35、inish = clock();duration = (double)(finish - start) / CLOCKS_PER_SEC;printf( %f secondsn, duration );system(pause);654.1-計時函數(shù)下述循環(huán)將持續(xù)運行1秒鐘clock_t start, finish;doubleduration;start = clock();duration=0.0;while(duration1.0) finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; 664.2-

36、線程休眠函數(shù)線程休眠函數(shù):Sleep(int);Sleep(1000)Windows下表示1000毫秒,也就是1秒鐘;Linux下表示1000秒,Linux下使用毫秒級別的函數(shù)可以使用usleep。 Sleep函數(shù)是使調(diào)用Sleep函數(shù)的線程休眠,線程主動放棄時間片。當(dāng)經(jīng)過指定的時間間隔后,再啟動線程,繼續(xù)執(zhí)行代碼。Sleep函數(shù)并不能起到定時的作用,主要作用是延時。 #include #include /注意頭文件一定要包含int main () int i=9;while(i1) Sleep(1000); /線程被掛起1秒,相當(dāng)于機(jī)器運行到這里停頓1秒,再繼續(xù)向下運行; printf(A)

37、;i-; system(pause);return 0;67提綱1. 使用線程實現(xiàn)任務(wù)并發(fā)2. 模塊化和工程3. 概要設(shè)計要點4. 時間控制函數(shù)5. 有限狀態(tài)自動機(jī)解題685.有限狀態(tài)自動機(jī)解題第一步:畫出狀態(tài)轉(zhuǎn)換圖第二步:針對每一種狀態(tài),進(jìn)一步分別分析:當(dāng)輸入為字符1時,需要做什么工作,下一個狀態(tài)是什么如刪除注釋一題中要做的工作就是往目標(biāo)文件中寫入非注釋部分的字符;當(dāng)輸入為字符2時,需要做什么工作,下一個狀態(tài)是什么;第三步:編碼。將要做的工作和狀態(tài)的遷移用代碼表示出來69練習(xí):輸入一個字符串,以回車結(jié)束;判斷該字符串是否是合法的C語言整型變量定義。C語言變量名必須由下劃線、字母或者數(shù)字組成,

38、且第一個字符是下劃線或者字母。int _myVariable, count; /合法int 8Count; /非法要求:先畫出本題的有限狀態(tài)自動機(jī)轉(zhuǎn)換圖,然后書寫程序。5.有限狀態(tài)自動機(jī)解題705.有限狀態(tài)自動機(jī)解題程序71q1:最近接收到的是/ q5:已收到/ , 注釋已經(jīng)開始 q4:非注釋狀態(tài) q3:等待/以結(jié)束注釋q2:已收到/* , 注釋已經(jīng)開始上機(jī)題講解【源程序】72電梯系統(tǒng)的state_trans函數(shù)設(shè)計73電梯系統(tǒng)的state_trans函數(shù)設(shè)計void state_trans() switch (state) /*根據(jù)狀態(tài)和事件 ,進(jìn)行相應(yīng)的處理*/ case IDLE: if

39、 (存在其他樓層的呼叫事件) /執(zhí)行相關(guān)工作; state=RUN; if(存在本樓層的呼叫事件 ) /執(zhí)行相關(guān)工作; state=STOP; /*電梯狀態(tài)設(shè)置為???/ break; 74電梯系統(tǒng)的state_trans函數(shù)設(shè)計 case RUN: . break; case STOP: . break; default: break; 75769、靜夜四無鄰,荒居舊業(yè)貧。9月-229月-22Sunday, September 18, 202210、雨中黃葉樹,燈下白頭人。21:20:1021:20:1021:209/18/2022 9:20:10 PM11、以我獨沈久,愧君相見頻。9月-2221:20:1021:20Sep-2218-Sep-2212、故人江海別,幾度隔山川。21:20:1021:20:1021:20Sunday, September 18, 202213、乍見翻疑夢,相悲各問年。9月-229月-2221:20:1021:20:10September 18, 202214、他鄉(xiāng)生白發(fā),舊國見青山。18 九月 20229:20:10 下午21:20:109月-2215、比不了得就不比,得不到的就不要。九月 229:20 下午9月-2221:20September 18, 202216、行動出成果,工作出財富。2022/9/18 21:20:1021:20:10

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論