• <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>
            面對(duì)現(xiàn)實(shí),超越自己
            逆水行舟,不進(jìn)則退
            posts - 269,comments - 32,trackbacks - 0
            @import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
            PNG2BMP.EXE 可以將png圖片轉(zhuǎn)換成bmp圖片。

            下載地址

            示例:PNG2BMP.EXE -X C:\\1.PNG -O 1.bmp -D c:\\

            命令參數(shù)如下:

            png2bmp, a PNG-to-BMP converter - version 1.62 (Sep 42005)
               Copyright (C) 1999-2005 MIYASAKA Masaru
               Compiled with libpng 1.2.8 and zlib 1.2.3.

            Usage: png2bmp.exe [-switches] inputfile(s) 
               or:  | png2bmp.exe [-switches] | 

            List of input files may use wildcards (* and ?)
            Output filename is same as input filename, but extension .bmp

            Switches (case-insensitive) :
               -A       Preserve alpha channel (save in 32bit ARGB BMP format)
               -B       Preserve alpha channel (save in 32bit Bitfield BMP format)
               -R       Convert transparent color to alpha channel (use with -A or -B)
               -O name  Specify name for output file
               -D dir   Output files into dir
               -E       Delete input files after successful conversion
               -T       Set the timestamp of input file on output file
               -Q       Quiet mode
               -L       Log errors to .\P2BERROR.LOG file
               -X       Disable conversion through standard input/output
            posted @ 2012-11-19 17:24 王海光 閱讀(1811) | 評(píng)論 (0)編輯 收藏
                 摘要: 以下實(shí)現(xiàn)適用于24位BMP圖片: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  1 //單擊一個(gè)Button,保存位圖  2 void CDlgDlg::OnButton1() ...  閱讀全文
            posted @ 2012-11-19 17:19 王海光 閱讀(7131) | 評(píng)論 (2)編輯 收藏

            1.介紹

             

                gSOAP編譯工具提供了一個(gè)SOAP/XML 關(guān)于C/C++ 語(yǔ)言的實(shí)現(xiàn),從而讓C/C++語(yǔ)言開發(fā)web服務(wù)或客戶端程序的工作變得輕松了很多。絕大多數(shù)的C++web服務(wù)工具包提供一組API函數(shù)類庫(kù)來處理特定的SOAP數(shù)據(jù)結(jié)構(gòu),這樣就使得用戶必須改變程序結(jié)構(gòu)來適應(yīng)相關(guān)的類庫(kù)。與之相反,gSOAP利用編譯器技術(shù)提供了一組透明化的SOAP API,并將與開發(fā)無(wú)關(guān)的SOAP實(shí)現(xiàn)細(xì)節(jié)相關(guān)的內(nèi)容對(duì)用戶隱藏起來。gSOAP的編譯器能夠自動(dòng)的將用戶定義的本地化的C或C++數(shù)據(jù)類型轉(zhuǎn)變?yōu)榉蟈ML語(yǔ)法的數(shù)據(jù)結(jié)構(gòu),反之亦然。這樣,只用一組簡(jiǎn)單的API就將用戶從SOAP細(xì)節(jié)實(shí)現(xiàn)工作中解脫了出來,可以專注與應(yīng)用程序邏輯的實(shí)現(xiàn)工作了。gSOAP編譯器可以集成C/C++和Fortran代碼(通過一個(gè)Fortran到C的接口),嵌入式系統(tǒng),其他SOAP程序提供的實(shí)時(shí)軟件的資源和信息;可以跨越多個(gè)操作系統(tǒng),語(yǔ)言環(huán)境以及在防火墻后的不同組織。

             

                gSOAP使編寫web服務(wù)的工作最小化了。gSOAP編譯器生成SOAP的代碼來序列化或反序列化C/C++的數(shù)據(jù)結(jié)構(gòu)。gSOAP包含一個(gè)WSDL生成器,用它來為你的web服務(wù)生成web服務(wù)的解釋。gSOAP的解釋器及導(dǎo)入器可以使用戶不需要分析web服務(wù)的細(xì)節(jié)就可以實(shí)現(xiàn)一個(gè)客戶端或服務(wù)端程序。下面是gSOAP的一些特點(diǎn):

             

            l        gSOAP編譯器可以根據(jù)用戶定義的C和C++數(shù)據(jù)結(jié)構(gòu)自動(dòng)生成符合SOAP的實(shí)例化代碼。

            l        gSOAP支持WSDL 1.1, SOAP 1.1, SOAP 1.2, SOAP RPC 編碼方式以及 literal/document 方式.

            l        gSOAP是少數(shù)完全支持SOAP1.1 RPC編碼功能的工具包,包括多維數(shù)組及動(dòng)態(tài)類型。比如,一個(gè)包含一個(gè)基類參數(shù)的遠(yuǎn)程方法可以接收客戶端傳來的子類實(shí)例。子類實(shí)例通過動(dòng)態(tài)綁定技術(shù)來保持一致性。

            l        gSOAP 支持 MIME (SwA) 和 DIME 附件包。

            l        gSOAP是唯一支持DIME附件傳輸?shù)墓ぞ甙?。它允許你在保證XML可用性的同時(shí)能夠以最快的方式(流方式)傳遞近乎無(wú)大小限制的二進(jìn)制數(shù)據(jù)。

            l        gSOAP 支持 SOAP-over-UDP。

            l        gSOAP 支持 IPv4 and IPv6.

            l        gSOAP 支持 Zlib deflate and gzip compression (for HTTP, TCP/IP, and XML file storage)。

            l        gSOAP 支持 SSL (HTTPS)。

            l        gSOAP 支持 HTTP/1.0, HTTP/1.1 保持連接, 分塊傳輸及基本驗(yàn)證。

            l        gSOAP 支持 SOAP 單向消息。

            l        gSOAP 包含一個(gè) WSDL 生成器,便于web服務(wù)的發(fā)布。

            l        gSOAP 包含一個(gè)WSDL解析器 (將WSDL轉(zhuǎn)換為gSOAP頭文件),可以自動(dòng)化用戶客戶端及服務(wù)端的開發(fā)。

            l        生成可以單獨(dú)運(yùn)行的web服務(wù)及客戶端程序。

            l        因?yàn)橹恍枰苌賰?nèi)存空間,所以可以運(yùn)行在類似Palm OS, Symbian, Pocket PC的小型設(shè)備中。

            l        適用于以C或C++開發(fā)的web服務(wù)中。

            l        跨平臺(tái):Windows, Unix, Linux, Mac OS X, Pocket PC, Palm OS, Symbian等。

            l        支持序列化程序中的本地化C/C++數(shù)據(jù)結(jié)構(gòu)。

            l        可以使用輸入和輸出緩沖區(qū)來提高效率,但是不用完全消息緩沖來確定HTTP消息的長(zhǎng)度。取而代之的是一個(gè)三相序列化方法。這樣,像64位編碼的圖像就可以在小內(nèi)存設(shè)備(如PDA)中以DIME附件或其他方式傳輸。

            l        支持C++單繼承,動(dòng)態(tài)綁定,重載,指針結(jié)構(gòu)(列表、樹、圖、循環(huán)圖,定長(zhǎng)數(shù)組,動(dòng)態(tài)數(shù)組,枚舉,64位2進(jìn)制編碼及16進(jìn)制編碼)。

            l        不需要重寫現(xiàn)有的C/C++應(yīng)用。但是,不能用unions,指針和空指針來作為遠(yuǎn)程方法調(diào)用參數(shù)的數(shù)據(jù)結(jié)構(gòu)中元素。

            l        三相編組:1)分析指針,引用,循環(huán)數(shù)據(jù)結(jié)構(gòu);2)確定HTTP消息長(zhǎng)度;3)將數(shù)據(jù)序列化位SOAP1.1編碼方式或用戶定義的數(shù)據(jù)編碼方式。

            l        雙相編組:1)SOAP解釋及編碼;2)分解“forward”指針(例如:分解SOAP中的href屬性)。

            l        完整可定制的SOAP錯(cuò)誤處理機(jī)制。

            l        可定制的SOAP消息頭處理機(jī)制,可以用來保持狀態(tài)信息

            gsoap通常帶有兩個(gè)工具: wsdl2h 和 soapcpp2。 wsdl2h主要是用來生成頭文件的,而soapcpp2主要是利用wsdl2h生成的頭文件來生成C文件或C++文件。 

            以下是README.txt中示例:

            Example translation of WSDL to code in two steps:
            $ wsdl2h -s -o calc.h http://www.cs.fsu.edu/~engelen/calc.wsdl
            $ soapcpp2 calc.h

            Windows下命令行運(yùn)行:

                   wsdl2h.exe -o TestServices.h http://192.168.20.242/ClientUpdateWebService.asmx?WSDL
                   soapcpp2 TestServices.h 


            出現(xiàn)如下錯(cuò)誤:Critical error: #import: Cannot open file "stlvector.h" for reading.你需要在gsoap\import下把這個(gè)文件拷貝過來。

             wsdl2h
            **  The gSOAP WSDL/Schema processor for C and C++, wsdl2h release 2.8.5
            **  Copyright (C) 2000-2011 Robert van Engelen, Genivia Inc.
            **  All Rights Reserved. This product is provided "as is", without any warranty.

            **  The wsdl2h tool is released under one of the following two licenses:
            **  GPL or the commercial license by Genivia Inc. Use option -l for details.

            Usage: wsdl2h [-a] [-c] [-d] [-e] [-f] [-g] [-h] [-I path] [-i] [-j] [-k] [-l] [
            -m] [-n name] [-N name] [-p|-P] [-q name] [-r proxyhost[:port[:uid:pwd]]] [-s] [
            -t typemapfile] [-u] [-v] [-w] [-W] [-x] [-y] [-z#] [-_] [-o outfile.h] infile.w
            sdl infile.xsd http://www 

            -a      generate indexed struct names for local elements with anonymous types
            -c      generate C source code
            -d      use DOM to populate xs:any, xs:anyType, and xs:anyAttribute
            -e      don't qualify enum names
            -f      generate flat C++ class hierarchy
            -g      generate global top-level element declarations
            -h      display help info
            -i      don't import (advanced option)
            -Ipath  use path to find files
            -j      don't generate SOAP_ENV__Header and SOAP_ENV__Detail definitions
            -k      don't generate SOAP_ENV__Header mustUnderstand qualifiers
            -l      display license information
            -m      use xsd.h module to import primitive types
            -nname  use name as the base namespace prefix instead of 'ns'
            -Nname  use name as the base namespace prefix for service namespaces
            -ofile  output to file
            -p      create polymorphic types with C++ inheritance from base xsd__anyType
            -P      don't create polymorphic types with C++ inheritance from xsd__anyType
            -qname  use name for the C++ namespace of all declarations
            -rhost[:port[:uid:pwd]]
                    connect via proxy host, port, and proxy credentials
            -s      don't generate STL code (no std::string and no std::vector)
            -tfile  use type map file instead of the default file typemap.dat
            -u      don't generate unions
            -v      verbose output
            -w      always wrap response parameters in a response struct (<=1.1.4 behavior)
            -W      suppress warnings
            -x      don't generate _XML any/anyAttribute extensibility elements
            -y      generate typedef synonyms for structs and enums
            -z1     compatibility with 2.7.6e: generate pointer-based arrays
            -z2     compatibility with 2.7.15: qualify element/attribute referenced members
            -_      don't generate _USCORE (replace with UNICODE _x005f)
            infile.wsdl infile.xsd http://www list of input sources (if none: use stdin) 
            soapcpp2
            Usage: soapcpp2 [-1|-2] [-C|-S] [-T] [-L] [-a] [-b] [-c] [-d path] [-e] [-f N] [
            -h] [-i] [-I path;path;] [-k] [-l] [-m] [-n] [-p name] [-s] [-t] [-u] [-v] [-
            w] [-x] [-y] [infile]

            -1      generate SOAP 1.1 bindings
            -2      generate SOAP 1.2 bindings
            -C      generate client-side code only
            -S      generate server-side code only
            -T      generate server auto-test code
            -L      don't generate soapClientLib/soapServerLib
            -a      use SOAPAction HTTP/WSA header to invoke server-side operations
            -b      serialize byte arrays char[N] as string
            -c      generate C source code
            -dpath  use path to save files
            -e      generate SOAP RPC encoding style bindings
            -fN     file split of N XML serializer implementations per file (N>=10)
            -h      display help info
            -Ipath  use path(s) for #import
            -i      generate C++ service proxies and objects inherited from soap struct
            -j      generate C++ service proxies and objects that share a soap struct
            -k      generate data structure walkers (experimental)
            -l      generate linkable modules (experimental)
            -m      generate Matlab(tm) code for MEX compiler
            -n      use service name to rename service functions and namespace table
            -pname  save files with new prefix name instead of 'soap'
            -qname  use name as the C++ namespace of all declarations
            -s      generate deserialization code with strict XML validation checks
            -t      generate code for fully xsi:type typed SOAP/XML messaging
            -u      uncomment comments in WSDL/schema output by suppressing XML comments
            -v      display version info
            -w      don't generate WSDL and schema files
            -x      don't generate sample XML message files
            -y      include C/C++ type access information in sample XML messages
            infile  header file to parse (or stdin)          
            其他相關(guān)鏈接: http://www.shnenglu.com/woaidongmao/archive/2008/05/28/51400.html
            posted @ 2012-11-16 17:14 王海光 閱讀(3003) | 評(píng)論 (0)編輯 收藏
            微軟在XP下提供了一個(gè)軟件程序,SYSTEM32\msiexec.exe
            在命令行下輸入:msiexec /? 顯示幫助信息,如下:
            Windows (R) Installer. V 5.0.7600.16385

            msiexec /Option <Required Parameter> [Optional Parameter]

            安裝選項(xiàng)
                </package | /i> <Product.msi>
                    安裝或配置產(chǎn)品
                /a <Product.msi>
                    管理安裝 - 在網(wǎng)絡(luò)上安裝產(chǎn)品
                /j<u|m> <Product.msi> [/t <Transform List>] [/g <Language ID>]
                    公布產(chǎn)品 - m 公布到所有用戶,u 公布到當(dāng)前用戶
                </uninstall | /x> <Product.msi | ProductCode>
                    卸載產(chǎn)品
            顯示選項(xiàng)
                /quiet
                    安靜模式,無(wú)用戶交互
                /passive
                    無(wú)人參與模式 - 只顯示進(jìn)度欄
                /q[n|b|r|f]
                    設(shè)置用戶界面級(jí)別
                    n - 無(wú)用戶界面
                    b - 基本界面
                    r - 精簡(jiǎn)界面
                    f - 完整界面(默認(rèn)值)
                /help
                    幫助信息
            重新啟動(dòng)選項(xiàng)
                /norestart
                    安裝完成后不重新啟動(dòng)
                /promptrestart
                    必要時(shí)提示用戶重新啟動(dòng)
                /forcerestart
                    安裝后始終重新啟動(dòng)計(jì)算機(jī)
            日志選項(xiàng)
                /l[i|w|e|a|r|u|c|m|o|p|v|x|+|!|*] <LogFile>
                    i - 狀態(tài)消息
                    w - 非致命警告
                    e - 所有錯(cuò)誤消息
                    a - 操作的啟動(dòng)
                    r - 操作特定記錄
                    u - 用戶請(qǐng)求
                    c - 初始用戶界面參數(shù)
                    m - 內(nèi)存不足或致命退出信息
                    o - 磁盤空間不足消息
                    p - 終端屬性
                    v - 詳細(xì)輸出
                    x - 額外調(diào)試信息
                    + - 擴(kuò)展到現(xiàn)有日志文件
                    ! - 每一行刷新到日志
                    * - 記錄所有信息,除了 v 和 x 選項(xiàng)
                /log <LogFile>
                    與 /l* <LogFile> 相同
            更新選項(xiàng)
                /update <Update1.msp>[;Update2.msp]
                    應(yīng)用更新
                /uninstall <PatchCodeGuid>[;Update2.msp] /package <Product.msi | ProductCode>
                    刪除產(chǎn)品的更新
            修復(fù)選項(xiàng)
                /f[p|e|c|m|s|o|d|a|u|v] <Product.msi | ProductCode>
                    修復(fù)產(chǎn)品
                    p - 僅當(dāng)文件丟失時(shí)
                    o - 如果文件丟失或安裝了更舊的版本(默認(rèn)值)
                    e - 如果文件丟失或安裝了相同或更舊的版本
                    d - 如果文件丟失或安裝了不同版本
                    c - 如果文件丟失或較驗(yàn)和與計(jì)算的值不匹配
                    a - 強(qiáng)制重新安裝所有文件
                    u - 所有必要的用戶特定注冊(cè)表項(xiàng)(默認(rèn)值)
                    m - 所有必要的計(jì)算機(jī)特定注冊(cè)表項(xiàng)(默認(rèn)值)
                    s - 所有現(xiàn)有的快捷鍵方式(默認(rèn)值)
                    v - 從源運(yùn)行并重新緩存本地安裝包
            設(shè)置公共屬性
                [PROPERTY=PropertyValue]

            請(qǐng)查閱 Windows (R) Installer SDK 獲得有關(guān)命令行語(yǔ)法的其他文檔。

            版權(quán)所有 (C) Microsoft Corporation. 保留所有權(quán)利。
            此軟件的部分內(nèi)容系基于 Independent JPEG Group 的工作。

            運(yùn)行CMD后,輸入msiexec /i Product.msi /q 即可安裝msi程序。 

            運(yùn)行CMD后,輸入msiexec /x ProductCode /q 即可卸載msi安裝過的程序。

            ProductCode的值可在注冊(cè)表中查找,注冊(cè)表位置:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall  根據(jù)DisplayName鍵值來確定安裝的msi程序,UninstallString的值中包含ProductCode 如:{BC12972C-BF15-4607-A745-948DA0DE63FF}

            卸載命令可以寫成如下所示:msiexec /x "{BC12972C-BF15-4607-A745-948DA0DE63FF}" /q
            posted @ 2012-11-15 11:21 王海光 閱讀(2939) | 評(píng)論 (0)編輯 收藏

            基數(shù)排序(Radix sort)是一種非比較型整數(shù)排序算法其原理是將整數(shù)按位數(shù)切割成不同的數(shù)字,然后按每個(gè)位數(shù)分別比較。由于整數(shù)也可以表達(dá)字符串(比如名字或日期)和特定格式的浮點(diǎn)數(shù),所以基數(shù)排序也不是只能使用于整數(shù)?;鶖?shù)排序的發(fā)明可以追溯到1887年赫爾曼·何樂禮打孔卡片制表機(jī)(Tabulation Machine)上的貢獻(xiàn)。

            它是這樣實(shí)現(xiàn)的:將所有待比較數(shù)值(正整數(shù))統(tǒng)一為同樣的數(shù)位長(zhǎng)度,數(shù)位較短的數(shù)前面補(bǔ)零。然后,從最低位開始,依次進(jìn)行一次排序。這樣從最低位排序一直到最高位排序完成以后, 數(shù)列就變成一個(gè)有序序列。

            基數(shù)排序時(shí)對(duì)每一維進(jìn)行調(diào)用子排序算法時(shí)要求這個(gè)子排序算法必須是穩(wěn)定的。
            基數(shù)排序與直覺相反:它是按照從底位到高位的順序排序的。

            偽代碼:

            RADIX-SORT(A,d)

            1    for i <-- 1 to d

            2        do use a stable sort to sort array A on digit i

             

            引理8.3: 給定n個(gè)d位數(shù),每一個(gè)數(shù)位可以取k種可能的值,如果所用穩(wěn)定排序需要Θ(n+k)時(shí)間,基數(shù)排序能以Θ(d(n+k))的時(shí)間完成。

            證明:如果采用計(jì)數(shù)排序這種穩(wěn)定排序,那么每一遍處理需要時(shí)間Θ(n+k),一共需處理d遍,于是基數(shù)排序的運(yùn)行時(shí)間為Θ(d(n+k))。當(dāng)d為常數(shù),k=O(n)時(shí),有線性運(yùn)行時(shí)間。

            注:將關(guān)鍵字分成若干位方面,可以有一定的靈活性。

            引理8.4給定n個(gè)b位數(shù)和任何正整數(shù)r<=b,如果采用的穩(wěn)定排序需要Θ(d(n+k))時(shí)間,則RADIX-SORT能在Θ((b/r)(n+2r))時(shí)間內(nèi)正確地對(duì)這些數(shù)進(jìn)行排序。

            證明:對(duì)于一個(gè)r<=b,將每個(gè)關(guān)鍵字看成由d=b/r位組成的數(shù),每一個(gè)數(shù)字都是(0~ -1)之間的一個(gè)整數(shù),這樣就可以采取計(jì)數(shù)排序。K= ,d=b/r,總的運(yùn)行時(shí)間為Θ((b/r)(n+ ))。

            對(duì)于給定的n值和b值,如何選擇r值使得最小化表達(dá)式(b/r)(n+2r)。如果b< lgn,對(duì)于任何r<=b的值,都有(n+2r)=Θ(n),于是選擇r=b,使計(jì)數(shù)排序的時(shí)間為Θ((b/b)(n+2b)) = Θ(n)。 如果b>lgn,則選擇r=lgn,可以給出在某一常數(shù)因子內(nèi)的最佳時(shí)間:當(dāng)r=lgn時(shí),算法復(fù)雜度為Θ(bn/lgn),當(dāng)r增大到lgn以上時(shí),分子 增大比分母r快,于是運(yùn)行時(shí)間復(fù)雜度為Ω(bn/lgn);反之當(dāng)r減小到lgn以下的時(shí)候,b/r增大,而n+ 仍然是Θ(n)。

            以下引自麻省理工學(xué)院算法導(dǎo)論——筆記:












            以下代碼實(shí)例轉(zhuǎn)自:http://www.docin.com/p-449224125.html

             1 以下是用C++實(shí)現(xiàn)的基數(shù)排序代碼:
             2 #include <cstdio>
             3 #include <cstdlib>
             4 // 這個(gè)是基數(shù)排序用到的計(jì)數(shù)排序,是穩(wěn)定的。
             5 // pDigit是基數(shù)數(shù)組,nMax是基數(shù)的上限,pData是待排序的數(shù)組, nLen是待排序數(shù)組的元素個(gè)數(shù)
             6 // 必須pDigit和pData的下標(biāo)相對(duì)應(yīng)的,即pDigit[1]對(duì)應(yīng)pData[1]
             7 int RadixCountingSort(int *pDigit, int nMax,int *pData,int nLen){
             8 // 以下是計(jì)數(shù)排序
             9 int *pCount = new int[nMax];
            10 int *pSorted = new int[nLen];
            11 int i,j;
            12 for(i=0; i<nMax; ++i)
            13 pCount[i] = 0;
            14 for(i=0; i<nLen; ++i)
            15 ++pCount[pDigit[i]];
            16 for(i=1; i<nMax; ++i)
            17 pCount[i] += pCount[i-1];
            18 for(i=nLen-1; i>=0--i){
            19 --pCount[pDigit[i]];
            20 pSorted[pCount[pDigit[i]]] = pData[i]; // z這里注意,是把待排序的數(shù)組賦值
            21 }
            22 for(i=0; i<nLen; ++i)
            23 pData[i] = pSorted[i];
            24 delete [] pCount;
            25 delete [] pSorted;
            26 return 1;
            27 }
            28 int RadixSort(int *pData, int nLen){
            29 int *pDigit = new int[nLen]; // 申請(qǐng)存放基數(shù)(某個(gè)位數(shù))的空間
            30 int nRadixBase = 1;
            31 bool flag = false;
            32 while(!flag){
            33 flag = true;
            34 nRadixBase *= 10;
            35 for(int i=0; i<nLen; ++i){
            36 pDigit[i] = pData[i]%nRadixBase; // 求出某位上的數(shù)當(dāng)做基數(shù)
            37 pDigit[i] /= nRadixBase/10;
            38 if(pDigit[i] > 0)
            39 flag = false;
            40 }
            41 if(flag)
            42 break;
            43 RadixCountingSort(pDigit,10,pData,nLen);
            44 }
            45 delete[] pDigit;
            46 return 1;
            47 }
            48 main()
            49 {
            50 int nData[10]={43,65,34,5,8,34,23,0,45,34};;
            51 RadixSort(nData, 10);
            52 printf("經(jīng)排序后的數(shù)列是:\n");
            53 for (int i = 0; i < 10++i)
            54 printf("%d ", nData[i]);
            55 printf("\n");
            56 return 0;
            57 }

             

            posted @ 2012-11-13 16:52 王海光 閱讀(694) | 評(píng)論 (0)編輯 收藏
            算法介紹
              計(jì)數(shù)排序是一個(gè)類似于桶排序的排序算法,其優(yōu)勢(shì)是對(duì)已知數(shù)量范圍的數(shù)組進(jìn)行排序。它創(chuàng)建一個(gè)長(zhǎng)度為這個(gè)數(shù)據(jù)范圍的數(shù)組C,C中每個(gè)元素記錄要排序數(shù)組中對(duì)應(yīng)記錄的出現(xiàn)個(gè)數(shù)。這個(gè)算法于1954年由 Harold H. Seward 提出。     

                  當(dāng)輸入的元素是 n 個(gè) 0 到 k 之間的整數(shù)時(shí),它的運(yùn)行時(shí)間是 Θ(n + k)。計(jì)數(shù)排序不是比較排序,排序的速度快于任何比較排序算法。

            由于用來計(jì)數(shù)的數(shù)組C的長(zhǎng)度取決于待排序數(shù)組中數(shù)據(jù)的范圍(等于待排序數(shù)組的最大值與最小值的差加上1),這使得計(jì)數(shù)排序?qū)τ跀?shù)據(jù)范圍很大的數(shù)組,需要大量時(shí)間和內(nèi)存。例如:計(jì)數(shù)排序是用來排序0到100之間的數(shù)字的最好的算法,但是它不適合按字母順序排序人名。但是,計(jì)數(shù)排序可以用在基數(shù)排序中的算法來排序數(shù)據(jù)范圍很大的數(shù)組。計(jì)數(shù)排序之所以能夠突破前面所述的Ω(nlgn)極限,是因?yàn)樗皇腔谠乇容^的。計(jì)數(shù)排序適合所需排序的數(shù)組元素取值范圍不大的情況(范圍太大的話輔助空間很大)。

            定理:任意一個(gè)比較排序算法在最壞情況下,都需要做Ω(nlgn)次比較。


            算法的步驟如下:

            • 找出待排序的數(shù)組中最大和最小的元素
            • 統(tǒng)計(jì)數(shù)組中每個(gè)值為i元素出現(xiàn)的次數(shù),存入數(shù)組C的第i項(xiàng)
            • 對(duì)所有的計(jì)數(shù)累加(從C中的第一個(gè)元素開始,每一項(xiàng)和前一項(xiàng)相加)
            • 反向填充目標(biāo)數(shù)組:將每個(gè)元素i放在新數(shù)組的第C(i)項(xiàng),每放一個(gè)元素就將C(i)減去1

            以下引自麻省理工學(xué)院算法導(dǎo)論——筆記:

            Counting sort: No comparisons between elements.
            • Input: A[1 . . n], where A[ j]??{1, 2, …, k} .
            • Output: B[1 . . n], sorted.
            • Auxiliary storage: C[1 . . k] .

            Counting sort
            for i  ← 1 to k
            do C[i]  ← 0
            for j  ←1 to n
            do C[A[ j]]  ← C[A[ j]] + 1   —> C[i] = |{key = i}|
            for i  ← 2 to k
            do C[i]  ← C[i] + C[i–1]        —>C[i] = |{key  ← i}|
            for j  ← n downto 1
            do B[C[A[ j]]]  ← A[ j]
            C[A[ j]]  ← C[A[ j]] – 1

            實(shí)例:


            對(duì)所有的計(jì)數(shù)累加(從C中的第一個(gè)元素開始,每一項(xiàng)和前一項(xiàng)相加)



            反向填充目標(biāo)數(shù)組:將每個(gè)元素i放在新數(shù)組的第C(i)項(xiàng),每放一個(gè)元素就將C(i)減去1






            注:基于比較的排序算法的最佳平均時(shí)間復(fù)雜度為 O(nlogn)
                 穩(wěn)定性:算法是穩(wěn)定的。


            如果k小于nlogn可以用計(jì)數(shù)排序,如果k大于nlogn可以用歸并排序。


            代碼實(shí)例:

             1 C++實(shí)現(xiàn):
             2 #include<cstdio>
             3 #include<algorithm>
             4 using namespace std;
             5 //n為數(shù)組元素個(gè)數(shù),k是最大的那個(gè)元素
             6 void CountingSort(int *input, int size, int k){
             7 int i;
             8 int *result = new int[size]; //開辟一個(gè)保存結(jié)果的臨時(shí)數(shù)組
             9 int *count = new int[k+1]; //開辟一個(gè)臨時(shí)數(shù)組
            10 for(i=0; i<=k; ++i)
            11 count[i]=0;
            12 //使count[i]等于等于i的元素的個(gè)數(shù)
            13 for(i=0; i<size; ++i)
            14 ++count[input[i]]; //count數(shù)組中坐標(biāo)為元素input[i]的增加1,即該元素出現(xiàn)的次數(shù)加1
            15 for(i=1; i<=k; ++i)
            16 count[i] += count[i-1];
            17 for(i=size-1; i>=0--i){ //正序來也行,但是到這來可以使排序是穩(wěn)定的
            18 --count[input[i]]; //因?yàn)閿?shù)組下標(biāo)從0開始,所以這個(gè)放在前面
            19 result[count[input[i]]] = input[i]; //這個(gè)比較繞, count[input[i]-1] 就代表小于等于元素
                }  
            20 copy(result,result+size,input); //調(diào)用copy函數(shù)把結(jié)果存回原數(shù)組
            21 delete [] result; //記得釋放空間
            22 delete [] count;
            23 }
            24 int main()
            25 {
            26 int input[11]={2,7,4,9,8,5,7,8,2,0,7};
            27 CountingSort(input,11,9);
            28 for(int i=0; i<11++i)
            29 printf("%d ",input[i]);
            30 putchar('\n');
            31 return 0;
            32 }

             

            posted @ 2012-11-13 11:07 王海光 閱讀(706) | 評(píng)論 (1)編輯 收藏
                 摘要:   1 #=============================================================================  2  本文轉(zhuǎn)自: http://blog.csdn.net/tge7618291      下載地址1:http:/...  閱讀全文
            posted @ 2012-11-09 13:59 王海光 閱讀(956) | 評(píng)論 (0)編輯 收藏
                 摘要: 為了編譯一個(gè)簡(jiǎn)單的源文件main.c,需要自動(dòng)生成一個(gè)makefile,以下是步驟:第一步:----------在/root/project/main目錄下創(chuàng)建一個(gè)文件main.c,其內(nèi)容如下:------------------------------------------------#include <stdio.h> int main(int argc, char** argv...  閱讀全文
            posted @ 2012-11-08 15:37 王海光 閱讀(1490) | 評(píng)論 (0)編輯 收藏

            目的:
                   基本掌握了 make 的用法,能在Linux系統(tǒng)上編程。
            環(huán)境:
                   Linux系統(tǒng),或者有一臺(tái)Linux服務(wù)器,通過終端連接。一句話:有Linux編譯環(huán)境。
            準(zhǔn)備:
                   準(zhǔn)備三個(gè)文件:file1.c, file2.c, file2.h
                   file1.c:
                          #include <stdio.h>
                          #include "file2.h"
                          int main()
                          {
                                 printf("print file1$$$$$$$$$$$$$$$$$$$$$$$$\n");
                                 File2Print();
                                 return 0;
                          }

                   file2.h:

                          #ifndef FILE2_H_
                          #define    FILE2_H_

                                  #ifdef __cplusplus

                                        extern "C" {

                                 #endif

                                 void File2Print();

                                 #ifdef __cplusplus

                                        }

                                 #endif

                          #endif

                   file2.c:
                          #include "file2.h"
                          void File2Print()
                          {
                                 printf("Print file2**********************\n");
                          }

            基礎(chǔ):
                   先來個(gè)例子:
                   有這么個(gè)Makefile文件。(文件和Makefile在同一目錄)
                   === makefile 開始 ===
                          helloworld:file1.o file2.o
                                 gcc file1.o file2.o -o helloworld

                         
            file1.o:file1.c file2.h
                                 gcc -c file1.c -o file1.o

                           file2.o:file2.c file2.h

                                 gcc -c file2.c -o file2.o

                          clean:

                                 rm -rf *.o helloworld

                   === makefile 結(jié)束 ===

            一個(gè) makefile 主要含有一系列的規(guī)則,如下:
            A: B
            (tab)<command>
            (tab)<command>

            每個(gè)命令行前都必須有tab符號(hào)。

             

            上面的makefile文件目的就是要編譯一個(gè)helloworld的可執(zhí)行文件。讓我們一句一句來解釋:

                   helloworld : file1.o file2.o                 helloworld依賴file1.o file2.o兩個(gè)目標(biāo)文件。

                   gcc File1.o File2.o -o helloworld      編譯出helloworld可執(zhí)行文件。-o表示你指定 的目標(biāo)文件名。

                  

                   file1.o : file1.c    file1.o依賴file1.c文件。

                   gcc -c file1.c -o file1.o                  編譯出file1.o文件。-c表示gcc 只把給它的文件編譯成目標(biāo)文件, 用源碼文件的文件名命名但把其后綴由“.c”“.cc”變成“.o”。在這句中,可以省略-o file1.o,編譯器默認(rèn)生成file1.o文件,這就是-c的作用。

             

                          file2.o : file2.c file2.h
                         
            gcc -c file2.c -o file2.o

            這兩句和上兩句相同。

             

                   clean:

                          rm -rf *.o helloworld

            當(dāng)用戶鍵入make clean命令時(shí),會(huì)刪除*.o helloworld文件。

             

            如果要編譯cpp文件,只要把gcc改成g++就行了。

            寫好Makefile文件,在命令行中直接鍵入make命令,就會(huì)執(zhí)行Makefile中的內(nèi)容了。

             

            到這步我想你能編一個(gè)Helloworld程序了。

             

            上一層樓:使用變量

                   上面提到一句,如果要編譯cpp文件,只要把gcc改成g++就行了。但如果Makefile中有很多gcc,那不就很麻煩了。

                   第二個(gè)例子:

                   === makefile 開始 ===
                         
            OBJS = file1.o file2.o
                         
            CC = gcc
                         
            CFLAGS = -Wall -O -g

                         
            helloworld : $(OBJS)
                                
            $(CC) $(OBJS) -o helloworld

                         
            file1.o : file1.c file2.h
                                
            $(CC) $(CFLAGS) -c file1.c -o file1.o

                         
            file2.o : file2.c file2.h
                                
            $(CC) $(CFLAGS) -c file2.c -o file2.o

             

                          clean:

                                 rm -rf *.o helloworld
            === makefile 結(jié)束 ===

             

                   這里我們應(yīng)用到了變量。要設(shè)定一個(gè)變量,你只要在一行的開始寫下這個(gè)變量的名字,后 面跟一個(gè) = 號(hào),后面跟你要設(shè)定的這個(gè)變量的值。以后你要引用 這個(gè)變量,寫一個(gè) $ 符號(hào),后面是圍在括號(hào)里的變量名。

             

            CFLAGS = -Wall -O –g,解釋一下。這是配置編譯器設(shè)置,并把它賦值給CFFLAGS變量。

            -Wall          輸出所有的警告信息。

            -O              在編譯時(shí)進(jìn)行優(yōu)化。

            -g               表示編譯debug版本。

             

                   這樣寫的Makefile文件比較簡(jiǎn)單,但很容易就會(huì)發(fā)現(xiàn)缺點(diǎn),那就是要列出所有的c文件。如果你添加一個(gè)c文件,那就需要修改Makefile文件,這在項(xiàng)目開發(fā)中還是比較麻煩的。

             

             

            再上一層樓:使用函數(shù)

                   學(xué)到這里,你也許會(huì)說,這就好像編程序嗎?有變量,也有函數(shù)。其實(shí)這就是編程序,只不過用的語(yǔ)言不同而已。

                   第三個(gè)例子:

                   === makefile 開始 ===
                         
            CC = gcc

                          XX = g++
                         
            CFLAGS = -Wall -O –g

                          TARGET = ./helloworld

                          %.o: %.c

                                 $(CC) $(CFLAGS) -c $< -o $@

                          %.o:%.cpp

                                 $(XX) $(CFLAGS) -c $< -o $@

             

                          SOURCES = $(wildcard *.c *.cpp)
                         
            OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))


                         
            $(TARGET) : $(OBJS)
                                
            $(XX) $(OBJS) -o $(TARGET)

                                 chmod a+x $(TARGET)

            clean:

                   rm -rf *.o helloworld
            === makefile 結(jié)束 ===

            函數(shù)1wildcard

                   產(chǎn)生一個(gè)所有以 '.c' 結(jié)尾的文件的列表。

                   SOURCES = $(wildcard *.c *.cpp)表示產(chǎn)生一個(gè)所有以 .c,.cpp結(jié)尾的文件的列表,然后存入變量 SOURCES 里。

             

            函數(shù)2patsubst

                   匹配替換,有三個(gè)參數(shù)。第一個(gè)是一個(gè)需要匹配的式樣,第二個(gè)表示用什么來替換它,第三個(gè)是一個(gè)需要被處理的由空格分隔的列表。

            OBJS = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCES)))表示把文件列表中所有的.c,.cpp字符變成.o,形成一個(gè)新的文件列表,然后存入OBJS變量中。

             

            %.o: %.c

                   $(CC) $(CFLAGS) -c $< -o $@

            %.o:%.cpp

                   $(XX) $(CFLAGS) -c $< -o $@

                   這幾句命令表示把所有的.c,.cpp編譯成.o文件。

                   這里有三個(gè)比較有用的內(nèi)部變量。$@ 擴(kuò)展成當(dāng)前規(guī)則的目的文件名, $< 擴(kuò)展成依靠       列表中的第一個(gè)依靠文件,而 $^ 擴(kuò)展成整個(gè)依靠的列表(除掉了里面所有重 復(fù)的文件名)。

             

                   chmod a+x $(TARGET)表示把helloworld強(qiáng)制變成可執(zhí)行文件。

                   到這里,我想你已經(jīng)能夠編寫一個(gè)比較簡(jiǎn)單也比較通用的Makefile文件了,上面所有的例子都假定所有的文件都在同一個(gè)目錄下,不包括子目錄。

                   那么文件不在一個(gè)目錄可以嗎?

                   怎么編寫Makefile生成靜態(tài)庫(kù)?

                   你還想更上一層樓嗎?

                   請(qǐng)聽下回分解。

            本文轉(zhuǎn)自:http://goodcandle.cnblogs.com/archive/2006/03/30/278702.html

            posted @ 2012-11-08 13:59 王海光 閱讀(454) | 評(píng)論 (0)編輯 收藏
            一、基本概念:

            鉤子(Hook),是Windows消息處理機(jī)制的一個(gè)平臺(tái),應(yīng)用程序可以在上面設(shè)置子程以監(jiān)視指定窗口的某種消息,而且所監(jiān)視的窗口可以是其他進(jìn)程所創(chuàng)建的。當(dāng)消息到達(dá)后,在目標(biāo)窗口處理函數(shù)之前處理它。鉤子機(jī)制允許應(yīng)用程序截獲處理window消息或特定事件。

            鉤子實(shí)際上是一個(gè)處理消息的程序段,通過系統(tǒng)調(diào)用,把它掛入系統(tǒng)。每當(dāng)特定的消息發(fā)出,在沒有到達(dá)目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數(shù)先得到控制權(quán)。這時(shí)鉤子函數(shù)即可以加工處理(改變)該消息,也可以不作處理而繼續(xù)傳遞該消息,還可以強(qiáng)制結(jié)束消息的傳遞。

            二、運(yùn)行機(jī)制:

            1、鉤子鏈表和鉤子子程:

            每一個(gè)Hook都有一個(gè)與之相關(guān)聯(lián)的指針列表,稱之為鉤子鏈表,由系統(tǒng)來維護(hù)。這個(gè)列表的指針指向指定的,應(yīng)用程序定義的,被Hook子程調(diào)用的回調(diào)函數(shù),也就是該鉤子的各個(gè)處理子程。當(dāng)與指定的Hook類型關(guān)聯(lián)的消息發(fā)生時(shí),系統(tǒng)就把這個(gè)消息傳遞到Hook子程。一些Hook子程可以只監(jiān)視消息,或者修改消息,或者停止消息的前進(jìn),避免這些消息傳遞到下一個(gè)Hook子程或者目的窗口。最近安裝的鉤子放在鏈的開始,而最早安裝的鉤子放在最后,也就是后加入的先獲得控制權(quán)。

            Windows 并不要求鉤子子程的卸載順序一定得和安裝順序相反。每當(dāng)有一個(gè)鉤子被卸載,Windows 便釋放其占用的內(nèi)存,并更新整個(gè)Hook鏈表。如果程序安裝了鉤子,但是在尚未卸載鉤子之前就結(jié)束了,那么系統(tǒng)會(huì)自動(dòng)為它做卸載鉤子的操作。

            鉤子子程是一個(gè)應(yīng)用程序定義的回調(diào)函數(shù)(CALLBACK Function),不能定義成某個(gè)類的成員函數(shù),只能定義為普通的C函數(shù)。用以監(jiān)視系統(tǒng)或某一特定類型的事件,這些事件可以是與某一特定線程關(guān)聯(lián)的,也可以是系統(tǒng)中所有線程的事件。

            鉤子子程必須按照以下的語(yǔ)法:
            1 LRESULT CALLBACK HookProc
            2 (
            3      int nCode, 
            4          WPARAM wParam, 
            5          LPARAM lParam
            6 );
            HookProc是應(yīng)用程序定義的名字。
            nCode參數(shù)是Hook代碼,Hook子程使用這個(gè)參數(shù)來確定任務(wù)。這個(gè)參數(shù)的值依賴于Hook類型,每一種Hook都有自己的Hook代碼特征字符集。
            wParam和lParam參數(shù)的值依賴于Hook代碼,但是它們的典型值是包含了關(guān)于發(fā)送或者接收消息的信息。

            2、鉤子的安裝與釋放:

            使用API函數(shù)SetWindowsHookEx()把一個(gè)應(yīng)用程序定義的鉤子子程安裝到鉤子鏈表中。SetWindowsHookEx函數(shù)總是在Hook鏈的開頭安裝Hook子程。當(dāng)指定類型的Hook監(jiān)視的事件發(fā)生時(shí),系統(tǒng)就調(diào)用與這個(gè)Hook關(guān)聯(lián)的Hook鏈的開頭的Hook子程。每一個(gè)Hook鏈中的Hook子程都決定是否把這個(gè)事件傳遞到下一個(gè)Hook子程。Hook子程傳遞事件到下一個(gè)Hook子程需要調(diào)用CallNextHookEx函數(shù)。 
             1 HHOOK SetWindowsHookEx( 
             2      int idHook,      // 鉤子的類型,即它處理的消息類型
             3      HOOKPROC lpfn,   // 鉤子子程的地址指針。如果dwThreadId參數(shù)為0
             4                                              // 或是一個(gè)由別的進(jìn)程創(chuàng)建的線程的標(biāo)識(shí),
             5                                              // lpfn必須指向DLL中的鉤子子程。
             6                                              // 除此以外,lpfn可以指向當(dāng)前進(jìn)程的一段鉤子子程代碼。
             7                                              // 鉤子函數(shù)的入口地址,當(dāng)鉤子鉤到任何消息后便調(diào)用這個(gè)函數(shù)。
             8      HINSTANCE hMod,  // 應(yīng)用程序?qū)嵗木浔?biāo)識(shí)包含lpfn所指的子程的DLL。
            10                                              // 如果dwThreadId 標(biāo)識(shí)當(dāng)前進(jìn)程創(chuàng)建的一個(gè)線程,
            11                                              // 而且子程代碼位于當(dāng)前進(jìn)程,hMod必須為NULL。
            12                                              // 可以很簡(jiǎn)單的設(shè)定其為本應(yīng)用程序的實(shí)例句柄。
            13      DWORD dwThreadId // 與安裝的鉤子子程相關(guān)聯(lián)的線程的標(biāo)識(shí)符。
            14                                              // 如果為0,鉤子子程與所有的線程關(guān)聯(lián),即為全局鉤子。
            15                  ); 
              
            函數(shù)成功則返回鉤子子程的句柄,失敗返回NULL。

            以上所說的鉤子子程與線程相關(guān)聯(lián)是指在一鉤子鏈表中發(fā)給該線程的消息同時(shí)發(fā)送給鉤子子程,且被鉤子子程先處理。

            在鉤子子程中調(diào)用得到控制權(quán)的鉤子函數(shù)在完成對(duì)消息的處理后,如果想要該消息繼續(xù)傳遞,那么它必須調(diào)用另外一個(gè)SDK中的API函數(shù)CallNextHookEx來傳遞它,以執(zhí)行鉤子鏈表所指的下一個(gè)鉤子子程。這個(gè)函數(shù)成功時(shí)返回鉤子鏈中下一個(gè)鉤子過程的返回值,返回值的類型依賴于鉤子的類型。這個(gè)函數(shù)的原型如下:
            1 LRESULT CallNextHookEx
            2             (
            3                 HHOOK hhk;
            4                 int nCode;
            5                 WPARAM wParam;
            6                 LPARAM lParam;
            7              );
            hhk為當(dāng)前鉤子的句柄,由SetWindowsHookEx()函數(shù)返回。
            NCode為傳給鉤子過程的事件代碼。
            wParam和lParam 分別是傳給鉤子子程的wParam值,其具體含義與鉤子類型有關(guān)。
              
            鉤子函數(shù)也可以通過直接返回TRUE來丟棄該消息,并阻止該消息的傳遞。否則的話,其他安裝了鉤子的應(yīng)用程序?qū)⒉粫?huì)接收到鉤子的通知而且還有可能產(chǎn)生不正確的結(jié)果。

            鉤子在使用完之后需要用UnHookWindowsHookEx()卸載,否則會(huì)造成麻煩。釋放鉤子比較簡(jiǎn)單,UnHookWindowsHookEx()只有一個(gè)參數(shù)。函數(shù)原型如下:
            1 UnHookWindowsHookEx
            2 (
            3     HHOOK hhk;
            4 );
            函數(shù)成功返回TRUE,否則返回FALSE。

            3、一些運(yùn)行機(jī)制:

            在Win16環(huán)境中,DLL的全局?jǐn)?shù)據(jù)對(duì)每個(gè)載入它的進(jìn)程來說都是相同的;而在Win32環(huán)境中,情況卻發(fā)生了變化,DLL函數(shù)中的代碼所創(chuàng)建的任何對(duì)象(包括變量)都?xì)w調(diào)用它的線程或進(jìn)程所有。當(dāng)進(jìn)程在載入DLL時(shí),操作系統(tǒng)自動(dòng)把DLL地址映射到該進(jìn)程的私有空間,也就是進(jìn)程的虛擬地址空間,而且也復(fù)制該DLL的全局?jǐn)?shù)據(jù)的一份拷貝到該進(jìn)程空間。也就是說每個(gè)進(jìn)程所擁有的相同的DLL的全局?jǐn)?shù)據(jù),它們的名稱相同,但其值卻并不一定是相同的,而且是互不干涉的。

            因此,在Win32環(huán)境下要想在多個(gè)進(jìn)程中共享數(shù)據(jù),就必須進(jìn)行必要的設(shè)置。在訪問同一個(gè)Dll的各進(jìn)程之間共享存儲(chǔ)器是通過存儲(chǔ)器映射文件技術(shù)實(shí)現(xiàn)的。也可以把這些需要共享的數(shù)據(jù)分離出來,放置在一個(gè)獨(dú)立的數(shù)據(jù)段里,并把該段的屬性設(shè)置為共享。必須給這些變量賦初值,否則編譯器會(huì)把沒有賦初始值的變量放在一個(gè)叫未被初始化的數(shù)據(jù)段中。

            #pragma data_seg預(yù)處理指令用于設(shè)置共享數(shù)據(jù)段。例如:
            1 #pragma data_seg("SharedDataName")
            2 HHOOK hHook=NULL;
            3 #pragma data_seg()
            在#pragma data_seg("SharedDataName")和#pragma data_seg()之間的所有變量 將被訪問該Dll的所有進(jìn)程看到和共享。


            當(dāng)進(jìn)程隱式或顯式調(diào)用一個(gè)動(dòng)態(tài)庫(kù)里的函數(shù)時(shí),系統(tǒng)都要把這個(gè)動(dòng)態(tài)庫(kù)映射到這個(gè)進(jìn)程的虛擬地址空間里(以下簡(jiǎn)稱"地址空間")。這使得DLL成為進(jìn)程的一部分,以這個(gè)進(jìn)程的身份執(zhí)行,使用這個(gè)進(jìn)程的堆棧。

            4、系統(tǒng)鉤子與線程鉤子:

            SetWindowsHookEx()函數(shù)的最后一個(gè)參數(shù)決定了此鉤子是系統(tǒng)鉤子還是線程鉤子。
                
            線程勾子用于監(jiān)視指定線程的事件消息。線程勾子一般在當(dāng)前線程或者當(dāng)前線程派生的線程內(nèi)。
                
            系統(tǒng)勾子監(jiān)視系統(tǒng)中的所有線程的事件消息。因?yàn)橄到y(tǒng)勾子會(huì)影響系統(tǒng)中所有的應(yīng)用程序,所以勾子函數(shù)必須放在獨(dú)立的動(dòng)態(tài)鏈接庫(kù)(DLL) 中。系統(tǒng)自動(dòng)將包含"鉤子回調(diào)函數(shù)"的DLL映射到受鉤子函數(shù)影響的所有進(jìn)程的地址空間中,即將這個(gè)DLL注入了那些進(jìn)程。

            幾點(diǎn)說明:
            (1)如果對(duì)于同一事件(如鼠標(biāo)消息)既安裝了線程勾子又安裝了系統(tǒng)勾子,那么系統(tǒng)會(huì)自動(dòng)先調(diào)用線程勾子,然后調(diào)用系統(tǒng)勾子。

            (2)對(duì)同一事件消息可安裝多個(gè)勾子處理過程,這些勾子處理過程形成了勾子鏈。當(dāng)前勾子處理結(jié)束后應(yīng)把勾子信息傳遞給下一個(gè)勾子函數(shù)。

            (3)勾子特別是系統(tǒng)勾子會(huì)消耗消息處理時(shí)間,降低系統(tǒng)性能。只有在必要的時(shí)候才安裝勾子,在使用完畢后要及時(shí)卸載。

            三、鉤子類型

            每一種類型的Hook可以使應(yīng)用程序能夠監(jiān)視不同類型的系統(tǒng)消息處理機(jī)制。下面描述所有可以利用的Hook類型。

            1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks

            WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以監(jiān)視發(fā)送到窗口過程的消息。系統(tǒng)在消息發(fā)送到接收窗口過程之前WH_CALLWNDPROCHook子程,并且在窗口過程處理完消息之后調(diào)用WH_CALLWNDPROCRET Hook子程。

            WH_CALLWNDPROCRET Hook傳遞指針到CWPRETSTRUCT結(jié)構(gòu),再傳遞到Hook子程。CWPRETSTRUCT結(jié)構(gòu)包含了來自處理消息的窗口過程的返回值,同樣也包括了與這個(gè)消息關(guān)聯(lián)的消息參數(shù)。

            2、WH_CBT Hook

            在以下事件之前,系統(tǒng)都會(huì)調(diào)用WH_CBT Hook子程,這些事件包括:
            1. 激活,建立,銷毀,最小化,最大化,移動(dòng),改變尺寸等窗口事件;
            2. 完成系統(tǒng)指令;
            3. 來自系統(tǒng)消息隊(duì)列中的移動(dòng)鼠標(biāo),鍵盤事件;
            4. 設(shè)置輸入焦點(diǎn)事件;
            5. 同步系統(tǒng)消息隊(duì)列事件。
                
            Hook子程的返回值確定系統(tǒng)是否允許或者防止這些操作中的一個(gè)。

            3、WH_DEBUG Hook

            在系統(tǒng)調(diào)用系統(tǒng)中與其他Hook關(guān)聯(lián)的Hook子程之前,系統(tǒng)會(huì)調(diào)用WH_DEBUG Hook子程。你可以使用這個(gè)Hook來決定是否允許系統(tǒng)調(diào)用與其他Hook關(guān)聯(lián)的Hook子程。

            4、WH_FOREGROUNDIDLE Hook

            當(dāng)應(yīng)用程序的前臺(tái)線程處于空閑狀態(tài)時(shí),可以使用WH_FOREGROUNDIDLE Hook執(zhí)行低優(yōu)先級(jí)的任務(wù)。當(dāng)應(yīng)用程序的前臺(tái)線程大概要變成空閑狀態(tài)時(shí),系統(tǒng)就會(huì)調(diào)用WH_FOREGROUNDIDLE Hook子程。

            5、WH_GETMESSAGE Hook

            應(yīng)用程序使用WH_GETMESSAGE Hook來監(jiān)視從GetMessage or PeekMessage函數(shù)返回的消息。你可以使用WH_GETMESSAGE Hook去監(jiān)視鼠標(biāo)和鍵盤輸入,以及其他發(fā)送到消息隊(duì)列中的消息。

            6、WH_JOURNALPLAYBACK Hook

            WH_JOURNALPLAYBACK Hook使應(yīng)用程序可以插入消息到系統(tǒng)消息隊(duì)列??梢允褂眠@個(gè)Hook回放通過使用WH_JOURNALRECORD Hook記錄下來的連續(xù)的鼠標(biāo)和鍵盤事件。只要WH_JOURNALPLAYBACK Hook已經(jīng)安裝,正常的鼠標(biāo)和鍵盤事件就是無(wú)效的。WH_JOURNALPLAYBACK Hook是全局Hook,它不能象線程特定Hook一樣使用。WH_JOURNALPLAYBACK Hook返回超時(shí)值,這個(gè)值告訴系統(tǒng)在處理來自回放Hook當(dāng)前消息之前需要等待多長(zhǎng)時(shí)間(毫秒)。這就使Hook可以控制實(shí)時(shí)事件的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它們不會(huì)被注射到任何行程位址空間。

            7、WH_JOURNALRECORD Hook

            WH_JOURNALRECORD Hook用來監(jiān)視和記錄輸入事件。典型的,可以使用這個(gè)Hook記錄連續(xù)的鼠標(biāo)和鍵盤事件,然后通過使用WH_JOURNALPLAYBACK Hook來回放。WH_JOURNALRECORD Hook是全局Hook,它不能象線程特定Hook一樣使用。WH_JOURNALRECORD是system-wide local hooks,它們不會(huì)被注射到任何行程位址空間。

            8、WH_KEYBOARD Hook

            在應(yīng)用程序中,WH_KEYBOARD Hook用來監(jiān)視WM_KEYDOWN and WM_KEYUP消息,這些消息通過GetMessage or PeekMessage function返回??梢允褂眠@個(gè)Hook來監(jiān)視輸入到消息隊(duì)列中的鍵盤消息。

            9、WH_KEYBOARD_LL Hook

            WH_KEYBOARD_LL Hook監(jiān)視輸入到線程消息隊(duì)列中的鍵盤消息。

            10、WH_MOUSE Hook

            WH_MOUSE Hook監(jiān)視從GetMessage 或者 PeekMessage 函數(shù)返回的鼠標(biāo)消息。使用這個(gè)Hook監(jiān)視輸入到消息隊(duì)列中的鼠標(biāo)消息。

            11、WH_MOUSE_LL Hook

            WH_MOUSE_LL Hook監(jiān)視輸入到線程消息隊(duì)列中的鼠標(biāo)消息。

            12、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks

            WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我們可以監(jiān)視菜單,滾動(dòng)條,消息框,對(duì)話框消息并且發(fā)現(xiàn)用戶使用ALT+TAB or ALT+ESC 組合鍵切換窗口。WH_MSGFILTER Hook只能監(jiān)視傳遞到菜單,滾動(dòng)條,消息框的消息,以及傳遞到通過安裝了Hook子程的應(yīng)用程序建立的對(duì)話框的消息。WH_SYSMSGFILTER Hook監(jiān)視所有應(yīng)用程序消息。
                
            WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我們可以在模式循環(huán)期間過濾消息,這等價(jià)于在主消息循環(huán)中過濾消息。
                
            通過調(diào)用CallMsgFilter function可以直接的調(diào)用WH_MSGFILTER Hook。通過使用這個(gè)函數(shù),應(yīng)用程序能夠在模式循環(huán)期間使用相同的代碼去過濾消息,如同在主消息循環(huán)里一樣。

            13、WH_SHELL Hook

            外殼應(yīng)用程序可以使用WH_SHELL Hook去接收重要的通知。當(dāng)外殼應(yīng)用程序是激活的并且當(dāng)頂層窗口建立或者銷毀時(shí),系統(tǒng)調(diào)用WH_SHELL Hook子程。
            WH_SHELL 共有5鐘情況:
            1. 只要有個(gè)top-level、unowned 窗口被產(chǎn)生、起作用、或是被摧毀;
            2. 當(dāng)Taskbar需要重畫某個(gè)按鈕;
            3. 當(dāng)系統(tǒng)需要顯示關(guān)于Taskbar的一個(gè)程序的最小化形式;
            4. 當(dāng)目前的鍵盤布局狀態(tài)改變;
            5. 當(dāng)使用者按Ctrl+Esc去執(zhí)行Task Manager(或相同級(jí)別的程序)。

                按照慣例,外殼應(yīng)用程序都不接收WH_SHELL消息。所以,在應(yīng)用程序能夠接收WH_SHELL消息之前,應(yīng)用程序必須調(diào)用SystemParametersInfo function注冊(cè)它自己。

            以上轉(zhuǎn)自:http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx
            以下轉(zhuǎn)自:http://topic.csdn.net/t/20030513/03/1774836.html

            CallNextHookEx 作用

            Hook   串鏈(Hook   Chains)
            當(dāng)許多程式都安裝了某種型態(tài)的hook   時(shí),就會(huì)形成一個(gè)filter-function   chain。一旦特定 的event   發(fā)生,Windows   會(huì)呼叫該型態(tài)中最新掛上的hook   filter   function。舉個(gè)例,如果 程式A   掛上了一個(gè)system-wide   WH_KEYBOARD   hook,每當(dāng)有任何執(zhí)行緒取得鍵盤訊 息,Windows   就會(huì)呼叫這個(gè)filter   function。如果程式B   也掛上了一個(gè)system-wide WH_KEYBOARD   hook,那麼當(dāng)event   發(fā)生,Windows   不再呼叫程式A   的filter   function, 改呼叫程式B的filter   function。這也意味每一個(gè)filter   function   有責(zé)任確保先前掛上的filter Windows   95   程式設(shè)計(jì)指南(Windows   95   :   A   Developer’s   Guide) 394 function   被呼叫(也就是維護(hù)串鏈的完整性)。 SetWindowsHookEx   函式會(huì)將新掛上的hook   filter   function   的代碼傳回。任何程式只要掛 上一個(gè)新的filter   function   就必須儲(chǔ)存這個(gè)代碼(通常存放在全域變數(shù)中):
            static   HHOOK   g_hhook   =   NULL;
            .   .   .
            g_hhook   =   SetWindowsHookEx(WH_KEYBOARD,   Example_kybdHook,   hinst,   NULL);
            .   .   .
            如果有錯(cuò)誤發(fā)生,SetWindowsHookEx   函式會(huì)傳回NULL。
            如果你希望hook   chain   中的其它filter   functions   也能夠執(zhí)行,你可以在你的filter   function 中呼叫CallNextHookEx   函式(或許你已經(jīng)在先前的Example_KybdHook   函式片段中注意 到了) 

            LRESULT   CallNextHookEx(HHOOK   hhook,   int   nCode,   WPARAM   wParam,   LPARAM   lParam);
            這個(gè)函式會(huì)呼叫filter-function   chain   的下一個(gè)filter   function,並傳入相同的nCode、 wParam   和lParam。下一個(gè)filter   function   結(jié)束之前,應(yīng)該也遵循這個(gè)規(guī)則去呼叫 CallNextHookEx   函式,並再次將hook   代碼(通常那是被放在全域變數(shù)中)傳入。 CallNextHookEx   函式利用這個(gè)hook   代碼,走訪整個(gè)串鏈,決定哪一個(gè)filter   function   是
            下一個(gè)呼叫目標(biāo)。如果CallNextHookEx   函式發(fā)現(xiàn)已經(jīng)沒有下一個(gè)filter   function   可以呼叫 (走到串鏈盡頭了),它會(huì)傳回0;否則它就傳回「下一個(gè)filter   function   執(zhí)行後的傳回值」。 

            你可能會(huì)在許多文件(包括SDK   文件)中發(fā)現(xiàn)一個(gè)有關(guān)CallNextHookEx   函式的過氣警告:「如 果nCode   小於0,則hook   函式應(yīng)該不做任何處理,直接將它交給CallNextHookEx   函式,並傳回 CallNextHookEx   函式的回返值」。這並不是真的,而且自Windows   3.0   以來(那時(shí)還在使用舊版的 SetWindowsHook   函式)就已經(jīng)不是真的了!撰寫程式時(shí),你可以完全不理會(huì)這項(xiàng)警告。
            第6章訊息攔截(Hooks) 395

            有些時(shí)候你可能不希望呼叫其他的filter   functions,這種情況下你只要不在你的filter function   中呼叫CallNextHookEx   函式即可。只要不將CallNextHookEx   函式放到你的filter
            function   中,你就不會(huì)呼叫其他的filter   functions,而你也因此可以指定你自己的傳回值。 不幸的是,這裡埋伏著一個(gè)陷阱:另一個(gè)執(zhí)行緒可能也為你安裝了一個(gè)hook,新的filter
            function   於是比你的filter   function   更早被喚起,而它可能不呼叫你的filter   function,完蛋 了!這個(gè)問題沒有一般性的解決方案,如果你先將自己的hook   卸除,然後再重新掛上, 那麼你的filter   function   就成為最新的一個(gè),會(huì)最先被呼叫。沒錯(cuò),但你不能夠保證其他 人不會(huì)依樣畫葫蘆。簡(jiǎn)言之,hooks   是一個(gè)合作機(jī)制,沒有任何保障。

            posted @ 2012-11-05 11:27 王海光 閱讀(566) | 評(píng)論 (0)編輯 收藏
            僅列出標(biāo)題
            共27頁(yè): First 10 11 12 13 14 15 16 17 18 Last 
            91麻精品国产91久久久久 | 久久精品国产精品亚洲人人 | 久久久久亚洲AV无码网站| 99久久综合国产精品免费| 香蕉久久永久视频| 97精品伊人久久久大香线蕉| 亚洲国产天堂久久综合| 国产精品久久久久久久人人看| 日韩久久久久中文字幕人妻| 久久99久久成人免费播放| 精品久久久久久国产三级| 香港aa三级久久三级老师2021国产三级精品三级在 | 久久久久免费精品国产| 精品久久久久久国产91| 久久精品成人国产午夜| 伊人色综合久久| 亚洲精品久久久www| 久久综合视频网| .精品久久久麻豆国产精品| 久久夜色精品国产噜噜噜亚洲AV| 亚洲AV日韩精品久久久久| 久久久久久久久无码精品亚洲日韩 | 久久久久久久久久免免费精品 | 国产一久久香蕉国产线看观看| 国产精自产拍久久久久久蜜| 狠狠综合久久综合中文88| 青青草国产97免久久费观看| 最新久久免费视频| 97精品伊人久久久大香线蕉 | 国产精品久久久久影视不卡| 狠狠精品久久久无码中文字幕| 伊人久久大香线蕉亚洲| 国产一区二区三精品久久久无广告| 亚洲综合伊人久久大杳蕉| 久久久久99精品成人片三人毛片| 久久精品国产亚洲av高清漫画| 欧美日韩成人精品久久久免费看 | 婷婷久久五月天| 国内精品久久久久影院网站| 天天躁日日躁狠狠久久| 免费精品久久久久久中文字幕 |