easyX作為一個第三方圖形庫祷膳,出現(xiàn)問題時問題的原因往往不容易找出來陶衅。比如一個圖形不移動的時候,可能是鏈表出了問題钾唬,也可能是圖像輸出部分參數(shù)有錯誤万哪,如果漫無目的的一次次看源代碼侠驯,可能要很久才能找出原因抡秆;又因為第三方圖形庫往往不能方便的分步調(diào)試,這時候一個合理的調(diào)試方法就變得非常重要吟策。
不同的程序中儒士,所需要的調(diào)試方法各不相同,一個合理的調(diào)試方法應(yīng)該可以幫助找到問題的發(fā)生點檩坚,最好能獨立于程序的運行輸出調(diào)試結(jié)果着撩,可以保留程序出錯的軌跡。
雖說easyX不能直接使用調(diào)試工具進行調(diào)試匾委,但easyX本身在設(shè)計的時候給我們留下了很多可以使用的調(diào)試手段拖叙。下面就來結(jié)合昨天晚上的實例說一說這些調(diào)試方法的具體應(yīng)用逼泣,希望可以給做課設(shè)的同學們打開一些思路真友。
最簡單的斷點調(diào)試
斷點調(diào)試設(shè)置最簡單,不需要添加任何語句月而,可以結(jié)合IDE的功能做一些簡單的判斷挨措,比如當程序無法正正常執(zhí)行但又不報錯時挖滤,可以通過斷點觀察變量的值,或者觀察程序是否陷入死循環(huán)無法執(zhí)行到某一行浅役。
如上圖所示斩松,當我拿到程序之后,程序不報錯觉既,但是不能正常運行惧盹,代碼結(jié)構(gòu)看起來問題又不大,因為是別人的代碼瞪讼,從頭看代碼縷清思路又不現(xiàn)實钧椰,所以我做的第一步就是在程序運行的主循環(huán)中各個函數(shù)設(shè)置斷點。
當我將斷點設(shè)置在getMOVE函數(shù)中時尝艘,斷點無法觸發(fā)演侯,說明程序無法執(zhí)行到getMOVE這一行,在之前的函數(shù)中陷入了死循環(huán)背亥。
而當我將斷點設(shè)置到fishmove中時秒际,斷點觸發(fā)悬赏,說明死循環(huán)位于fishmove函數(shù)中,接下來我就可以有針對性的解決這個函數(shù)中的死循環(huán)問題娄徊,解決之后更便于從整體考慮問題闽颇。
使用命令行調(diào)試
使用命令行調(diào)試是使用easyX調(diào)試程序的最好的方法。比起觀察圖像的變化寄锐,使用命令行調(diào)試可以像寫普通程序一樣兵多,使用printf直接輸出其中的變量以變量的值,更直觀且更精確橄仆,而且很多圖像無法反映出來的數(shù)據(jù)剩膘,只能通過命令行進行輸出。
如何使用命令行輸出
在初始化繪圖環(huán)境的時候盆顾,使用如下語句進行初始化:
initgraph(640, 480, SHOWCONSOLE);
即在坐標后加參數(shù)SHOWCONSOLE怠褐,即可在顯示圖形界面的時候保留命令行窗口,接下來就可以使用printf等語句進行調(diào)試您宪。
下面舉幾個使用命令行調(diào)試的例子奈懒,供大家打開思路,來源均來自于昨天調(diào)試的代碼:
判斷鏈表是否操作正常
鏈表讓很多同學頭疼宪巨,尤其是在圖形界面下原因難以判斷的時候更是如此磷杏,當其他部分還存在問題時,只通過圖形界面根本無法判斷鏈表是否正常工作捏卓,這個時候就可以使用命令行來獨立觀察鏈表工作情況极祸。
昨天我調(diào)試的代碼中,圖像顯示不正常天吓,我要測試一下函數(shù)是否正常遍歷了鏈表中的所有元素贿肩。
于是我在appear函數(shù)遍歷鏈表的循環(huán)體中,設(shè)置了標記變量龄寞,并設(shè)置了相應(yīng)的輸出語句汰规,代碼如下:
運行結(jié)果如下:
在初始化的時候,代碼初始化了十五個對象物邑,這里函數(shù)共輸出了15次溜哮,考慮到邊界處理等因素帶來的輸出錯誤,數(shù)量基本沒有錯誤色解,說明鏈表被正常遍歷茂嗓。
同樣的方式我還用來測試了移動所有電腦控制的魚的fishmove函數(shù):
fishmove函數(shù)運行的次數(shù)和appear函數(shù)輸出的次數(shù)一樣,說明在遍歷鏈表的操作上科阎,二者沒有錯誤述吸。
注意點
因為我們在命令行輸出內(nèi)容是為了方便調(diào)試,因此我們要能通過輸出的內(nèi)容判斷出該內(nèi)容來自于哪個一函數(shù)的哪一部分。因此有一些注意點:
一定要換行蝌矛。一條信息占一行才能讓你更清晰的看清楚每一條信息內(nèi)容道批。
要標記函數(shù)名。比如inappear, in fishmove等入撒,不要自己猜測該變量來自于哪一個函數(shù)隆豹。
測試循環(huán)的時候要注意輸出循環(huán)數(shù)量。
如果輸出變量茅逮,要記得寫上變量名璃赡,比如ptinf(“data=%d\n”,%d),方便觀察献雅。
判斷某一個條件是否執(zhí)行
這一點也比較常見碉考。當你寫了一個按鍵操作的代碼段,但你的操作并沒有對程序產(chǎn)生影響惩琉,這是你如何判斷該操作是否被程序捕捉豆励?這個時候用命令行也可以解決。
在昨天的程序中瞒渠,我看到了一個我沒用過的獲取按鍵消息的函數(shù)GetAsyncKeyState(如下圖所示):
此時,我無法通過按鍵控制魚的移動技扼。雖說我可以很輕松的查到函數(shù)的功能伍玖,但我無法確定函數(shù)的觸發(fā)方式在游戲中能否實現(xiàn)。
這時剿吻,可以通過命令行來判斷按鍵是否能正常操作:
如果按下W的時候窍箍,命令行可以輸出in getMOVE GetAsyncKeyStateW,則說明該條件語句可以執(zhí)行丽旅,問題不出在這里椰棘。運行一下之后結(jié)果如下:
如上圖所示,命令行窗口輸出了該語句榄笙,說明按下W的時候邪狞,條件語句正常執(zhí)行,問題是在別的地方茅撞。
測試變量是否被修改
同樣的道理帆卓,我們需要測試某些變量的時候,我們也可以直接在命令行輸出米丘。比如測試坐標是否被修改剑令。
當我們遍歷修改鏈表中的元素的時候,我們只需要測試其中某一個元素的坐標是否被修改即可判斷程序是否正常執(zhí)行拄查。因此我們可以只在計數(shù)到某個固定的值的時候吁津,輸出該元素的坐標值,如下圖所示:
運行的時候如下圖所示:
從284到302堕扶,說明坐標值被修改碍脏。
總之癣疟,善用命令行讓你方便地獨立調(diào)試課設(shè)中某一部分的內(nèi)容,對某些中間變量等進行輸出潮酒,可以讓你快速找到程序中的問題睛挚。
使用ifdef切換調(diào)試模式
使用ifdef/endif語句,可以讓編譯器在編譯程序的時候急黎,根據(jù)是否定義某一段宏扎狱,來決定是否編譯該段語句。
上圖中勃教,當宏定義中使用#defineDEBUGMODE定義了DEBUGMODE之后淤击,其中的語句可以運行;如果取消對DEBUGMODE的定義故源,比如將宏定義注釋掉:
可以發(fā)現(xiàn)上面的語句變?yōu)榛疑?/p>
此時再編譯污抬,該段語句不會執(zhí)行。
合理使用該功能绳军,比如將所有的測試語句全部至于ifdef/endif之中印机,有兩個好處:
可以通過是否注釋掉定義的宏(如DEBUGMODE)來關(guān)閉/開啟所有的測試語句;
當你的測試語句非常多的時候门驾,可以通過設(shè)置多個不同的宏定義射赛,開啟/關(guān)閉不同的測試程序,避免過多的測試語句造成干擾奶是。比如定義MOVEMODE,JUDGEMODE等楣责,根據(jù)不同的情況開啟不同的測試語句。
關(guān)于圖片讀取
這一點和測試無關(guān)聂沙。
easyX在讀取圖片文件的時候會消耗大量的時間秆麸,當你的程序運行非常緩慢的時候,很可能就是因為你進行了重復文件讀取操作及汉。
當你在函數(shù)中使用了讀取函數(shù)功能時沮趣,可以使用下面的方式使該函數(shù)在程序運行的時候無論調(diào)用多少次,都只進行一次文件讀取操作豁生,提高程序的執(zhí)行效率:
將儲存圖片的指針(FISH)設(shè)置為static靜態(tài)變量兔毒,并設(shè)置一個靜態(tài)標記變量(loadFlag),讀取一次文件之后甸箱,修改標記變量育叁,下一次便不再進行讀取操作。
關(guān)于調(diào)試的內(nèi)容就到這里
希望這些內(nèi)容可以幫助做課設(shè)的同學們更快更好地完成自己的課設(shè)
如果有需要補充或者有其他疑問的可以后臺聯(lián)系我或者在下面留言
之前我還寫過一篇輸出透明圖片的解決方案芍殖,歡迎點擊查看: