龔燕峰
摘 要 利用C++編程技術(shù)采用堆棧數(shù)據(jù)結(jié)構(gòu)將從遠程數(shù)據(jù)庫獲取到的原始航標數(shù)據(jù)進行解析處理,使得符合整個航標位置準確性自動校核系統(tǒng)的數(shù)據(jù)格式要求,并進一步將解析出來的航標數(shù)據(jù)存入指定的數(shù)據(jù)庫,以備后期對航標位置復(fù)核時使用。航標數(shù)據(jù)的解析工作是整個航標位置自動校核系統(tǒng)運行的開端,也是系統(tǒng)得以運行的基礎(chǔ)。
【關(guān)鍵詞】C++ 堆棧 數(shù)據(jù)解析 數(shù)據(jù)庫
本文在長江重慶航道局航標位置自動校核系統(tǒng)項目的基礎(chǔ)上進行論述的,其中原始航標數(shù)據(jù)的解析是整個航標位置自動校核系統(tǒng)項目的開端和進行項目其它階段的基礎(chǔ),同時也是整個系統(tǒng)項目的核心環(huán)節(jié),如何高效率的將從航標遙測遙控系統(tǒng)獲得的原始航標數(shù)據(jù)解析成系統(tǒng)項目中能直接使用的數(shù)據(jù)非常重要。
本項目軟件系統(tǒng)通過SoapClient遠程訪問航標遙測遙控系統(tǒng),并通過航標遙測遙控管理軟件系統(tǒng)間接地從后臺數(shù)據(jù)庫獲取航標的數(shù)據(jù)。
1 原始航標數(shù)據(jù)的解析
上述獲取到的有關(guān)航標的數(shù)據(jù)暫時保存在一個文檔中,初步獲取的保存在這個文檔中的數(shù)據(jù)還不能直接在項目的軟件中使用,因此必須對這些數(shù)據(jù)做進一步解析處理,在航標數(shù)據(jù)的解析工作中我們采用了順序棧。
順序棧的類定義中各成員變量和成員函數(shù)的含義:
m_pBuffer:為指向棧元素的數(shù)組的頭指針;
m_pTop和m_pBottom:分別指向棧頂和棧底;
IsFull()成員函數(shù):用來判斷棧中元素是否已經(jīng)滿了;
GetSize()成員函數(shù):用來獲取棧中元素的個數(shù),隨著新元素的進棧和棧頂元素的出棧,在需要的時候需重新調(diào)用GetSize()成員函數(shù);
push(T element)成員函數(shù):用來將新元素寫入棧;
pop(T& element)成員函數(shù):用來從棧中取出元素。
圖1是整個航標數(shù)據(jù)解析算法的流程圖,pChar為指向存有初始航標數(shù)據(jù)的拷貝字符數(shù)組的指針。
1.1 讀出原數(shù)據(jù)并獲得其副本
利用文件操作函數(shù)fopen打開之前保存了航標數(shù)據(jù)的文本文檔,將航標數(shù)據(jù)讀出到自定義的字符數(shù)組中,其中,全局函數(shù)GetModuleFileName(),用于獲取工程當前目錄;在使用那個保存有航標數(shù)據(jù)的字符數(shù)組前,先利用memcpy()函數(shù)獲得原數(shù)據(jù)的一個拷貝,以保證原數(shù)據(jù)的最終不被修改的原則,進行數(shù)據(jù)拷貝前還需先將自定義的拷貝數(shù)組的內(nèi)存進行清零操作,在此,用到了memset()函數(shù),為了保證拷貝數(shù)據(jù)的完整性,使用了多線程中的線程同步機制,具體采用了事件對象的線程同步方法,使得原數(shù)據(jù)在拷貝的過程中不被打斷。
1.2 解析數(shù)據(jù)
準備工作做好后,開始進入數(shù)據(jù)的核心解析工作了,本文主要利用一個大的while循環(huán)和堆棧來進行,循環(huán)條件是判斷一個指向待解析數(shù)據(jù)的字符指針是否為空,只要不為空,則循環(huán)繼續(xù)。在整個while循環(huán)里再利用一個if...else...選擇結(jié)構(gòu)具體判斷指針所指向的字符為哪種類型,在else語句塊中,若所指向的字符不為“,”或“}”,則將字符數(shù)據(jù)存入棧中,直至遇到“,”或“}”字符,這意味著某個數(shù)據(jù)項或數(shù)據(jù)元素的結(jié)束,此時, if語句的執(zhí)行主體要完成數(shù)據(jù)項和數(shù)據(jù)元素的讀取和儲存工作,每執(zhí)行完這樣一個if語句主體便意味著一個航標的特性數(shù)據(jù)項或一整個航標的數(shù)據(jù)元素解析工作完成了。由于每個航標數(shù)據(jù)元素包括很多子元素,如:航標的經(jīng)度、緯度等,因此,在if語句主體中,通過其他的結(jié)構(gòu)具體完成子元素的解析工作,主要采用了幾個while和for循環(huán)結(jié)構(gòu),同時,由于子元素又包含兩個數(shù)據(jù)項,將它們分別命名為數(shù)據(jù)項名和數(shù)據(jù)項值,只有分別完成了數(shù)據(jù)項名和數(shù)據(jù)項值的解析才算完成了一個子元素的解析工作。
數(shù)據(jù)項值的解析:
經(jīng)過最初的while大循環(huán),代表數(shù)據(jù)項值的原始數(shù)據(jù)已被保存在棧中,為了解析它,需通過另一個while循環(huán)逐個將其從棧中取出進行判斷,只要棧非空,取出的字符非“"”并且非“:”,則將此字符存入一個字符數(shù)組中,循環(huán)結(jié)束后便完成了一個數(shù)據(jù)項值的解析。
數(shù)據(jù)項名的解析:
與數(shù)據(jù)項值相同,經(jīng)過最初的while大循環(huán),代表數(shù)據(jù)項名的原始數(shù)據(jù)已被保存在棧中,此時,通過另外一個while循環(huán)繼續(xù)從棧中取出數(shù)據(jù)進行判斷,只要棧非空并且取出的字符非“"”,則將此字符存入一個字符數(shù)組中,循環(huán)結(jié)束后便完成了一個數(shù)據(jù)項名的解析。
對數(shù)據(jù)項的解析工作完成后,即可將一個子元素保存在一個BEACON類型的結(jié)構(gòu)中,此過程中采用了另一個if...else...結(jié)構(gòu),以strcmp()函數(shù)的返回值作為判斷條件,將與指定的數(shù)據(jù)項名匹配的數(shù)據(jù)項值依次保存在BEACON結(jié)構(gòu)對應(yīng)的成員中。完成某個數(shù)據(jù)項值的保存后繼續(xù)利用其它if語句判斷指向原數(shù)據(jù)的字符指針的內(nèi)容是否為“}”(因為“}”意味著原數(shù)據(jù)中一個航標數(shù)據(jù)元素的結(jié)束),若為“}”,則將此時的BEACON結(jié)構(gòu)保存的數(shù)據(jù)寫入到數(shù)據(jù)庫中,至此,航標數(shù)據(jù)的一個解析循環(huán)工作結(jié)束。
2 總結(jié)
本文詳述了在航標位置自動校核系統(tǒng)中對航標數(shù)據(jù)的解析算法的運用。首先利用Soap Client 客戶端通過航標遙測遙控軟件管理系統(tǒng)遠程獲取航道局航標數(shù)據(jù)庫的航標數(shù)據(jù),并使用堆棧數(shù)據(jù)結(jié)構(gòu)和C++編程技術(shù)將獲取到的原始航標數(shù)據(jù)進行解析,使其成為符合本系統(tǒng)規(guī)范的數(shù)據(jù)格式要求,并最后實現(xiàn)了將其存儲到本地數(shù)據(jù)庫以備用。為整個航標位置自動校核系統(tǒng)的成功運行提供了必要的數(shù)據(jù)基礎(chǔ)。
參考文獻
[1]David J.Kruglinski著,潘愛民,王國印譯.Visual C++ 技術(shù)內(nèi)幕[M].北京:清華大學(xué)出版社,2002.
[2]長江航道局,長江干線航標配布研究[Z]. 武漢:長江航道局,2004.
作者單位
重慶交通大學(xué)交通運輸學(xué)院 重慶市 400074