国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
VC知識(shí)庫(kù)文章 - C++字符串完全指引之一

C++字符串完全指引之一 —— Win32 字符編碼


原著:Michael Dunn

翻譯:Chengjie Sun



原文出處:CodeProject:The Complete Guide to C++ Strings, Part I

引言

  毫無(wú)疑問(wèn),我們都看到過(guò)像 TCHAR, std::string, BSTR 等各種各樣的字符串類(lèi)型,還有那些以 _tcs 開(kāi)頭的奇怪的宏。你也許正在盯著顯示器發(fā)愁。本指引將總結(jié)引進(jìn)各種字符類(lèi)型的目的,展示一些簡(jiǎn)單的用法,并告訴您在必要時(shí),如何實(shí)現(xiàn)各種字符串類(lèi)型之間的轉(zhuǎn)換。
  在第一部分,我們將介紹3種字符編碼類(lèi)型。了解各種編碼模式的工作方式是很重要的事情。即使你已經(jīng)知道一個(gè)字符串是一個(gè)字符數(shù)組,你也應(yīng)該閱讀本部分。一旦你了解了這些,你將對(duì)各種字符串類(lèi)型之間的關(guān)系有一個(gè)清楚地了解。
  在第二部分,我們將單獨(dú)講述string類(lèi),怎樣使用它及實(shí)現(xiàn)他們相互之間的轉(zhuǎn)換。

字符基礎(chǔ) -- ASCII, DBCS, Unicode

  所有的 string 類(lèi)都是以C-style字符串為基礎(chǔ)的。C-style 字符串是字符數(shù)組。所以我們先介紹字符類(lèi)型。這里有3種編碼模式對(duì)應(yīng)3種字符類(lèi)型。第一種編碼類(lèi)型是單子節(jié)字符集(single-byte character set or SBCS)。在這種編碼模式下,所有的字符都只用一個(gè)字節(jié)表示。ASCII是SBCS。一個(gè)字節(jié)表示的0用來(lái)標(biāo)志SBCS字符串的結(jié)束。
  第二種編碼模式是多字節(jié)字符集(multi-byte character set or MBCS)。一個(gè)MBCS編碼包含一些一個(gè)字節(jié)長(zhǎng)的字符,而另一些字符大于一個(gè)字節(jié)的長(zhǎng)度。用在Windows里的MBCS包含兩種字符類(lèi)型,單字節(jié)字符(single-byte characters)和雙字節(jié)字符(double-byte characters)。由于Windows里使用的多字節(jié)字符絕大部分是兩個(gè)字節(jié)長(zhǎng),所以MBCS常被用DBCS代替。
  在DBCS編碼模式中,一些特定的值被保留用來(lái)表明他們是雙字節(jié)字符的一部分。例如,在Shift-JIS編碼中(一個(gè)常用的日文編碼模式),0x81-0x9f之間和 0xe0-oxfc之間的值表示"這是一個(gè)雙字節(jié)字符,下一個(gè)子節(jié)是這個(gè)字符的一部分。"這樣的值被稱(chēng)作"leading bytes",他們都大于0x7f。跟隨在一個(gè)leading byte子節(jié)后面的字節(jié)被稱(chēng)作"trail byte"。在DBCS中,trail byte可以是任意非0值。像SBCS一樣,DBCS字符串的結(jié)束標(biāo)志也是一個(gè)單字節(jié)表示的0。
  第三種編碼模式是Unicode。Unicode是一種所有的字符都使用兩個(gè)字節(jié)編碼的編碼模式。Unicode字符有時(shí)也被稱(chēng)作寬字符,因?yàn)樗葐巫庸?jié)字符寬(使用了更多的存儲(chǔ)空間)。注意,Unicode不能被看作MBCS。MBCS的獨(dú)特之處在于它的字符使用不同長(zhǎng)度的字節(jié)編碼。Unicode字符串使用兩個(gè)字節(jié)表示的0作為它的結(jié)束標(biāo)志。
  單字節(jié)字符包含拉丁文字母表,accented characters及ASCII標(biāo)準(zhǔn)和DOS操作系統(tǒng)定義的圖形字符。雙字節(jié)字符被用來(lái)表示東亞及中東的語(yǔ)言。Unicode被用在COM及Windows NT操作系統(tǒng)內(nèi)部。
  你一定已經(jīng)很熟悉單字節(jié)字符。當(dāng)你使用char時(shí),你處理的是單字節(jié)字符。雙字節(jié)字符也用char類(lèi)型來(lái)進(jìn)行操作(這是我們將會(huì)看到的關(guān)于雙子節(jié)字符的很多奇怪的地方之一)。Unicode字符用wchar_t來(lái)表示。Unicode字符和字符串常量用前綴L來(lái)表示。例如:

wchar_t wch = L''1''; // 2 bytes, 0x0031            wchar_t* wsz = L"Hello"; // 12 bytes, 6 wide characters

字符在內(nèi)存中是怎樣存儲(chǔ)的

  單字節(jié)字符串:每個(gè)字符占一個(gè)字節(jié)按順序依次存儲(chǔ),最后以單字節(jié)表示的0結(jié)束。例如。"Bob"的存貯形式如下:

42 6F 62 00
B o b BOS

Unicode的存儲(chǔ)形式,L"Bob"

42 00 6F 00 62 00 00 00
B o b BOS

使用兩個(gè)字節(jié)表示的0來(lái)做結(jié)束標(biāo)志。

  一眼看上去,DBCS 字符串很像 SBCS 字符串,但是我們一會(huì)兒將看到 DBCS 字符串的微妙之處,它使得使用字符串操作函數(shù)和永字符指針遍歷一個(gè)字符串時(shí)會(huì)產(chǎn)生預(yù)料之外的結(jié)果。字符串" " ("nihongo")在內(nèi)存中的存儲(chǔ)形式如下(LB和TB分別用來(lái)表示 leading byte 和 trail byte)

93 FA 96 7B 8C EA 00
LB TB LB TB LB TB EOS
EOS

值得注意的是,"ni"的值不能被解釋成WORD型值0xfa93,而應(yīng)該看作兩個(gè)值93和fa以這種順序被作為"ni"的編碼。

使用字符串處理函數(shù)

  我們都已經(jīng)見(jiàn)過(guò)C語(yǔ)言中的字符串函數(shù),strcpy(), sprintf(), atoll()等。這些字符串只應(yīng)該用來(lái)處理單字節(jié)字符字符串。標(biāo)準(zhǔn)庫(kù)也提供了僅適用于Unicode類(lèi)型字符串的函數(shù),比如wcscpy(), swprintf(), wtol()等。
  微軟還在它的CRT(C runtime library)中增加了操作DBCS字符串的版本。Str***()函數(shù)都有對(duì)應(yīng)名字的DBCS版本_mbs***()。如果你料到可能會(huì)遇到DBCS字符串(如果你的軟件會(huì)被安裝在使用DBCS編碼的國(guó)家,如中國(guó),日本等,你就可能會(huì)),你應(yīng)該使用_mbs***()函數(shù),因?yàn)樗麄円部梢蕴幚鞸BCS字符串。(一個(gè)DBCS字符串也可能含有單字節(jié)字符,這就是為什么_mbs***()函數(shù)也能處理SBCS字符串的原因)
  讓我們來(lái)看一個(gè)典型的字符串來(lái)闡明為什么需要不同版本的字符串處理函數(shù)。我們還是使用前面的Unicode字符串 L"Bob":

42 00 6F 00 62 00 00 00
B o b BOS

  因?yàn)閤86CPU是little-endian,值0x0042在內(nèi)存中的存儲(chǔ)形式是42 00。你能看出如果這個(gè)字符串被傳給strlen()函數(shù)會(huì)出現(xiàn)什么問(wèn)題嗎?它將先看到第一個(gè)字節(jié)42,然后是00,而00是字符串結(jié)束的標(biāo)志,于是strlen()將會(huì)返回1。如果把"Bob"傳給wcslen(),將會(huì)得出更壞的結(jié)果。wcslen()將會(huì)先看到0x6f42,然后是0x0062,然后一直讀到你的緩沖區(qū)的末尾,直到發(fā)現(xiàn)00 00結(jié)束標(biāo)志或者引起了GPF。
  到目前為止,我們已經(jīng)討論了str***()和wcs***()的用法及它們之間的區(qū)別。Str***()和_mbs**()之間的有區(qū)別區(qū)別呢?明白他們之間的區(qū)別,對(duì)于采用正確的方法來(lái)遍歷DBCS字符串是很重要的。下面,我們將先介紹字符串的遍歷,然后回到str***()與_mbs***()之間的區(qū)別這個(gè)問(wèn)題上來(lái)。

正確的遍歷和索引字符串

  因?yàn)槲覀冎写蠖鄶?shù)人都是用著SBCS字符串成長(zhǎng)的,所以我們?cè)诒闅v字符串時(shí),常常使用指針的++-和-操作。我們也使用數(shù)組下標(biāo)的表示形式來(lái)操作字符串中的字符。這兩種方式是用于SBCS和Unicode字符串,因?yàn)樗鼈冎械淖址兄嗤膶挾?,編譯器能正確的返回我們需要的字符。
  然而,當(dāng)碰到DBCS字符串時(shí),我們必須拋棄這些習(xí)慣。這里有使用指針遍歷DBCS字符串時(shí)的兩條規(guī)則。違背了這兩條規(guī)則,你的程序就會(huì)存在DBCS有關(guān)的bugs。

  • 1.在前向遍歷時(shí),不要使用++操作,除非你每次都檢查lead byte;
  • 2.永遠(yuǎn)不要使用-操作進(jìn)行后向遍歷。
  •   我們先來(lái)闡述規(guī)則2,因?yàn)檎业揭粋€(gè)違背它的真實(shí)的實(shí)例代碼是很容易的。假設(shè)你有一個(gè)程序在你自己的目錄里保存了一個(gè)設(shè)置文件,你把安裝目錄保存在注冊(cè)表中。在運(yùn)行時(shí),你從注冊(cè)表中讀取安裝目錄,然后合成配置文件名,接著讀取該文件。假設(shè),你的安裝目錄是C:\Program Files\MyCoolApp,那么你合成的文件名應(yīng)該是C:\Program Files\MyCoolApp\config.bin。當(dāng)你進(jìn)行測(cè)試時(shí),你發(fā)現(xiàn)程序運(yùn)行正常。
      現(xiàn)在,想象你合成文件名的代碼可能是這樣的:

    bool GetConfigFileName ( char* pszName, size_t nBuffSize )            {            char szConfigFilename[MAX_PATH];            // Read install dir from registry... we''ll assume it succeeds.            // Add on a backslash if it wasn''t present in the registry value.            // First, get a pointer to the terminating zero.            char* pLastChar = strchr ( szConfigFilename, ''\0'' );            // Now move it back one character.            pLastChar--;            if ( *pLastChar != ''\\'' )            strcat ( szConfigFilename, "\\" );            // Add on the name of the config file.            strcat ( szConfigFilename, "config.bin" );            // If the caller''s buffer is big enough, return the filename.            if ( strlen ( szConfigFilename ) >= nBuffSize )            return false;            else            {            strcpy ( pszName, szConfigFilename );            return true;            }            }      
      這是一段很健壯的代碼,然而在遇到 DBCS 字符時(shí)它將會(huì)出錯(cuò)。讓我們來(lái)看看為什么。假設(shè)一個(gè)日本用戶(hù)使用了你的程序,把它安裝在 C:\
    。下面是這個(gè)名字在內(nèi)存中的存儲(chǔ)形式:
     
    43 3A 5C 83 88 83 45 83 52 83 5C 00
          LB TB LB TB LB TB LB TB  
    C : \
    EOS

      當(dāng)使用 GetConfigFileName() 檢查尾部的''\\''時(shí),它尋找安裝目錄名中最后的非0字節(jié),看它是等于''\\''的,所以沒(méi)有重新增加一個(gè)''\\''。結(jié)果是代碼返回了錯(cuò)誤的文件名。
      哪里出錯(cuò)了呢?看看上面兩個(gè)被用藍(lán)色高量顯示的字節(jié)。斜杠''\\''的值是0x5c。'' ''的值是83 5c。上面的代碼錯(cuò)誤的讀取了一個(gè) trail byte,把它當(dāng)作了一個(gè)字符。
      正確的后向遍歷方法是使用能夠識(shí)別DBCS字符的函數(shù),使指針移動(dòng)正確的字節(jié)數(shù)。下面是正確的代碼。(指針移動(dòng)的地方用紅色標(biāo)明)

    bool FixedGetConfigFileName ( char* pszName, size_t nBuffSize )            {            char szConfigFilename[MAX_PATH];            // Read install dir from registry... we''ll assume it succeeds.            // Add on a backslash if it wasn''t present in the registry value.            // First, get a pointer to the terminating zero.            char* pLastChar = _mbschr ( szConfigFilename, ''\0'' );            // Now move it back one double-byte character.              pLastChar = CharPrev ( szConfigFilename, pLastChar );            if ( *pLastChar != ''\\'' )            _mbscat ( szConfigFilename, "\\" );            // Add on the name of the config file.            _mbscat ( szConfigFilename, "config.bin" );            // If the caller''s buffer is big enough, return the filename.            if ( _mbslen ( szInstallDir ) >= nBuffSize )            return false;            else            {            _mbscpy ( pszName, szConfigFilename );            return true;            }            }            
      上面的函數(shù)使用CharPrev() API使pLastChar向后移動(dòng)一個(gè)字符,這個(gè)字符可能是兩個(gè)字節(jié)長(zhǎng)。在這個(gè)版本里,if條件正常工作,因?yàn)閘ead byte永遠(yuǎn)不會(huì)等于0x5c。
      讓我們來(lái)想象一個(gè)違背規(guī)則1的場(chǎng)合。例如,你可能要檢測(cè)一個(gè)用戶(hù)輸入的文件名是否多次出現(xiàn)了'':''。如果,你使用++操作來(lái)遍歷字符串,而不是使用CharNext(),你可能會(huì)發(fā)出不正確的錯(cuò)誤警告如果恰巧有一個(gè)trail byte它的值的等于'':''的值。
    與規(guī)則2相關(guān)的關(guān)于字符串索引的規(guī)則:
    2a. 永遠(yuǎn)不要使用減法去得到一個(gè)字符串的索引。

    違背這條規(guī)則的代碼和違背規(guī)則2的代碼很相似。例如,

    char* pLastChar = &szConfigFilename [strlen(szConfigFilename) - 1];

    這和向后移動(dòng)一個(gè)指針是同樣的效果。

    回到關(guān)于str***()和_mbs***()的區(qū)別

      現(xiàn)在,我們應(yīng)該很清楚為什么_mbs***()函數(shù)是必需的。Str***()函數(shù)根本不考慮DBCS字符,而_mbs***()考慮。如果,你調(diào)用strrchr("C:\\ ", ''\\''),返回結(jié)果可能是錯(cuò)誤的,然而_mbsrchr()將會(huì)認(rèn)出最后的雙字節(jié)字符,返回一個(gè)指向真的''\\''的指針。
      關(guān)于字符串函數(shù)的最后一點(diǎn):str***()和_mbs***()函數(shù)認(rèn)為字符串的長(zhǎng)度都是以char來(lái)計(jì)算的。所以,如果一個(gè)字符串包含3個(gè)雙字節(jié)字符,_mbslen()將會(huì)返回6。Unicode函數(shù)返回的長(zhǎng)度是按wchar_t來(lái)計(jì)算的。例如,wcslen(L"Bob")返回3。

    Win32 API中的MBCS和Unicode

    兩組 APIs:
      盡管你也許從來(lái)沒(méi)有注意過(guò),Win32中的每個(gè)與字符串相關(guān)的API和message都有兩個(gè)版本。一個(gè)版本接受MBCS字符串,另一個(gè)接受Unicode字符串。例如,根本沒(méi)有SetWindowText()這個(gè)API,相反,有SetWindowTextA()和SetWindowTextW()。后綴A表明這是MBCS函數(shù),后綴W表示這是Unicode版本的函數(shù)。
      當(dāng)你 build 一個(gè) Windows 程序,你可以選擇是用 MBCS 或者 Unicode APIs。如果,你曾經(jīng)用過(guò)VC向?qū)Р⑶覜](méi)有改過(guò)預(yù)處理的設(shè)置,那表明你用的是MBCS版本。那么,既然沒(méi)有 SetWindowText() API,我們?yōu)槭裁纯梢允褂盟兀縲inuser.h頭文件包含了一些宏,例如:

    BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString );            BOOL WINAPI SetWindowTextW ( HWND hWnd, LPCWSTR lpString );            #ifdef UNICODE            #define SetWindowText  SetWindowTextW            #else            #define SetWindowText  SetWindowTextA            #endif      
    當(dāng)使用MBCS APIs來(lái)build程序時(shí),UNICODE沒(méi)有被定義,所以預(yù)處理器看到:
    #define SetWindowText SetWindowTextA

      這個(gè)宏定義把所有對(duì)SetWindowText的調(diào)用都轉(zhuǎn)換成真正的API函數(shù)SetWindowTextA。(當(dāng)然,你可以直接調(diào)用SetWindowTextA() 或者 SetWindowTextW(),雖然你不必那么做。)
      所以,如果你想把默認(rèn)使用的API函數(shù)變成Unicode版的,你可以在預(yù)處理器設(shè)置中,把_MBCS從預(yù)定義的宏列表中刪除,然后添加UNICODE和_UNICODE。(你需要兩個(gè)都定義,因?yàn)椴煌念^文件可能使用不同的宏。) 然而,如果你用char來(lái)定義你的字符串,你將會(huì)陷入一個(gè)尷尬的境地??紤]下面的代碼:

    HWND hwnd = GetSomeWindowHandle();            char szNewText[] = "we love Bob!";            SetWindowText ( hwnd, szNewText );

    在預(yù)處理器把SetWindowText用SetWindowTextW來(lái)替換后,代碼變成:

    HWND hwnd = GetSomeWindowHandle();            char szNewText[] = "we love Bob!";            SetWindowTextW ( hwnd, szNewText );

      看到問(wèn)題了嗎?我們把單字節(jié)字符串傳給了一個(gè)以Unicode字符串做參數(shù)的函數(shù)。解決這個(gè)問(wèn)題的第一個(gè)方案是使用 #ifdef 來(lái)包含字符串變量的定義:

    HWND hwnd = GetSomeWindowHandle();            #ifdef UNICODE            wchar_t szNewText[] = L"we love Bob!";            #else            char szNewText[] = "we love Bob!";            #endif            SetWindowText ( hwnd, szNewText );

    你可能已經(jīng)感受到了這樣做將會(huì)使你多么的頭疼。完美的解決方案是使用TCHAR.

    使用TCHAR

      TCHAR是一種字符串類(lèi)型,它讓你在以MBCS和UNNICODE來(lái)build程序時(shí)可以使用同樣的代碼,不需要使用繁瑣的宏定義來(lái)包含你的代碼。TCHAR的定義如下:

    #ifdef UNICODE            typedef wchar_t TCHAR;            #else            typedef char TCHAR;            #endif

    所以用MBCS來(lái)build時(shí),TCHAR是char,使用UNICODE時(shí),TCHAR是wchar_t。還有一個(gè)宏來(lái)處理定義Unicode字符串常量時(shí)所需的L前綴。

    #ifdef UNICODE            #define _T(x) L##x            #else            #define _T(x) x            #endif

      ##是一個(gè)預(yù)處理操作符,它可以把兩個(gè)參數(shù)連在一起。如果你的代碼中需要字符串常量,在它前面加上_T宏。如果你使用Unicode來(lái)build,它會(huì)在字符串常量前加上L前綴。

    TCHAR szNewText[] = _T("we love Bob!");

      像是用宏來(lái)隱藏SetWindowTextA/W的細(xì)節(jié)一樣,還有很多可以供你使用的宏來(lái)實(shí)現(xiàn)str***()和_mbs***()等字符串函數(shù)。例如,你可以使用_tcsrchr宏來(lái)替換strrchr()、_mbsrchr()和wcsrchr()。_tcsrchr根據(jù)你預(yù)定義的宏是_MBCS還是UNICODE來(lái)擴(kuò)展成正確的函數(shù),就像SetWindowText所作的一樣。
      不僅str***()函數(shù)有TCHAR宏。其他的函數(shù)如, _stprintf(代替sprinft()和swprintf()),_tfopen(代替fopen()和_wfopen())。 MSDN中"Generic-Text Routine Mappings."標(biāo)題下有完整的宏列表。

    字符串和TCHAR typedefs

      由于Win32 API文檔的函數(shù)列表使用函數(shù)的常用名字(例如,"SetWindowText"),所有的字符串都是用TCHAR來(lái)定義的。(除了XP中引入的只適用于Unicode的API)。下面列出一些常用的typedefs,你可以在msdn中看到他們。

    type Meaning in MBCS builds Meaning in Unicode builds
    WCHAR wchar_t wchar_t
    LPSTR zero-terminated string of char (char*) zero-terminated string of char (char*)
    LPCSTR constant zero-terminated string of char (const char*) constant zero-terminated string of char (const char*)
    LPWSTR zero-terminated Unicode string (wchar_t*) zero-terminated Unicode string (wchar_t*)
    LPCWSTR constant zero-terminated Unicode string (const wchar_t*) constant zero-terminated Unicode string (const wchar_t*)
    TCHAR char wchar_t
    LPTSTR zero-terminated string of TCHAR (TCHAR*) zero-terminated string of TCHAR (TCHAR*)
    LPCTSTR constant zero-terminated string of TCHAR (const TCHAR*) constant zero-terminated string of TCHAR (const TCHAR*)

    何時(shí)使用 TCHAR 和 Unicode

      到現(xiàn)在,你可能會(huì)問(wèn),我們?yōu)槭裁匆褂肬nicode。我已經(jīng)用了很多年的char。下列3種情況下,使用Unicode將會(huì)使你受益:

  • 1.你的程序只運(yùn)行在Windows NT系統(tǒng)中。
  • 2. 你的程序需要處理超過(guò)MAX_PATH個(gè)字符長(zhǎng)的文件名。
  • 3. 你的程序需要使用XP中引入的只有Unicode版本的API.
  •   Windows 9x 中大多數(shù)的 API 沒(méi)有實(shí)現(xiàn) Unicode 版本。所以,如果你的程序要在windows 9x中運(yùn)行,你必須使用MBCS APIs。然而,由于NT系統(tǒng)內(nèi)部都使用Unicode,所以使用Unicode APIs將會(huì)加快你的程序的運(yùn)行速度。每次,你傳遞一個(gè)字符串調(diào)用MBCS API,操作系統(tǒng)會(huì)把這個(gè)字符串轉(zhuǎn)換成Unicode字符串,然后調(diào)用對(duì)應(yīng)的Unicode API。如果一個(gè)字符串被返回,操作系統(tǒng)還要把它轉(zhuǎn)變回去。盡管這個(gè)轉(zhuǎn)換過(guò)程被高度優(yōu)化了,但它對(duì)速度造成的損失是無(wú)法避免的。
      只要你使用Unicode API,NT系統(tǒng)允許使用非常長(zhǎng)的文件名(突破了MAX_PATH的限制,MAX_PATH=260)。使用Unicode API的另一個(gè)優(yōu)點(diǎn)是你的程序會(huì)自動(dòng)處理用戶(hù)輸入的各種語(yǔ)言。所以一個(gè)用戶(hù)可以輸入英文,中文或者日文,而你不需要額外編寫(xiě)代碼去處理它們。
      最后,隨著windows 9x產(chǎn)品的淡出,微軟似乎正在拋棄MBCS APIs。例如,包含兩個(gè)字符串參數(shù)的SetWindowTheme() API只有Unicode版本的。使用Unicode來(lái)build你的程序?qū)?huì)簡(jiǎn)化字符串的處理,你不必在MBCS和Unicdoe之間相互轉(zhuǎn)換。
      即使你現(xiàn)在不使用Unicode來(lái)build你的程序,你也應(yīng)該使用TCHAR及其相關(guān)的宏。這樣做不僅可以的代碼可以很好地處理DBCS,而且如果將來(lái)你想用Unicode來(lái)build你的程序,你只需要改變一下預(yù)處理器中的設(shè)置就可以實(shí)現(xiàn)了。

     

     

     

    作者簡(jiǎn)介
      Michael Dunn:居住在陽(yáng)光城市洛杉磯。他是如此的喜歡這里的天氣以致于想一生都住在這里。他在4年級(jí)時(shí)開(kāi)始編程,那時(shí)用的電腦是Apple //e。1995年,在 UCLA 獲得數(shù)學(xué)學(xué)士學(xué)位,隨后在Symantec 公司做 QA 工程師,在 Norton AntiVirus 組工作。他自學(xué)了 Windows 和 MFC 編程。1999-2000年,他設(shè)計(jì)并實(shí)現(xiàn)了 Norton AntiVirus 的新界面。 
      Michael 現(xiàn)在在 Napster(一個(gè)提供在線(xiàn)訂閱音樂(lè)服務(wù)的公司)做開(kāi)發(fā)工作,他還開(kāi)發(fā)了UltraBar,一個(gè)IE工具欄插件,它可以使網(wǎng)絡(luò)搜索更加容易,給了 googlebar 以沉重打擊;他還開(kāi)發(fā)了 CodeProject SearchBar;與人共同創(chuàng)建了 Zabersoft 公司,該公司在洛杉磯和丹麥的 Odense 都設(shè)有辦事處。
      他喜歡玩游戲。愛(ài)玩的游戲有 pinball, bike riding,偶爾還玩 PS, Dreamcasth 和 MAME 游戲。他因忘了自己曾經(jīng)學(xué)過(guò)的語(yǔ)言:法語(yǔ)、漢語(yǔ)、日語(yǔ)而感到悲哀。
    本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
    打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
    猜你喜歡
    類(lèi)似文章
    《C 字符串完全指南——第一部分:win32 字符編碼》
    windows環(huán)境下unicode編程總結(jié)
    LPSTR、LPCSTR、LPTSTR和LPCTSTR的意義及區(qū)別(轉(zhuǎn))
    VC中unicode項(xiàng)目向多字節(jié)字符集項(xiàng)目移植
    VC++中的char,wchar_t,
    c++字符串完全指引之二 —— 字符串封裝類(lèi) - 悠悠我心
    更多類(lèi)似文章 >>
    生活服務(wù)
    分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
    綁定賬號(hào)成功
    后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
    如果VIP功能使用有故障,
    可點(diǎn)擊這里聯(lián)系客服!

    聯(lián)系客服