當前位置:
首頁 > 最新 > C語言快速入門——笑臉繪圖程序:最終實現

C語言快速入門——笑臉繪圖程序:最終實現

數據需求概要

數據部分包括對圖形元素的定義及管理。定義是指用一個合適的數據類型描述圖元,還記得我們如何描述貓這種動物嗎?在這個程序中,我們主要操作坐標點,可想而知,用一個struct定義一個Point類型再合適不過了。管理則是指針對此數據類型的操作,比如說我們可以用一個數組管理程序中的活動點,並定義針對此數組的操作等。程序的核心數據與操作由Primitive.h描述。


Primitive.h


數據點

程序定義了Point類型用於描述一個二維點。數組 pts[MAX_POINTS] 用於管理程序使用的點集合,這裡被限制為最多存儲64個點,這也表示在繪圖窗口最多只能畫64個笑臉。

觀察者

數組 obs[MAX_OBSERVERS] 用於關聯窗口的三部分。之所以使用int數組,是因為這三部分的消息輸出由三個不同的函數控制,而我們目前沒法把它們放到一個集合中,所以我們用一個數字ID關聯到一個具體函數。另一種可行的方案是為每部分設置一個標誌值,此值打開時,執行輸出操作,否則不做任何動作。

根據前面概覽介紹可知,觀察者可以隨時被註冊或註銷,這種方案下就是設置bool值為true或false。直接在程序中插入設置這些變數的語句會使程序整體顯得混亂,好的方法就是為它們提供enable/disable函數。

圖元結構體

最後我們使用Primitive結構體將這兩者結合起來,這只是一種可能的設計策略,響應一下我們上節提到的理念:程序通常圍繞兩個方面進行:數據與數據操作。結構體可以有效的組織數據,函數則可以針對數據進行處理。


initPrimitve函數用於初始化數據,在這裡是使數據處於未使用狀態。uninitPrimitive函數則用於程序退出時執行數據清理操作。事實上在這個程序中,可以什麼都不用做。我們象徵性的加入觀察者註銷操作,表示與通知部分斷開連接。

至此,你也可以大致猜測到其它方法的實現。

不同的是,在addObserver中,對同一id(也就是窗口的某一部分)只允許註冊一次。

在addPoint/deletePoint中,則會有發出通知讓窗口三部分進行處理的消息。

這裡是通知函數。

在觀察者ID是OBWINDOW時,程序根據當前的動作(添加/刪除)來設置clear變數,以告訴window函數當前是繪製點還是擦除點。在OBLOG的情況下,則直接把格式化後的信息傳遞給log函數進行輸出。


觀察者介面與實現被安排在Observer.h/Observer.c中。這裡是Observer.h,注意其中的一個細節。

函數window與console中使用了自定義類型Point,但這裡卻沒有包含Primitive.h。在講解函數時我們提過,函數在被使用之前其名稱必須是可見的,由struct定義的類型也同樣需要。對於struct定義的類型,在看到其聲明後就可以定義其指針變數,但不能定量實例變數,如下:

因為在定義實例變數時,需要完全看到結構體的定義,這樣才能分配合理的內存空間。只有一個聲明時,誰都不知道應該分配多少,因此是錯誤的。但對於指針,其實在32位環境下,不管什麼類型的指針,都佔4個位元組,因此pfoo的定義是可行的。這些內容知道就行,以後會細講。

你可以嘗試注釋掉代碼中struct Point;聲明,然後包含頭文件Primitive.h,這時編譯會出錯,因為整個項目中,Primitive.h會被多次包含,而類型(這裡指struct Point等)只能定義一次,多次包含導致多次定義錯誤。這可以使用頭文件守衛宏解決,同樣,知道就行。

這些介面的實現細節相當簡單,具體可以下載代碼查看。


只需要知道在主函數中調用了_getch()函數,它是getch()的安全版本,用於讀取輸入流中的一個字元,這樣可以保證你按下一個鍵程序就執行下一段,剩餘的就是將整個程序組裝起來,至此整個程序完結。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 皮拉夫大王 的精彩文章:

C語言快速入門——引入結構體

TAG:皮拉夫大王 |