• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 89  文章 - 118  trackbacks - 0
            <2010年9月>
            2930311234
            567891011
            12131415161718
            19202122232425
            262728293012
            3456789

            留言簿(16)

            隨筆分類(56)

            隨筆檔案(89)

            文章分類

            推薦博客

            搜索

            •  

            最新隨筆

            最新評論

            閱讀排行榜

                 摘要: IOCP(I/O Completion Port,I/O完成端口)是性能最好的一種I/O模型。它是應用程序使用線程池處理異步I/O請求的一種機制。在處理多個并發的異步I/O請求時,以往的模型都是在接收請求是創建一個線程來應答請求。這樣就有很多的線程并行地運行在系統中。而這些線程都是可運行的,Windows內核花費大量的時間在進行線程的上下文切換,并沒有多少時間花在線程運行上。再加上創建新線程的開銷...  閱讀全文
            posted @ 2011-07-13 16:19 胡滿超 閱讀(817) | 評論 (0)編輯 收藏

            轉自:http://yinkai210.blog.163.com/blog/static/287483452009050256466/

            大家在啟動服務器時,有時正常啟動有時又啟動不了是怎么回事呢??那為什么關掉迅雷等軟件就又好了呢??現在就來給大家講解一下,

            如何查詢端口被占用的程序 - kakis - Kakis

            這些端口如果被其他程序占用就不能正常啟動,比如有時啟動時會提示WEB啟動失敗,其實就是80端口被占用了,而迅雷等下載軟件恰恰就是占用了80端口,關掉就行了。但有時迅雷等都沒有開也啟動不了,那就是別的東西占用了,那怎么辦呢?我來叫你查看端口并關掉的方法。
            1.在開始--運行   里面輸入cmd點回車,會出現運行窗口。
            2.在提示符后輸入netstat -ano回車,找到tcp 80端口對應的pid,比如1484.
            3.ctrl+alt+del打開任務管理器,選進程,這里有很多正在運行的程序怎么找?別急點上面的   查看--選擇列--在PID(進程標示符)前面打鉤。好了,下面的進程前面都有了PID號碼。這時上一步找到的PID就有用了,找到1484,比如PEER.EXE什么的,結束進程吧。這時再開服務器,看WEB可以啟動了!

            如上面的不清楚還有簡明的:

            假如我們需要確定誰占用了我們的80端口

            1、Windows平臺
            在windows命令行窗口下執行:
            C:\>netstat -aon|findstr "80"
            TCP     127.0.0.1:80         0.0.0.0:0               LISTENING       2448
            看到了嗎,端口被進程號為2448的進程占用,繼續執行下面命令:
            C:\>tasklist|findstr "2448"
            thread.exe                     2016 Console                 0     16,064 K
            很清楚吧,thread占用了你的端口,Kill it
            如果第二步查不到,那就開任務管理器,看哪個進程是2448,然后殺之即可。

            如果需要查看其他端口。把 80 改掉即可

            posted @ 2011-05-03 11:20 胡滿超 閱讀(1030) | 評論 (7)編輯 收藏

            本文轉自:http://blog.csdn.net/miromelo/archive/2010/04/04/5450460.aspx

            筆者現在了解一種比較簡單的方法,即:

            修改CXXAPP中的InitInstance函數,將原來的模態對話框改為非模態對話框,及修改

            view plaincopy to clipboardprint?
            INT_PTR nResponse = dlg.DoModal(); 
            INT_PTR nResponse = dlg.DoModal();

             

            view plaincopy to clipboardprint?

            dlg.Create(CModalHideDlg::IDD); //創建為非模態對話框   
            dlg.ShowWindow(SW_HIDE);        //創建完畢后,可以設置對話框的顯示方式,正常為“SW_SHOW”,   
                                                                //在此,我們使用“SW_HIDE”將對話框隱藏,但是在進程列表中仍然可以看到   
            dlg.RunModalLoop();                  //消息循環 
            dlg.Create(CModalHideDlg::IDD); //創建為非模態對話框
            dlg.ShowWindow(SW_HIDE);        //創建完畢后,可以設置對話框的顯示方式,正常為“SW_SHOW”,
                                                              //在此,我們使用“SW_HIDE”將對話框隱藏,但是在進程列表中仍然可以看到
             dlg.RunModalLoop();                  //消息循環

             

             

            還有其他一些朋友的方法:

             

            有很多應用程序要求一起動就隱藏起來,這些程序多作為后臺程序運行,希望不影響其他窗口,

            往往只在托盤區顯示一個圖標。這些程序通常都是對話框程序,而對話框在初始化的過程上與SDI

            、MDI的初始化是不同的,對話框只需要DoModule或者是CreateDialog等等對話框函數調用一次便

            可,SDI、MDI則要好幾步才行。這樣看來,對話框在使用方法上面是隱藏了不少細節的,其中就

            沒有SDI、MDI所要求的ShowWindow(nCmdShow)這一步。因此對話框要想一運行就隱藏,并不是很

            直接的。有一些方法可以做到這一點,下面我們就來看看幾種方案。

            1.定時器
            最直觀,又是最無奈的一個方法就是使用定時器。既然我們在對話框開始顯示之前不能用ShowWin

            dow(SW_HIDE)將其隱藏,那就給一個時間讓它顯示,完了我們在隱藏它。

            方法:

            1.在OnInitDialog()函數里設置定時器:(WINDOWS API里面響應消息WM_INITDIALOG)

            SetTimer(1, 1, NULL);

            2.添加處理WM_TIMER的消息處理函數OnTimer,添加代碼:

            if(nIDEvent == 1)

            {

            DeleteTimer(1);

            ShowWindow(SW_HIDE);

            }

            這種方法的缺點是顯而易見的,使用定時器,使得程序的穩定性似乎打一個折扣;窗口是要先顯

            示出來的,那么效果就是窗口閃了一下消失。

            2.改變對話框顯示狀況
            在對話框初始化時改變其顯示屬性可以讓它隱藏起來。方法是調用SetWindowPlacement函數:


            BOOL CDialogExDlg::OnInitDialog()

            {

            CDialog::OnInitDialog();

            //DO something


            WINDOWPLACEMENT wp;

            wp.length=sizeof(WINDOWPLACEMENT);

            wp.flags=WPF_RESTORETOMAXIMIZED;

            wp.showCmd=SW_HIDE;

            SetWindowPlacement(&wp);

            return TRUE;

            }

             

            在需要顯示時(通常是響應熱鍵或者托盤圖標的鼠標消息):


            WINDOWPLACEMENT wp;

            wp.length=sizeof(WINDOWPLACEMENT);

            wp.flags=WPF_RESTORETOMAXIMIZED;

            wp.showCmd=SW_SHOW;

            SetWindowPlacement(&wp);


            這樣的效果很不理想:窗口顯示在屏幕的左上角,并且是只有標題欄,要正常顯示,還需加上如

            下代碼:

            定義一個成員變量CRect rect;

            在OnInitDialog()里面:

            GetWindowRect(&rect);

            在需要顯示的地方:

            SetWindowPos(&wndNoTopMost, wndRc.left, wndRc.top, wndRc.right, wndRc.bottom,

            SWP_SHOWWINDOW);

            CenterWindow();

            即使這樣,效果還是很差。

            這種方法還有一個弊端是當程序開始運行并且隱藏起來后,原來激活的窗口變成了非激活狀態了

            ,而當對話框顯示出來后,對話框自身也是非激活狀態的。


            3.不繪制窗口
            當對話框顯示時將要響應消息WM_PAINT繪制客戶區,相應消息WM_NCPAINT繪制窗口邊框。我們在

            窗口第一次自繪自身時隱藏窗口,可以收到比較良好的效果。由于窗口是先畫窗口邊框,所以我

            們僅需處理WM_NCPAINT即可。代碼如下:

            添加WM_NCPAINT處理函數。

            void CMyDialog::OnNcPaint()

            {

            static int i = 2;

            if(i > 0)

            {

            i --;

            ShowWindow(SW_HIDE);

            }

            else

            CDialog::OnNcPaint();

            }

            這里有個問題:為什么要定義靜態變量i而且設其值為2呢?

            我們只要窗口隱藏第一次,所以定義這個變量可以判斷是否時首次顯示窗口。當程序開始運行時

            ,系統發送(SendMessage)WM_NCPAINT消息,此時程序的窗口邊框應該被顯示,但是此時我們沒

            有作任何顯示的操作,而是將窗口隱藏,ShowWindow(SW_HIDE)將把窗口的WS_VISIBLE屬性去掉,

            繼續執行,程序將檢查WS_VISIBLE屬性,如果沒有則顯示窗口,所以又發送了一個WM_NCPAINT消

            息。所以我們要處理兩次WM_NCPAINT消息。

            在需要窗口顯示時,調用ShowWindow(SW_SHOW)即可。

            程序執行的結果是,原來處于激活狀態的窗口可能會閃動兩下,然后仍然處于激活狀態。這種處

            理方式比上面的方式要優越得多。


            4.將對話框作為子窗口
            這種方法是采用SDI框架,主窗口始終隱藏,對話框作為主窗口的成員變量,在CMainFrame::OnCr

            eate()里面加入下代碼:

            if(!dlg.Create(IDD_MYDIALOG, this))

            {

            return –1;

            }

            dlg.ShowWindow(SW_HIDE);

            在要顯示對話框的地方用dlg.ShowWindow(SW_SHOW);即可。注意,主窗口一定要隱藏,否則對話

            框可能會閃現一下。

            隱藏狀態欄窗口
            上面介紹了幾種檢查對話框的方法,大家如果試過的話可能已經注意到系統狀態欄里在程序啟動

            時會有程序的圖標閃過,在隱藏對話框的時候這個也是要隱藏的,方法很簡單:

            在OnInitDialog()函數里面加上ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);即可。在

            要顯示窗口的地方加上代碼ModifyStyleEx(WS_EX_TOOLWINDOW, WS_EX_APPWINDOW);即將窗口的擴

            展樣式改回來。


            以上是我的一點經驗總結,有錯誤或不完善的地方還望大家提出指正。歡迎大家與我聯系。


            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/miromelo/archive/2010/04/04/5450460.aspx

            posted @ 2010-12-03 16:02 胡滿超 閱讀(10803) | 評論 (6)編輯 收藏
            You will only need to do four things:

            1) At the top of your cpp file (under the #includes) add: #define WM_UPDATEFIELDS WM_APP + 1

            2) Go to your Message Map section and add: ON_MESSAGE(WM_UPDATEFIELDS, UpdateDisplay)

            3) Add a member function: LRESULT UpdateDisplay(WPARAM wParam, LPARAM lParam)

            4) Add the following to the function:
            UpdateData((BOOL)wParam);
            return 0;

            This should now allow you to pass UpdateData TRUE or FALSE from within a thread.

            +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            reference from: codeproject
            http://www.codeproject.com/KB/cpp/avoidupdatedata.aspx
            posted @ 2010-09-28 13:29 胡滿超 閱讀(526) | 評論 (0)編輯 收藏
            #include <stdlib.h> #include <iostream>
            using namespace std;

            class tgh
            {
            public:
                tgh():i(
            3){}
               
            const int a() const {return 5;}
               
            int a(){return i;}
            protected:
               
            int i;
            private:
            };

            void main()
            {
               
            const tgh v;
                tgh s;
               
            const int i=s.a();//調用的是int a()
               
            int const j=s.a();//調用的是int a()
                printf(
            "%d,%d",j,i);
               
            const int k = v.a();//調用的是const int a() 
                cout
            <<k<<endl;
                system(
            "pause");
            }

            結果是3,35

            轉自:http://www.shnenglu.com/tgh621/archive/2008/04/15/47100.aspx?opt=admin
            posted @ 2010-08-09 17:16 胡滿超 閱讀(199) | 評論 (0)編輯 收藏

            轉載  [轉]寫好代碼的10個秘密 收藏

            作者:飛哥 (百度)

            先給大家看一段據說是史上最強的程序:
            e100 33 f6 bf 0 20 b5 10 f3 a5 8c c8 5 0 2 50 68 13 1 cb e 1f be a1 1 bf 0 1
            e11b 6 57 b8 11 1 bb 21 13 89 7 4b 4b 48 79 f9 ad 86 e0 8b c8 bd ff ff e8 20
            e134 0 3d 0 1 74 1a 7f 3 aa eb f3 2d ff 0 50 e8 f 0 5a f7 d8 8b d8 26 8a 1 aa
            e14f 4a 75 f9 eb de cb 57 bb 21 13 8b c1 40 f7 27 f7 f5 8b fb ba 11 1 4f 4f 4a
            e168 39 5 7f f9 52 8b c5 f7 25 f7 37 2b c8 95 f7 65 2 f7 37 95 2b e8 fe e fe
            e181 10 79 6 c6 6 fe 10 7 46 d0 14 d1 d1 d1 e5 79 ec 5a b8 11 1 ff 7 4b 4b 48
            e19b 3b d0 75 f7 5f c3 83 f7 83 a6 5d 59 82 cd b2 8 42 46 9 57 a9 c5 ca aa 1b
            .............................................................................


            這段程序是1997年世界程序設計大賽的一等獎作品的部分代碼(完整的代碼下載,把代碼復制粘貼到cmd的debug命令中,回車看到效果)。這個程序運行后將是一個3D的且伴隨著音樂的動畫。震撼吧!
            是不是從事軟件開發的人員都希望成為這樣的武林高手呢?然而真要是用這樣的高手來設計、編寫我們的產品代碼,恐怕某一天,我們什么都不用干了,只能人手一本機器代碼,一句一句進行翻譯了;那么對于軟件產品開發而言,如何寫好代碼呢?一流的軟件產品的代碼具備哪些特征呢?

            一流代碼的特征

            1、穩定可靠(Robustness)
            代碼寫出來以后,一定要能夠運行得非常好,非常穩定可靠。在現 今的IT行業,軟件產品都是是24*7,即要保證系統一天24小時,一星期7天中都可以無間斷的正常運行。比如我們百度的搜索引擎系統,比如我們的通信系 統,等等。到了產品開發后期,大部分的成本都將投入到產品穩定性的提高。

            2、可維護且簡潔(Maintainable and Simple Code)
            在寫代碼時,首先要考 慮的是:寫出來的代碼不但要自己可以讀懂,而且我們的同事、測試工程師都可能要修改這些代碼,對其進行增減。如果代碼很復雜,不容易讀懂,如程序中的遞歸 一大堆、程序不知何時或從何地跳出,則會使程序的可維護性和簡潔性降低。所以必要的注釋、統一的編程規范等都是非常重要的。

            3、高效(Fast)
            在軟件行業中效率是非常重要的,比如搜索引擎。有些軟件的搜索效率就不高,搜索過 程特別緩慢,讓人難以接受。當然這里面有一個帶寬的問題,但是程序效率不高也是一個重要的原因。而實際上程序的效率提高,有時候很簡單,并沒有什么神秘之 處,如使用數組索引時候,可以用指針方式而不使用數組下標;數組的空間定義應該定義為2的N次冪等等。

            4、簡短(Small)
            這方面大家的感受可能不是很深,但是我的感受是很深的。配置過PSTN程控交換 機、路由器、VoIP網關設備的人都知道,這些設備的軟件都是從PC機通過網口或串口下載到這些設備的Flash上(類似PC機的BIOS)再通過設備上 的CPU啟動。如果程序寫的很羅嗦,隨著特性不斷增加,程序規模將變大的巨大,Flash空間告急、內存告急、下載升級變的不可忍受,等等,帶來的就是成 本不斷增加,利潤不斷下降。

            5、共享性(Reusable)
            如果做大型產品開發,程序的共享性也是非常重要的。我們產品有那么多開 發人員,如果每一個人都自己定義字符串、鏈表等數據結構,那么開發效率就會降低,我們的產品恐怕到今天也不能出臺。我所說的“共享”不是指將別人的代碼復 制到自己的代碼中,而是指直接調用別人的代碼,拿來即可用。這一方面可以減少代碼的冗余性,另一方面可以增強代碼的可維護性。如果別人的代碼里有Bug, 只需修改他的代碼,而調用此代碼的程序不用進行任何修改就可以達到同步。這同時要求我們在設計的時候,如何考慮系統的內聚和耦合的問題。

            6、可測試性(Testable)
            我們的產品開發里,除了軟件開發人員,還有一部分工程師負責軟件測 試。軟件測試人員會將開發代碼拿來,一行一行地運行,看程序運行是否有錯。如果軟件開發人員的代碼不可測試,那測試工程師就沒有辦法進行工作。因此可測試 性在大型軟件開發里是很重要的一點。可測試性有時候與可維護性是遙相呼應的,一個具有好的可測試性和可維護性的代碼,測試人員可以根據開發提供的維護手 冊、debug信息手冊等就可以判斷出程序出錯在哪個模塊。

            7、可移植性(Portable)
            可移植性是指程序寫出來以后,不僅在windows 2000里可以運行,在NT/9X下可以運行,而且在Linux甚至Macintosh等系統下都可以運行。所有這些特性都是一流代碼所具備的特性。但是 其中有些特性是會有沖突的。比如高效性,程序寫的效率很高,就可能變得很復雜,犧牲的就是簡潔。好的代碼要在這些特性中取得平衡。

            寫好代碼的10個秘密

            1、百家之長歸我所有(Follow Basic Coding Style)
            其實寫代碼的方式有很多,每個人都有自己的風格,但是眾多的風格中總有一些共性的、基本的寫代碼的風格,如為程序寫注釋、代碼對齊,等等。是不是編程規范?對就是編程規范。

            2、取個好名字(Use Naming Conventions)
            取個好的函數名、變量名,最好按照一定的規則起名。還是編程規范。

            3、凌波微步,未必摔跤(Evil goto's?Maybe Not...)
            這里我用“凌波微步”來形容goto語句。通常,goto語句使程序跳來跳去,不容易讀,而且不能優化,但是在某種情況下,goto語句反而可以增強程序的可讀性。Just go ahead,not go back。

            4、先發制人,后發制于人(Practic Defensive Coding)
            Defensive Coding指一些可能會出錯的情況,如變量的初始化等,要考慮到出現錯誤情況下的處理策略。測試時要多運行幾個線程。有些程序在一個線城下運行是正常 的,但是在多個線程并行運行時就會出現問題;而有些程序在一個CPU下運行幾個線程是正常的,但是在多個CPU下運行時就會出現問題,因為單CPU運行線 程只是狹義的并行,多CPU一起運行程序,才是真正的并行運算。

            5、見招拆招,滴水不漏(Handle The Error Cases:They Will Occur!)
            這里的Error Case(錯誤情況),是指那些不易重視的錯誤。如果不對Error Case進行處理,程序在多數情況下不會出錯,但是一旦出現異常,程序就會崩潰。 6、熟習劍法刀術,所向無敵(Learn Win32 API Seriously)
            用“劍法刀術”來形容一些API是因為它們都是經過了很多優秀開發人員的不斷開發、測試,其效率很高,而且簡潔易懂,希望大家能掌握它,熟悉它,使用它。是不是象我們的ULIB。

            7、雙手互搏,無堅不摧(Test,but don't stop there)
            這里的測試不是指別人來測試你的代碼,而是指自己去測試。因為你是寫代碼的原作者,對代碼的了解最深,別人不可能比你更了解,所以你自己在測試時,可以很好地去測試哪些邊界條件,以及一些意向不到的情況。

            8、活用斷言(Use,don't abuse,assertions)
            斷言(assertion)是個很好的調試工具和方法,希望大家能多用斷言,但是并不是所有的情況下都可以用到斷言。有些情況使用斷言反而不合適。

            9、草木皆兵,不可大意(Avoid Assumptions)
            是指在寫代碼時,要小心一些輸入的情況,比如輸入文件、TCP的sockets、函數的參數等等,不要認為使用我們的API的用戶都知道什么是正確的、什么是錯的,也就是說一定要考慮到對外接口的出錯處理問題。

            10、最高境界、無招勝有招(Stop writing so much code)
            意思就是說盡量避免寫太多的代碼,寫的越多,出錯的機會也越多。最好能重用別人開放的接口函數或直接調用別人的api。

            posted @ 2010-08-05 17:53 胡滿超 閱讀(411) | 評論 (0)編輯 收藏
            轉自:http://blog.csdn.net/pennyliang/archive/2010/07/07/5717498.aspx

            中文分詞方法有很多,其中基于詞典的分詞方法有:
            •     基于模式匹配的方法:(速度快)

                                 正向最大匹配、逆向最大匹配法、雙向匹配法

            •      基于規則的方法:(索引壓縮的效果最好)
                                 最少分詞法
                 基于統計的分詞方法有:
            •      統計語言模型分詞(2-gram,3-gram)
            •      串頻統計的漢語自動分詞

                  除了這些基本的方法,為了獲得最佳的效果,也可以引入動態規劃的方法獲得最優解。

                 設句子P = W0W1W2?Wn , 其中Wi (0≤i≤n) 為句子P中的第i 個漢字。Si(0≤i≤n+1)為句子的第i個間隙(切分位置)

                 那么一個句子P理論上有多少種分詞法呢?

                 分詞分法總數的通項:Fn)表示一個有n個單詞的句子包含的全部不同的分詞方法。

                 F(n)=1+ F(n-1)+F(n-2)+F(n-3)+F(n-4)+..F(1)

                F(1)=1

                F(2)=2

                F(3)=4

                F(4)=8

                 …

                F(n)=2F(n-1)

                則F(n)=2n-1

                如果將詞頻看做是距離,則求解最佳切分方法等價于在2n-1的解空間中尋找1種最佳的切分方法使得路徑最短。為此我們舉個例子:

                早起先刷牙

             

                

             

            圖中紅圈為切分點,切分點之間的連線表示確定的一種分詞

            圖中給出了三種分法,分別是[][][][][][早起][][刷牙][][起先][刷牙]

            假定我們有這樣一個字頻和詞頻表,分別如下

             

                          400

            早起            100

                          500

            起先            150

                          500

                          300

            刷牙            100

                          500

            則以上三種切分法的代價分別為

            [][][][][]400+500+500+300+500 = 2200

            [早起][][刷牙]100+500+100 = 700

            [][起先][刷牙]400+150+100 =750 (此處應為650)

            因此選用第2種切分法。

            動態規劃的偽代碼大致為:

            Segment(S,low,high,cost,last)

            {

                    Mincost = MAX;

                    If(high-low<=1)

                    {

                    mincost = Costof(costL(low,high-low)); //其中L(start,length)的含義表示從start開始從P中取length長度的文本,Costof為該段文本的字頻,或者詞頻,如果不存在則為無窮大;如果cost數組中已經計算過,則不重復計算,直接取值返回。

                    cost[low][high] = mincost;

                    Return mincost

                   }

                    fori = low+1 to high

                   {

                       a = Segment(S,low,i,cost,last);//為了簡單這里做了精簡,事實上如果a返回的是無窮大,則后面不用繼續計算,直接跳出,因為這種情況下無論如何也不可能是最優解,可以直接剪枝。

                       b = Segment(S,i,high,cost,last);

                       if(a+b<Mincost)

                       {

                           Mincost = a + b;

                           Cost[low][high]=Mincost;

                           Last[low][high] = i;//Last記錄最佳切分點

                       }

                    }

                    ExtractSegmentPos(Last,low,high);//該函數是將切分點一一展開。

            }

             

             

             

             ExtractSegmentPos(Last,low,high)

            {

                 SegPos=MAX;

                 if(high-low>1)

                 {

                      If(Last[low][high]>0)

                      {

                          SegPos =  Last[low][high]

                          output(SegPos);
                      }

                      else

                      { 

                           return;

                      }

                 }

                 ExtractSegmentPos(Last,low, SegPos);

                 ExtractSegmentPos(Last, SegPos,high);

            }


            參考文獻

            [1] 孫 曉, 黃德根  基于動態規劃的最小代價路徑漢語自動分詞   [J]小型微型計算機系統  第27 卷第3 期 2006 年3 月

            其他推薦閱讀

            http://www.leadbbs.com/MINI/default.asp?230-2682632-0-0-0-0-0-a-.htm

            posted @ 2010-07-30 09:06 胡滿超 閱讀(759) | 評論 (0)編輯 收藏
            我做OO時間不長,提出自己發現的一些問題,僅供各位朋友參考。

            1,功能過于復雜,被微軟牽著走

            OO的前身是StarOffice,我想它的初衷肯定不是想做成微軟這么復雜的辦公軟件,但現在的發展方向是微軟能做到的,OO也希望可以做到;

            2,架構、代碼、數據處理算法,質量整體不高

            如果從一般意義來講OO的架構與代碼也算不錯,但如果用市場一線軟件的標準去度量OO,它顯然還有相當大的改進空間;

            3、商業價值至今不夠顯現

            幾個參與OO的開發的廠商目的不一樣,所專注的側重點也不一樣,但有兩點是一致的,一是不能讓微軟落太遠,二是誰也沒在OO身上掙到錢;

            4、投入太少,被微軟越落越遠

            與微軟相比的財力與人力,各廠商的投入尚不是一個層次。當然,商業上的成功與研發的投入是正相關的一個循環體,大家各有各個考慮,是情理之中的事情。

            5、二次開發功能太弱,接口尚不能十分穩定

            二次開發是讓一個系統起飛的翅膀,良好的二次開發功能會創造出軟件編寫都想像不出來的應用,但開源的OO恰恰做的不好;
            我一直覺得這個OO趕超微軟唯一的切入點,可以說只要你能想到的應用,理論上微軟的Office都可以實現,但大家不相信它,應該它不開源,不安全,還可能有版權問題,但OO在這方面顯然有一定的心理優勢;

            6、在主流用戶平臺,用戶群較少

            這主指windows,當然在linux上OO還是很牛的,反正也沒有別的選擇。但從主流用戶平臺上搶不到客戶,估計每一個做OO的人都夠郁悶的了,包括我。

            7、未能找到未來的發展方向

            OO陣營大家不能找到一個共同而明確的方向,形成合力,使有限力量顯得有些分散,為OO的開展帶來很多的不可預見性。

            簡單的談了一下自己的看法,如果說的不對,還請見諒小弟。

            posted @ 2010-03-05 10:29 胡滿超 閱讀(371) | 評論 (0)編輯 收藏
            什么樣的程序員稱得上優秀,根據我所看到,有如下體會:

            1、不愿意將就的人

            程序設計工作是一項地地道道的腦力勞動,把工作做得很好和做的很差往往只在工作中的一個小小的細節,我發現我身邊優秀的程序員都不太喜歡將就,始終把自己的計算機和自己的開發環境調整到最佳狀態,原來帶我的老員工甚至會自己寫一些小工具,來提高工作效率。

            2、不喜歡蠻干

            腦力勞動與體力勞動不同,很多時候很難通過簡單的量的積累達到目的,尤其是處理一些難題的時候。一味的強調蠻干,加班幾乎天生與高手無緣。沒有思路的時候,換個環境,也許答案就在明天上班的路上想起。

            3、愿意思考、專注改進

            程序員與其他勞動者相似,熟練了以后都會形成慣性思維,會不自覺的用自己習慣的方式解決問題,但問題的形式與本質總會變化,只有不斷的改進才能使工作效率不斷提高。而把腦力勞動變成體力勞動的現象在實際工作中比比皆是。

            4、良好的基礎和不斷的學習

            良好的基礎與不斷的學習是天生的一對孿生兄弟,因為基礎好所以學的快,因為學得快,所以基本功好。良好學習習慣不是不停的簡單追蹤新技術,一方面是了解新技術,另一方面需要不斷的彌補思維盲區,學習可以有很多種狀態,有一種是聞一而知一,技也,有一種是聞一而知三,術也,有一種是聞一而知十,道也。

            5、直接切入問題的能力

            在解決一個問題的時候,有些人總是能夠直接切入問題核心,而有些人總是喜歡關注邊緣問題。直入主題是一種核心能力,需要思考,實踐,改進,積累,提高,周而復使,螺旋上升。另外我覺得這與思維方式與知識面關系很大,多涉獵一些領域沒有壞處。

            ***英語***:呵呵,對,還是英語,流利的聽說讀寫。
            posted @ 2009-12-16 17:39 胡滿超 閱讀(255) | 評論 (0)編輯 收藏
            1、    查找一個字符串中最長的重復子串;
            2、    查找一個字符串中重復最多的子串;

            查找“重復子串最長的”和“子串出現次數最多的”解決方案相似:
            首先、生成一個指針數組,數組的成員依次指向字符串中每一個的字符地址,如

            String: “banana”
            那么指針數組分別代表字串:

            banana
            anana
            nana
            ana
            na
            a

            之后按指針數組指向的字符串值,對數組進行排序,排序結果如下:

            a[0]: a
            a[1]: ana
            a[2]: anana
            a[3]: banana
            a[4]: na
            a[5]: nana

            有個這個數組,統計“重復的最長子串”和“重復次數最多子串”就非常容易了。
            “重復的最長子串”代碼如下:

             1 int comlen(char *p, char *q)
             2 {
             3     i = 0
             4     while *&& (*p++ == *q++)
             5         i++
             6     return i
             7 }
             8 
             9 maxlen = -1
            10 for i = [0, n)
            11     for j = (i, n)
            12         if (thislen = comlen(&c[i], &c[j])) > maxlen
            13             maxlen = thislen
            14             maxi = i maxj = j 

            這個方法出自《編程珠璣》。


            posted @ 2009-12-16 14:07 胡滿超 閱讀(546) | 評論 (1)編輯 收藏
            介紹的一些字符串處理的問題在日常編程中比較常見,但是在大學讀書的時候幾乎一個都沒有涉及,最近學習了一下在這里介紹給大家,僅供參考。

            這些算法與內容包括:

            1、    查找一個短串在一個長串中位置;
            2、    查找一個字符串中最長的重復子串;
            3、    查找一個字符串中重復最多的子串;
            4、    兩個字符串最長的公共子串(連續);
            5、    兩個字符串最長的公共子序列(不連續);
            6、    介紹一種強大的數據結構,Suffix tree.

            這里有一個PPT:
            http://www.shnenglu.com/Files/humanchao/StringAlg.zip

            -------------------------------------------------

            查找一個短串在一個長串中位置

            這個問題傳統的解法時間復雜度為O(m*n),m、n為兩個串的長度。有一個Sunday算法,可以最大限度的優化這個比較過程,原理如下:

            1、建立一個hash table,依次把search各個字符值作為table索引,為table相應的位置一個值(表示字符存在),如果出現重復,后面的位置會覆蓋前面的位置。
            例:我們要在"WHICH-FINALLY-HALTS.—AT-THAT-POINT"(簡稱string)查找" AT-THAT "(簡稱pat),剛開始時,把pat與string對齊,查看串string中與串pat 相對應的字符(F),在pat的位置,這個查找的過程時間復雜度通過hash table的下標索引為 O(1): 



            2、如果發現沒有,說明字符F之前已經無法與pat匹配,直接跳到position(F)+stringlength(pat)


             
            3、發現”-”在pat位置3,于是重新定位對齊兩串為:

             
            4、倒序(從最后一個向前)比較兩串,發現無法匹配,繼續跳轉->查找->定位
            因為上面已經有一個T匹配成功,這次要從HALTS的S來查找,于是定位為:



            5、上圖無法匹配,從”--AT-“中A后的”-”繼續查找,重復上過程,最終匹配如圖:
             

            這個算法關鍵點:
            1、建立為pat建立hash表,以提高查找字符的速度;
            2、對齊跳轉,快速的后移比較,使比較次數減少。

            具體的代碼實現可以參考鏈接:

            http://blog.csdn.net/unicode1985/archive/2007/05/30/1631038.aspx


            posted @ 2009-11-25 17:20 胡滿超 閱讀(3131) | 評論 (0)編輯 收藏
            關于:找到兩個字符串最長的連續公共子串里無論是表達還是算法本身都是存在一定問題的,查找公共子串的問題在很多資料上都有明確的定義,通過動態規劃來解決,算法復雜度為O(M*N),在此向大家深表歉意。


            正確的做法在wikipedia上有所描述,請大家參考:
            http://en.wikipedia.org/wiki/Longest_common_substring_problem

            http://hellobmw.com/archives/dynamic-programming-longest-common-substring.html
            posted @ 2009-11-25 17:09 胡滿超 閱讀(179) | 評論 (0)編輯 收藏

            將字符串里詞順序倒置,如"Times New Roman"變為"Roman New Times"。以空格為分隔符。

            解決方案為:先將整個字串倒置,然后依次把倒置后串中的每一個單詞倒置。

            這個問題解答的思路很簡單,但是要考慮到很多種的情況,比如字符串的頭、尾有多余的空格怎么辦,如果字符串中只有空格,還有字符串中間可能會有兩個以上并列的空格。

            程序如下:

             1 void ReverseStr(char *pStr, int len)
             2 {
             3     assert(pStr);
             4     
             5     char ch;
             6     for (int i = 0; i < len/2 ; i++)
             7     {
             8         ch = pStr[i];
             9         pStr[i] = pStr[len-1-i];
            10         pStr[len-1-i] = ch;
            11     }
            12 }
            13 
            14 void ReverseStrWord(char *pStr, int len)
            15 {
            16     assert(pStr);
            17 
            18     if (len <= 1)
            19         return;
            20 
            21     // 倒置整個字符串
            22     ReverseStr(pStr, len);
            23 
            24     // 處理頭多余的空格
            25     int i = 0;
            26     if (pStr[0== ' ')            while (pStr[i] == ' ' && i < len)        i++;
            27 
            28     // 整個串都是空格
            29     if (i == len)
            30         return;
            31 
            32     // 處理尾多余的空格
            33     if (pStr[len - 1== ' ')    while (pStr[len - 1== ' ' && len - 1 > 0)    len--;
            34 
            35     for (int start = i; i < len; i++)
            36     {
            37         // 最后的end要+1
            38         if (i == len-1)
            39         {
            40             ReverseStr(pStr+start, i-start+1);
            41             break;
            42         }
            43 
            44         // 倒置一個單詞
            45         if (pStr[i] == ' ')
            46         {
            47             ReverseStr(pStr+start, i-start);
            48             start = i+1;
            49             // 處理內部并列的空格
            50             if (pStr[start] == ' ')
            51             {
            52                 while(pStr[start] == ' ') {i++;start++;};
            53             }
            54         }
            55     }
            56 }
            57 

             

            說實話,如果是突然面對這樣一個問題,要在一張紙上寫下比較完整的程序是不大可能。能邊調試邊寫程序有的時候也是一件幸事。
            中秋節要到了,我要換工作了,告別已經工作兩年多熟悉的環境,感覺這兩年沒有太大的進步,奮斗吧,趁著自己還年輕!

            posted @ 2008-09-12 20:42 胡滿超 閱讀(2224) | 評論 (5)編輯 收藏
            問題找出整數1~N范圍和為M的所有集合,M<=N且M>1,集合里的數不允許重復。

            解答:這個問題用遞歸解決最簡單,代碼如下:

             1 #define MAX_NUM 20        //要足夠大
             2 int log[MAX_NUM];        //記錄和數
             3 int index = 0;            //log[]數組的當前指針
             4 
             5 void calc(int start, int n)
             6 {
             7     if (n == 0)  
             8     {
             9         for(int j = 0; j < index; j++)
            10             printf("%d ", log[j]);
            11         printf("\n");
            12     }
            13     else
            14     {
            15         for(int i = start; i<=n; i++)
            16         {
            17             log[index++= i;    
            18             calc(i + 1, n - i);
            19         }
            20     }
            21 
            22     index--;
            23 }

            如果允許重復只需要將上面第18條代碼改為:

            calc(i, n - i);

            即可。

            擴展問題在數組{5,1,7,9,2,10,11,4,13,14}中找到和為28的所有集合,集合中不允許有重復的數。

            解答:第一步要先對數組排序,然后按照上去的思路,對程序略做一些改動。
            代碼如下:

             1 #define MAX_NUM 20        //要足夠大
             2 int log[MAX_NUM];        //記錄和數
             3 int index = 0;            //log[]數組的當前指針
             4 
             5 void calc__(int *nArr     //數組, 
             6             int start    //數組起始元素下標, 
             7             int nArrLen    //數組長度, 
             8             int sum)
             9 {
            10     if (sum == 0)  
            11     {
            12         for(int j = 0; j < index; j++)
            13             printf("%d ", log[j]);
            14         printf("\n");
            15     }
            16     else
            17     {
            18         for(int i = start; i < nArrLen; i++)
            19         {
            20             log[index++= nArr[i];    
            21             calc__(nArr, i+1, nArrLen, sum - nArr[i]);
            22         }
            23     }
            24     
            25     index--;
            26 }

            這個問題的解答思路是相當簡單的,但如何把程序寫的細致、簡捷是除了解答思路以外的另一個關鍵。就像迷宮最短路徑的那個問題,言語描述很簡單,但把實現的程序寫好確要花一些時間。

            posted @ 2008-08-29 16:13 胡滿超 閱讀(1049) | 評論 (0)編輯 收藏
            已知前序和中序:

            struct NODE 
            {
                NODE 
            *pLeft;
                NODE 
            *pRight;
                
            char chValue;
            };

            int  CharInStrFirstPos(char ch, char *str, int nLen)
            {
                
            char *pOrgStr = str;
                
            while (nLen > 0 && ch != *str)
                {
                    str
            ++;
                    nLen
            --;
                }
                
                
            return (nLen > 0? (str - pOrgStr) : -1;
            }

            void ReBuild_PreIn(char *pPreOrder, char *pInOrder, int nTreeLen, NODE **pRoot)
            {
                
            if (pPreOrder == NULL || pInOrder == NULL)
                {
                    
            return;
                }

                NODE 
            *pTemp = new NODE;
                pTemp
            ->chValue = *pPreOrder;
                pTemp
            ->pLeft = NULL;
                pTemp
            ->pRight = NULL;

                
            if (*pRoot == NULL)
                {
                    
            *pRoot = pTemp;
                }

                
            if (nTreeLen == 1)
                {
                    
            return;
                }

                
            int nLeftLen = CharInStrFirstPos(*pPreOrder, pInOrder, nTreeLen);
                assert(nLeftLen 
            != -1);
                
            int nRightLen = nTreeLen - nLeftLen -1;

                
            if (nLeftLen > 0)
                {
                    ReBuild_PreIn(pPreOrder 
            + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft));
                }

                
            if (nRightLen > 0)
                {
                    ReBuild_PreIn(pPreOrder 
            + nLeftLen + 1, pInOrder + nLeftLen + 1,
                        nRightLen, 
            &((*pRoot)->pRight));
                }
            }

            已知后序和中序:


            void ReBuild_AftIn(char *pAftOrder, char *pInOrder, int nTreeLen, NODE **pRoot)
            {
                
            if (pAftOrder == NULL || pInOrder == NULL)
                {
                    
            return;
                }
                
                NODE 
            *pTemp = new NODE;
                pTemp
            ->chValue = *pAftOrder;
                pTemp
            ->pLeft   = NULL;
                pTemp
            ->pRight  = NULL;
                
                
            if (*pRoot == NULL)
                {
                    
            *pRoot = pTemp;
                }
                
                
            if (nTreeLen == 1)
                {
                    
            return;
                }
                
                
            int nLeftLen = CharInStrFirstPos(*pAftOrder, pInOrder, nTreeLen);
                assert(nLeftLen 
            != -1);
                
            int nRightLen = nTreeLen - nLeftLen -1;
                
                
            if (nLeftLen > 0)
                {
                    ReBuild_AftIn(pAftOrder 
            + nRightLen + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft));
                }
                
                
            if (nRightLen > 0)
                {
                    ReBuild_AftIn(pAftOrder 
            + 1, pInOrder + nLeftLen + 1,
                        nRightLen, 
            &((*pRoot)->pRight));
                }
            }

            我上傳了一個工VC的工程,有興趣的朋友點此下載。代碼參考于《編程之美》。
            posted @ 2008-08-27 17:51 胡滿超 閱讀(921) | 評論 (0)編輯 收藏
            我們先看一個函數:函數的功能完成1~10的加法。

            int Add1to10(int a, int b)
            {
               
            return a +b;
            }

            但是一般我們還需要加上幾條代碼:

            int Add1to10(int a, int b)
            {
                assert(a 
            >= 1 && a <= 10);
                assert(b 
            >= 1 && b < =10);

                
            if ( a < 1 || a > 10 || b < 1 || b > 10)
                    
            return -1;

                
            return a +b;
            }

            加上上面幾條代碼的作用是檢查函數的輸入參數,當參數不正確的時候不光要在返回值上得到體現,而且會觸發assert斷言,提醒我們參數有誤。

            斷言式編程體現一個編程的思想,在我們的程序執行偏離預想的路線時給出提醒。當程序執行偏離預想的路線時一般會出現兩種可能:即斷言以上的程序沒有理解下面程序的調用條件、或斷言以下的程序需要接受更為寬泛輸入條件。以下分別討論修改方法:

            1、如果函數的輸入參數是我們編程的一個疏漏,我們認為根本就不應該出現或產生這樣的值,那我們應該修改調用函數處的代碼,避免非預想的值出現。

            2、如果無法避免出現或者產生一個非法輸入值,那我們要么在函數調用處加入判斷,產生符合條件的值時調用函數,不符合參數條件else處理;要么修改函數,使函數可以接受更為寬泛輸入條件,并調整斷言內容和參數判斷邏輯。

            斷言不僅可以出現在函數的參數檢查的場合,也可以出現在其他的上下文調用的場合。而且它還會隨著程序的開發進程逐漸的增加、刪除和調整。它可以驗證程序是按照我們預想的思路在執行,當出現意外時及時的給出提醒,提醒我們修正程序或者自己的思路。

            posted @ 2008-08-19 10:00 胡滿超 閱讀(806) | 評論 (0)編輯 收藏
            void QuickSort(int* pData,int left,int right)
            {
                
            int i = left, j = right;
                
            int middle = pData[(left+right)/2];        // midlle value
                int iTemp;
                
            do
                {    
                    
            while (pData[i] < middle && i < right)            i++;
                    
            while (pData[j] > middle && j > left)            j--;
                    
            if (i < j)                            // swap
                    {
                        iTemp    
            = pData[i];
                        pData[i] 
            = pData[j];
                        pData[j] 
            = iTemp;
                        i
            ++;            j--;
                    } 
                    
            else if (i == j)
                    {
                        i
            ++;            j--;
                    }
                } 
            while (i < j);

                
            if (left  < j)        QuickSort(pData,left,j);
                
            if (right > i)        QuickSort(pData,i,right);
            }

            沒的說,理解不了就是背也得把這段代碼背下來。
            posted @ 2008-08-18 17:02 胡滿超 閱讀(770) | 評論 (0)編輯 收藏
            學習數據結構和算法的好東西,非常形象,制作水平比較高,向制作者致敬!里面包含以下算法的過程演示:

            B樹的刪除
            B樹的生長過程
            三元組表的轉置
            中序線索化二叉樹
            串的順序存儲
            二分查找
            二叉排序樹的刪除
            二叉排序樹的生成
            二叉樹的建立
            克魯斯卡爾算法構造最小生成樹
            冒泡排序
            分塊查找
            單鏈表結點的刪除
            單鏈表結點的插入
            圖的深度優先遍歷
            基數排序
            堆排序
            頭插法建單鏈表
            尋找中序線索化二叉樹指定結點的前驅
            尋找中序線索化二叉樹指定結點的后繼
            尾插法建表
            希兒排序
            開放定址法建立散列表
            循環隊列操作演示
            快速排序
            拉鏈法創建散列表
            拓撲排序
            數據結構和算法Flash動畫演示.rar
            最短路徑
            樸素串匹配算法過程示意
            構造哈夫曼樹的算法模擬
            構造哈夫曼樹過程
            棧與遞歸
            ...更多


            點擊下載






            posted @ 2008-07-24 16:19 胡滿超 閱讀(3289) | 評論 (1)編輯 收藏
            如果BAT不帶參數,腳本內容如下:

            SetOutPath '$INSTDIR'
            ExecWait '$INSTDIR\A.bat'

            如果BAT需要參數時,要把帶參數的命令寫入另外一個新的BAT中,執行新BAT:

            B.bat內容:
            CALL A.bat install

            NSIS 腳本:
            SetOutPath '$INSTDIR'
            ExecWait '$INSTDIR\B.bat'
            posted @ 2008-07-23 16:47 胡滿超 閱讀(6053) | 評論 (3)編輯 收藏

            #import   
            "scrrun.dll"   raw_interfaces_only

            // 參數格式:"c:\" 或 "c:\test"
            ULONGLONG GetPathUseSpace(
            const char *szPath)
            {
                ASSERT(szPath 
            != NULL);

                
            int nLen = strlen(szPath);
                
            if (nLen == 0)
                    
            return 0;

                ULONGLONG result 
            = 0;

                
            if (nLen == 3)      // c:\
                {
                    ULARGE_INTEGER nFreeBytesAvailable;
                    ULARGE_INTEGER nTotalNumberOfBytes;
                    ULARGE_INTEGER nTotalNumberOfFreeBytes;
                    
            //
                    if (GetDiskFreeSpaceEx(szPath,
                          
            &nFreeBytesAvailable,
                          
            &nTotalNumberOfBytes,
                          
            &nTotalNumberOfFreeBytes))
                    {
                        result 
            = nTotalNumberOfBytes.QuadPart - nFreeBytesAvailable.QuadPart;
                    }
                }
                
            else
                {
                    CoInitialize(NULL);  
                    {  
                        
            try  
                        {  
                            Scripting::IFileSystem3Ptr   fs;  
                            fs.CreateInstance(__uuidof(Scripting::FileSystemObject)); 
                            
                            Scripting::IFolderPtr   folder;  
                            fs
            ->GetFolder(_bstr_t(szPath),&folder);
                            
                            _variant_t vsize;
                            folder
            ->get_Size(&vsize);
                            result 
            = (double)vsize;
                        }  
                        
            catch(_com_error &e)  
                        {  
                            result 
            = -1;
                        }  
                    }  

                    CoUninitialize();   
                }

                
            return result;
            }


            VC取得目錄的大小可以用COM方式,但是在某些操作系統上使用COM方式取根目錄大小(即某一個盤已用空間)會出現問題,可以用GetDiskFreeSpaceEx,上面是我寫了一個小函數。
            posted @ 2008-07-02 16:33 胡滿超 閱讀(2915) | 評論 (13)編輯 收藏
            僅列出標題
            共5頁: 1 2 3 4 5 
            一本久久a久久精品亚洲| 久久婷婷五月综合色奶水99啪| 综合网日日天干夜夜久久| 久久久精品日本一区二区三区| 国内精品久久久久影院免费| 久久精品国产亚洲av影院| 精品熟女少妇AV免费久久| 无码乱码观看精品久久| 青青草国产97免久久费观看| 久久人人超碰精品CAOPOREN| 国内精品伊人久久久久影院对白| 久久综合丝袜日本网| 国产精品久久久久9999高清| 99久久精品午夜一区二区| 97久久精品午夜一区二区| 97久久精品国产精品青草| 一本久久a久久精品综合夜夜| 久久91亚洲人成电影网站| 26uuu久久五月天| 久久国产精品视频| 亚洲?V乱码久久精品蜜桃| 亚洲美日韩Av中文字幕无码久久久妻妇| 久久久久九国产精品| 久久这里只精品99re66| 久久偷看各类wc女厕嘘嘘| 久久青青草原国产精品免费| 精品无码久久久久久久久久| 久久久午夜精品福利内容| 亚洲国产精品无码久久一区二区| 久久久无码精品亚洲日韩按摩| 99久久精品毛片免费播放| 精品无码人妻久久久久久| 久久精品国产AV一区二区三区| 国产午夜福利精品久久2021| 久久97久久97精品免视看| 中文字幕乱码久久午夜| 91久久福利国产成人精品| 久久国产欧美日韩精品免费| 久久精品99久久香蕉国产色戒| 国产精品99久久不卡| 狠狠综合久久AV一区二区三区|