全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4814
推到 Plurk!
推到 Facebook!

[推薦] AnsiString類別介紹

 
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-08-14 10:19:40 IP:61.218.xxx.xxx 未訂閱

AnsiString類別

1. AnsiString的建構函數 2. AnsiString的指定運算 3. AnsiString的比較運算子 4. AnsiString的其他成員函數

作者:契子 資料來源: http://video.ee.ntu.edu.tw/~howard/bcb/index.html 在C語言中,字串的處理一直是耐人尋味的,那個空結束字元(null-terminated char)一直都是個藝術品,不過也令人頭痛。下面三種型態是常用的字串使用法: char aString[100] ; // 一個字元陣列,100個字元大小。 char *aString ; // 指向字元型態的指標 LPSTR aString ; // 同上,常用在Windows程式上 在C語言中,字串是靠空結束字元(null-terminated char)'\0',來界定的。一個沒有'\0'的字元陣列,是不能當成一個字串來看的。同理,字元指標所指到的字串,在結束的地方也必須要有一個結束字元,否則會一直往下找到結束字元出現為止。字串處理,變成了一件麻煩事,因為結束字元常常是程式問題的所在。實在不敢想像,把一個沒有結束字元的指標當成字串來處理,那會是什麼後果。 在C語言的標準函數庫(standard library)裡,有一籮筐處理字串的函數,例如strlen()、strcpy()、strcmp()、strchr()等,它們的原型宣告放在這個標頭檔。它們也都是使用字元指標做為它們的參數,萬一使用者忽略了結束字元的處理,後果可想而知了。有沒有更好的辦法?答案是有的,那就是AnsiString這個類別。 AnsiString是C Builder從Object Pascal(Delphi使用的母語)抄過來的類別,專門處理在VCL中所有字串的處理,原因是好用的不得了。事實上,C 的類別庫裡也有專門處理字串的類別─String類別,不過為了VCL相容性考慮,C Builder還是採用了與Object Pascal相容的AnsiString類別。 使用AnsiString類別 AnsiString的原型宣告是放在dstring.h這個標頭檔,我們可以在..\Include\VCL\這個目錄找到dstring.h。你應該花點時間研究一下這個檔案的內容,這樣會對AnsiString的了解很有幫助。 AnsiString的建構函數 AnsiString封裝了一組十分完整的建構函數,底下是這些建構函數的原型:
        __fastcall AnsiString() : Data(0) { } 
        __fastcall AnsiString(const char* src) ;
        __fastcall AnsiString(const AnsiString& src) ;
        __fastcall AnsiString(const char* src, unsigned char len) ;
        __fastcall AnsiString(const wchar_t* src) ;
        __fastcall AnsiString(char src) ;
        __fastcall AnsiString(int src) ;
        __fastcall Anstring(double src) ;
我們可以看到倒數兩個建構函數,把整數和浮點數(double)也封裝進來,表示我們可以直接把數值資料轉成字串,例如下面這一段程式碼:
        // ……
        int nNum = 543 ;
        AnsiString sNum(nNum) ;
        AnsiString sConstStr(“ sNum is a real string : ”) ;
        cout << sConstStr.c_str() << sNum.c_str()  << endl ;
        // ……
程式的第二行,讀入整數資料並以字串型態存在sNum這個AnsiString物件中,接著則是一個字串常數的讀取。c_str()是AnsiString()的一個成員函數,傳回值是一個字元指標,也就是傳統的C字串,底下是c_str()函數原型:
        char* __fastcall c_str( ) const ;
在C Builder中,VCL所用的字串型態都是AnsiString,所以通常初始化一個AnsiString的物件之後,就可以直接使用,比方說: //… AnsiString sCaption(“Hello, C Builder”) ; Form1->Caption = sCaption ; //… AnsiString的指定運算(Assignment) 為了增加處理的能力,這個類別也把指定運算重新打造過了(overloading),下面是指定運算的函數原型:
        AnsiString& __fastcall operator =(const AnsiString& rhs) ;
        AnsiString& __fastcall operator  =(const AnsiString& rhs) ;
指定運算現在可強悍多了,這當然是與建構函數通力合作的成果。
        //…
        Form1->Caption = 123 ;         // 直接把數值資料指定給AnsiString
        Form1->Caption  = “木頭人”        ;        // Caption現在變成了“123木頭人”
        //…
AnsiString的比較運算子(Comparison Operators) 常常我們會用到字串的比對,比方說密碼比對、身分證號碼比對等等,另外我們可能也會需要字串比較運算來做資料的排序,AnsiString也有一組比較運算子,幫你簡單地完成字串比較。底下是AnsiString比較運算子的函數原型:
            bool __fastcall operator ==(const AnsiString& rhs) const;
        bool __fastcall operator !=(const AnsiString& rhs) const;
        bool __fastcall operator <(const AnsiString& rhs) const;
        bool __fastcall operator >(const AnsiString& rhs) const;
        bool __fastcall operator <=(const AnsiString& rhs) const;
        bool __fastcall operator >=(const AnsiString& rhs) const;
        int __fastcall AnsiCompare(const AnsiString& rhs) const;
        int __fastcall AnsiCompareIC(const AnsiString& rhs) const;  //ignorecase 
字串大小的判定是由英文字母順序來決定的,例如:"apple"會大於"orange",而"cat"會大於"cow"。如此一來,字串的比對就再簡單不過了。
            //…
        const char* password = “C   Builder is Excellent”;
        cout << “Hello! Please input password” << endl ;
        AnsiString inPassword ;
        cin >> inPassword ;
        if  (inPassword == password) 
                cout << “WelCome to C   Builder”  << endl ;
        else 
        {
                cout << “You are not allowed to enter” << endl ;
                exit(0) ;
        }
        //…
另外,字串的排序也可以很容易來完成。
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // List2.2 sort.cpp
        //---------------------------------------------------------------------------
        #include 
        #include 
        #include 
        #include 
        #include 
        #include             #pragma hdrstop
        //---------------------------------------------------------------------------
        USERES("sort.res");
        //---------------------------------------------------------------------------
        int main(int argc, char **argv)
        {
                const int NUM = 10 ;
                const char* fruit[NUM] = { "howard", "joe", "bach", "pony", "betty", "cth", "syma", "sor", "han", "lsf" } ;
        
                AnsiString sorted[NUM] ;                    // initialize
                for (int index=0 ; index    我們使用了一個很簡單的排序演算法─Selection Sort來排列字串的順序,當然你可以使用更有效率的排序演算法,如Quict Sort,不過,這並不是我們討論的重點。我們可以看到,AnsiString類別把比較運算子重新overloading,讓我們在字串的比對、比較的用途上更加的直覺與方便。感受到它的威力了嗎?你還可以在CDROM上,找到更多的相關資料與範例喔!    AnsiString的其他成員函數    在C   Builder的線上輔助說明(On Line Help),你可以找到更詳細的成員函數的說明,如果你願意而且也有興趣的話,也可以直接去研究在 ..\Source\VCL\這個目錄下的dstring.cpp,這是整個AnsiString類別的實作。不過,基於物件封裝性,你大可以不必理會AnsiString類別是如何實作的,只要把成員函數掌握的一清二楚就夠了。就算你想要自己打造一個處理字串的類別,那也別忘了繼承這個法寶,藉由繼承AnsiString類別,你也可以做出一個具有個人風味而且功能強大的string類別。    底下列出了一些常見的AnsiString成員函數:
            char* __fastcall c_str() const ;
        int __fastcall Length() const ;
        friend AsiString __fastcall operator  (const char* lhs, const AnsiString& rhs) ;
        AnsiString __fastcall operator  (const AnsiString& rhs) const ;
        int __fastcall Pos(const AnsiString& subStr) const ;
        void __fastcall SetLength(int newLength);
        static AnsiString __fastcall StringOfChar(char ch, int count) ;
        AnsiString __fastcall SubString(int index, int count) const;
        AnsiString __fastcall UpperCase() const ;
        AnsiString __fastcall LowerCase() const ;
        bool __fastcall IsDelimiter(const AnsiString& delimiters, int index) const;
        int __fastcall LastDelimiter(const AnsiString& delimiters) const;
上面的這幾個成員函數都是與字串處理相關的,比方說c_str()就是把AnsiString物件的字串成員轉成一般的字元指標輸出,又譬如兩個多載後的” ”號運算子,可以把兩個字串連接起來;另外Length()可以把字串的長度讀出;SetLength() 可以重新設定字串長度,也就是說切掉字串的片斷;而SubString()則可以取出字串的部份出來,形成一個新的字串;UpperCase()、LowerCase()則是對字串轉換大小寫。底下這個範例,在一般需要檔案處理的地方,很常會用得到,主要是用來分離出一個檔案的路徑名稱(PathName)與檔案名稱(FileName):
            ///////////////////////////////////////////////////////////////////////////////////////////////
        / List2.3 path1.cpp
        //---------------------------------------------------------------------------
        #include 
        #include 
        #include 
        #include 
        #include 
        #include             #pragma hdrstop
        //---------------------------------------------------------------------------
        USERES("path1.res");
        //---------------------------------------------------------------------------
        int main(int argc, char **argv)
        {
                AnsiString FullName = "C:\\Program Files\\Projects\\Cbuilder\\myprog.cpp" ;
                int bkPos = FullName.LastDelimiter("\\") ;
                int strLength = FullName.Length() ;
                AnsiString PathName = FullName.SubString(0, bkPos) ;
                AnsiString FileName = FullName.SubString(bkPos 1, strLength-bkPos) ;
                AnsiString desFullName = PathName   FileName ;
                cout << PathName.c_str() << endl ;
                cout << FileName.c_str() << endl ;
                cout << FullName.c_str() << endl ;
                cout << desFullName.c_str() << endl ;                    getch() ;
                return 0;
        }
        //---------------------------------------------------------------------------
這個程式片段的執行結果如下:
            C:\Program Files\Projects\Cbuilder\
        myprog.cpp
        C:\Program Files\Projects\Cbuilder\myprog.cpp
        C:\Program Files\Projects\Cbuilder\myprog.cpp
如果你考慮程式的效率,也可以使用傳統的C字串處理方式:
            ////////////////////////////////////////////////////////////////////////////////////////////////////////
        // List2.3 Path2.cpp
        ////////////////////////////////////////////////////////////////////////////////////////////////////////
        #include 
        #include 
        #include             int main()
        {                    const char *fullname = "C:\\Program Files\\Projects\\Cbuilder\\myprog.cpp" ;
                char pathname[80], filename[20] ;
                int i, len;
                len = strlen(fullname);
                for(i = len - 1; i >= 0; i--)
                {
                        if(fullname[i] == '\\')        break;
                }                    strncpy(pathname, fullname, i   1);
                pathname[i   1] = 0;
                strcpy(filename, fullname   i   1)
                cout << "FullName--> " << fullname << endl ;
                cout << "PathName--> " << pathname << endl ;
                cout << "FileName--> " << filename << endl ;                    getch() ;
                return 0 ;
        }    
時間就是金錢---[ 發問前請先找找舊文章]
系統時間:2024-03-29 17:09:31
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!