用VS.Net編寫擴展存儲過程(三,完)
2024-07-21 02:07:32
供稿:網(wǎng)友
昨天忙著寫這個,沒看奧運會,剛知道老郭和小吳又讓外國人郁悶了一把。不知道奧委會是不是又要對跳水改變規(guī)則哪?
在上一節(jié),我們把含有兩車站的所有火車id和路線信息分別讀入了int *trainid和char** ppcstations,完成了最后一次讀入數(shù)據(jù)的過程,下面就要處理這些數(shù)據(jù)以獲得結果……就要結束了,前途是光明的,道路是平坦的……風是背后吹來的……有mm在身邊陪著的……暈,忘了告訴各位兄弟,小弟現(xiàn)在不吃西紅柿了,改吃雞蛋,請多多關照積極配合,謝謝~~~
第三步,尋找最短的路線
顯然,首先要對路線信息的字符串做分詞處理,知道了從一站到下一站需要多長時間,才可能計算最短路線。本文中將用.net類庫中提供的正則式類來分割這些字符串……當然用普通方法也完全可以處理。
要使用正則式類,就要用到托管代碼,我還是只講應用,不講原理。對托管代碼工作機制感興趣的朋友,請參閱msdn中的托管編程部分。
先選擇xstrainquery項目的屬性,將“配置屬性”下“常規(guī)”中的“使用托管擴展”改為“是”,隨后在proc.cpp中加入如下預編譯頭:
#using
#using
using namespace system;
using namespace system::text::regularexpressions;
對于char*字符串,必須轉化為托展字符串類型,即system::string*指針,才能用正則式類處理。我是用這樣的方式把char*轉化為system::string*:
system::string *newstr = system::text::encoding::unicode->getstring(system::text::encoding::unicode->getbytes(oldstr));
現(xiàn)在就到了這一步的重頭戲——正則式分詞。不知道大家有沒有掌握.net的正則式,如果象我一樣是菜鳥,還是讓msdn隨時待命吧~
{
// 把起點和終點站由pbyte轉化為system::string*
system::string *strstart = system::text::encoding::unicode->getstring(system::text::encoding::unicode->getbytes((pchar)pbstart));
system::string *strend = system::text::encoding::unicode->getstring(system::text::encoding::unicode->getbytes((pchar)pbend));
// 定義正則式模式
// 用兩個//,是因為|在正則式中有特定含義,必須在|前加上/轉義,而//代表了/
regex *r = new regex(s"( ?://|(.+?),(.+?)小時)+//|");
// 定義循環(huán)中將用到的變量
int ioldtime = int_max;
int nfastest = 0;
// 萬事俱備,開始處理ppcstations指針數(shù)組
for (int i=0; i {
// 用r來匹配ppcstations[i]
match *m = r->match(ppcstations[i]);
// 所有站點的匹配組
system::text::regularexpressions::group *gstation = m->groups->get_item(1);
// 所有時間的匹配組,與站點匹配組按順序一一對應
system::text::regularexpressions::group *gtime = m->groups->get_item(2);
// 定義ppcstations[i]所代表的路線所需時間
int inewtime = 0;
// 定義是否已經(jīng)找到起點站的bool變量
bool bstartfound = false;
// j從0到gstation中捕獲的個數(shù),即總共捕獲到多少個站點
for (int j=0; jcaptures->count; ++j)
{
if ( !bstartfound )
{
// 如果尚未找到起點,則判斷當前捕獲站點是否為起點
if ( gstation->captures->get_item(i)->value->trim()->equals(strstart->trim()) )
bstartfound = true;
// 即使找到了起點,也直接continue,因為起點站對應的時間對運算無意義
continue;
}
else
{
// 已經(jīng)找到起點站,開始累加路線時間
inewtime += int32::parse(gtime->captures->get_item(i)->value->trim());
// 看當前捕獲站點是否為終點,若是則退出for循環(huán)
if ( gstation->captures->get_item(i)->value->trim()->equals(strend->trim()) )
break;
}
}
// for循環(huán)已退出,比較inewtime和ioldtime,并記錄較小的路線索引
if ( inewtime < ioldtime )
{
ioldtime = inewtime;
nfastest = i;
}
}
// 現(xiàn)在,nfastest代表了最短路線的索引,ioldtime則代表所需的最短時間
}
終于找到了最短路線和最短時間,工作完成了!運行運行…………期待…………期待…………焦慮…………疑惑…………不對啊,怎么沒有結果?
哦!忘了最后一步,還需要把結果傳出……
第四步,也是最后一步,傳出結果
結果定義為這樣的形式——'車id,需時',生成結果就很簡單了:
{
// 定義一個255字節(jié)的數(shù)組,較容易處理
char pcresult[255];
sprintf(pcresult, "火車id為%d,需時%d小時", pitrainid[nfastest], ioldtime);
}
怎樣把pcresult送出去?這就用到了srv.h中定義的srv_paramsetoutput方法,其格式如下:
int srv_paramsetoutput (
srv_proc * srvproc,
int n,
byte * pbdata,
ulong cblen,
bool fnull );
其中,n代表是第幾個參數(shù),pbdata代表參數(shù)數(shù)據(jù),cblen代表參數(shù)長度(字節(jié)),
若fnull設置為true,則此出參將被強制設為null.
大家肯定注意到,pbdata是一個byte指針,于是我們還要把pcresult轉換為byte*,這個很簡單,直接顯式轉換即可。
設置出參的代碼如下:
{
// 得到結果的實際長度(字節(jié)數(shù))
int nresultlen = strlen(pcresult);
// 傳出參數(shù)
srv_paramsetoutput(srvproc, 3, (pbyte)pcresult, nresultlen, false);
// 所有的工作完成后,發(fā)出senddone信息
srv_senddone(psrvproc, (srv_done_count | srv_done_more), 0, 1);
}
現(xiàn)在工作似乎已經(jīng)完成了,快拿去運行吧,嘿嘿,多運行幾次……再運行幾次……陶醉一下……又運行幾次……然后……重啟計算機,繼續(xù)往下看。
上面的代碼中,我們沒有完全釋放所分配的資源,所以每次運行都會造成內存泄漏。我們必須在代碼的最后加上釋放內存空間的語句,比如ppcstations, pitrainid等。
大功告成,第一個問題得到了解決。
本來還想寫第二個問題的,可第二個問題和第一個問題的區(qū)別只在于第三步,即如何計算最短路線的算法上,這個,我相信我現(xiàn)在用的方法一定不是最好的,就不拿出來獻丑了。
原來寫篇文章是這么累的……