2016年7月1日 星期五

[轉]Ansistring 使用



//原文為簡體,下文為繁體。
//--------------------------------------------------------------
//Ansistring 轉 char
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "哈哈";
char *chr = Test.c_str();
}
//--------------------------------------------------------------
//char轉Ansistring
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString str = "Sample";
char chr[MAX_PATH];
strcpy(chr, str.c_str());
}
//--------------------------------------------------------------
//Bool轉AnsiString
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = BoolToStr(CheckBox1->Checked);
}
//--------------------------------------------------------------
//Ansistring轉bool
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "-1";        CheckBox1->Checked = StrToBool(Test);
}
//--------------------------------------------------------------
//int轉ansistring
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i = 123;        AnsiString str = IntToStr(i);
}
//--------------------------------------------------------------
//AnsiString轉double
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "123";        long double d = StrToFloat(Test);
}
//--------------------------------------------------------------
//double轉AnsiString
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
double d = 123.456;        AnsiString str = FloatToStr(d);
}
//--------------------------------------------------------------
//double轉AnsiString並四捨五入
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
long double d = 123.456121212;
AnsiString str = FloatToStrF(d, ffFixed, 5, 4);
//說明FloatTostrF裏5代表從第幾個數位的後一位元開始四捨五入,4代表取4位小數。  
//執行後得到str是123.4600。
}
//--------------------------------------------------------------
//double轉AnsiString使用類似vb的format函數
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
double d = 123.456;
AnsiString str = FormatFloat("000000.00", d);    //得到 000123.45,當然你可以使用"# . , ; E  E- xx"等符號,你自己試試
}
//--------------------------------------------------------------
//AnsiString轉Tclor型
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "0x00FF8080";        TColor Col = StringToColor(Test);
}
//--------------------------------------------------------------
//Tclor轉AnsiString
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TColor Col = 0x00FF8080;        AnsiString str = ColorToString(Col);
}
//--------------------------------------------------------------
//消除AnsiString 中的一部分字串
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";
int First = 3;    // 消除制定開頭      
int Length = 2;    // 消除制定長度    
AnsiString Dstr = Test.Delete(First, Length);  //得到ABEF
}
//--------------------------------------------------------------
//在AnsiString 中插入字串
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";
AnsiString Ins = "12345";    // 插入串      
int Pos = 3;        // 在哪插      
AnsiString Istr = Test.Insert(Ins, Pos); //得到AB12345CDEF
}
//--------------------------------------------------------------
//取得ansi某一位元字元
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";
AnsiString Npos = Test[3];  //得到C
}
//--------------------------------------------------------------
//取得AnsiString裏最後一個字元
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";        char *Lstr = Test.AnsiLastChar();  //得到F
}
//--------------------------------------------------------------
//取出AnsiString字元,這個類似vb的mid函數!
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";
int First = 3;    // 3開始取      
int Length = 2;    // 取2位      
AnsiString Getstr = Test.SubString(First, Length);   //得到CD
}
//--------------------------------------------------------------
//AnsiString的字母比較
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";
AnsiString Sample = "abcdef";
int Result = Test.AnsiCompare(Sample); //返回1,不同!分大小寫。
}
//--------------------------------------------------------------
////代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";
AnsiString Sample = "abcdef";
int Result = Test.AnsiCompareIC(Sample); //返回0,相同!沒有分大小寫,哈哈
}
//--------------------------------------------------------------
//在AnsiString中尋找字元
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";
AnsiString Sample = "E";
int Result = Test.Pos(Sample); //返回5,如果你寫Sample="haha",就返回0,找不到,哈哈
}

//--------------------------------------------------------------
//在AnsiString中找字串,和上一個類似
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCDEF";
AnsiString Sample = "EF";
int Result = Test.Pos(Sample); //返回5,即E字元的位置
}

//--------------------------------------------------------------
//判斷字串長度,類似vb的len
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "拿金幣來";
int Len = Test.Length(); //返回8
}
//--------------------------------------------------------------
//取得字串,類似vb的left
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "小蘋果然看了這篇文章";
AnsiString SLstr = Test.SetLength(6);  //得到"小蘋果"
}
//--------------------------------------------------------------
//檢測雙位元組字串
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString ChkStr = "你好";
int ChkPos = 1;
if (ByteType(ChkStr, ChkPos) == mbSingleByte)
{
Edit1->Text = "0";
}
else
{
Edit1->Text = "1";
}//返回1,如果你寫ChkStr="fxxk",就返回0
}
//--------------------------------------------------------------
//檢測空字串
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "";
bool chk = Test.IsEmpty();
if (chk)
Edit1->Text = "1";//返回1
}
//--------------------------------------------------------------
//全部變小寫vs全部變大寫
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCdef";
AnsiString Lstr = Test.LowerCase();
}    //代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "ABCdef";
AnsiString Ustr = Test.UpperCase();
}
//--------------------------------------------------------------
//類似vb中Trim 的去空格函數
//代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "    ABCDEF    ";
AnsiString TLstr = Test.TrimLeft();
AnsiString TRstr = Test.TrimRight();
AnsiString Tstr = Test.Trim();
}
//--------------------------------------------------------------
//但是,這個處理不了全形的空格
//代碼:
AnsiString __fastcall TForm1::TrimStr(AnsiString Tm, AnsiString LR)
{        // LR ... L:左除去   R:右除去   B:dou除去
int len;    // 左除去    
if (LR == "L" || LR == "B")
{
len = Tm.Length();
while (Tm.SubString(1, 1) == " " || Tm.SubString(1, 2) == " ")
{        // 半形除去    
if (Tm.SubString(1, 1) == " ")
{
Tm = Tm.SubString(2, len);
len = Tm.Length();
}        // 全形除去    
else if (Tm.SubString(1, 2) == " ")
{
Tm = Tm.SubString(3, len);
len = Tm.Length();
}
}
}        // 右除去
if (LR == "R" || LR == "B")
{
len = Tm.Length();
while (Tm.SubString(len, 1) == " " || Tm.SubString(len - 1, 2) == " ")
{        // 半形除去    
if (Tm.SubString(len, 1) == " ")
{
len = Tm.Length();
Tm = Tm.SubString(1, len - 1);
len = Tm.Length();
}        // 全形除去
else if (Tm.SubString(len - 1, 2) == " ")
{
len = Tm.Length();        Tm = Tm.SubString(1, len - 2);        len = Tm.Length();
}
}
}        return Tm;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Test = "  拳腳  ";        AnsiString Ret = TrimStr(Test, "B")
}
//--------------------------------------------------------------
//相同字元重復輸入
////代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Soc = AnsiString::StringOfChar('*', 100);
Edit1->Text = Soc;//顯示100個*
}
//--------------------------------------------------------------
//字串替換
////代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Str = "Borland C   Builder is free";
AnsiString From = "C   Builder";
AnsiString To = "Delphi";
AnsiString Result;
Result = StringReplace(Str, From, To, TReplaceFlags() << rfReplaceAll << rfIgnoreCase);    //<<後是參數,得到Borland Delphi is free
}
//--------------------------------------------------------------
//全形變半形
////代碼:
AnsiString Zen = "1234567890";
int Len = Zen.Length();
char buf[MAX_PATH];
ZeroMemory(buf, sizeof(buf));
LCMapString(GetUserDefaultLCID(), LCMAP_HALFWIDTH, Zen.c_str(), Len, buf, sizeof(buf));
AnsiString Han = AnsiString(buf);
Edit1->Text = Han;

//--------------------------------------------------------------
//半形變全形
////代碼:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Han = "1234567890";
int Len = Han.Length();
char buf[MAX_PATH];
ZeroMemory(buf, sizeof(buf));
LCMapString(GetUserDefaultLCID(), LCMAP_FULLWIDTH, Han.c_str(), Len, buf, sizeof(buf));
AnsiString Zen = AnsiString(buf);
}
AnsiString重載了"[]"運算符,可以將內容當做字元陣列一樣操作,不過和char[]不同的是AnsiString的[]運算符的下標是從1開始的,
和Delphi的String 相容。對於長度不大的AnsiString可以直接使用[]來操作,長度大的時候最好轉換成char*在使用,
因為重載是通過成員函數實現的,增加了系統的調用開銷。
如:
////代碼:
AnsiString  Temp = "這是一個測試的AnsiString";
int Length = Temp.Length();
for (int i = 1; i <= Length; i)
{
if (Temp[i] > 128) {
//........      
//篩選其中的漢字;      
i;
}
else
{
//......非漢字的字元。      
}
}
對於長度小的AnsiString不必要使用c_str()轉換成C的字串來操作。
A
nsiString的構造函數有一下幾種:
////代碼:
__fastcall AnsiString();
__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(int src);
__fastcall AnsiString(double src);
__fastcall AnsiString(char src);
__fastcall AnsiString(short);
__fastcall AnsiString(unsigned short);
__fastcall AnsiString(unsigned int);
__fastcall AnsiString(long);
__fastcall AnsiString(unsigned long);
__fastcall AnsiString(__int64);
__fastcall AnsiString(unsigned __int64);
__fastcall AnsiString(const WideString &src);    第一個是缺省構造函數,就是生命一個AnsiString的時候使用的,比如
////代碼:
AnsiString Str1;    第二個是將字串常量或者字元陣列或者字元指標轉換成AnsiString的構造函數,他是根據C字串的規則進行構造,
即以第一個遇到的'\0'字元作為結束字元的。常見的應用是
////代碼:
AnsiString Str2 = "TestString";    第三個是標準的拷貝構造函數,當執行一個賦值操作的時候實際上就是使用了這個構造函數。
第四個是指定了長度和源的構造函數,他和第二個不同的是,不是以'\0'字元作為結束字元的,而是按照指定的長度為准,
這個構造函數可以突破C語言中字串的限制和不足,可能在實際中更具使用價值,大多數的API返回的都是char*,
但並不一定都是可視的字元,也可能包含了'\0',就可以使用這個構造函數來實現對內容的拷貝,儘管第二個參數是unisgned char類型,
但是實際中使用好像可以突破256的限制,在一定意義上將這個構造函數可以是我們在使用BCB的時候避免使用new來分配char類型的陣列資料
,在一個局部的應用中,使用AnsiString保存臨時的char陣列資料,不需要考慮在什麼異常的情況下需要釋放記憶體,
因為超出作用域的時候,AnsiString是可以自己釋放的。    第五個構造函數可以是的AnsiString可以直接和wchar_t*進行轉換,就是可以直接將w_chart*使用=賦值給AnsiString類型。    第六個是將整型轉換為字串的構造函數,也就是可以直接將一個int類型的值賦給AnsiString,其結果和通過IntToStr賦值一樣的。
如:
////代碼:
int Temp = 46573284;
AnsiString Str3 = IntToStr(Temp);
和 AnsiString Str4 = Temp;    結果是一樣的。    第七個至第十五個和第六個類似,作用也相當。
第十六個是將Windows的WideString轉換為AnsiString的構造函數,也就是可以直接將WideString賦值給AnsiString,
而不需要使用其他的方法或者API進行轉換,功能和AnsiString(wchar_t*)類似。
String和string是不同的,string是標準從c++支援的處理字串的類,在c  裏我們經常這樣使用string
////代碼:
cout<>str;    在使用stl的時候,我們經常需要string,但String沒有提供直接轉換為string的方法,但我們可以這樣:
////代碼:
//---------------------------------------------------------------------------
#pragma hdrstop #include #include #define VCL_IOSTREAM #include
//---------------------------------------------------------------------------
using namespace std;
#pragma argsused
int main(int argc, char* argv[])
{
String str = "hello world";    string ss(str.c_str());    cout << system("pause");    return 0;
}
這時我們可以使用stl的強大能力來處理String了。
混用AnsiString和c_str()的安全問題by nethobo      當你使用返回AnsiString類型變數的函數,當你要寫一個返回AnsiString變數
(不是指標也不是引用)函數時,或者當你使用一個以AnsiString變數為參數的函數,
或者當你整天用VCL控制項傳入傳出AnsiString屬性變數時,當這個AnsiString變數
包含很長一個字串時,你是否有些擔心有些不安?擔心物件的構造與析構,更擔心
的是大字串的複製(分配記憶體、記憶體複製、刪除記憶體)所帶來的效率問題?如果你
是一個完美主義者或者是一個比較負責的程式作者比較關係程式效率的話,我想你一
定在每次使用時都有與我一樣的這種不安的感覺。
另外當你想要對一個AnsiString變數所含的字串進行c的char*裸字串操作時,
你用AnsiString::c_str()獲得char*的指標然後對其進行c字串操作,這時你是否
會擔心你所作的是否會與AnsiString衝突呢,當然前提是你不想一上來就用strcpy
自己作一拷貝(還是效率問題)。      下面我就本人近來幾天編程中發現的問題來探討一下AnsiString的效率問題及
其c_str()的安全問題。      BCB的提供了操作動態字串的類AnsiString的unicode版的WideString,
而且在VCL類中凡用到字串類型時都是使用的AnsiString。但有時用
c的char*裸字串來處理一些問題更方便,尤其是在一些編碼與解碼演算法中。
為此AnsiString提供了c_str()函數以返回其內部的char*指標供使用(WideString
中為c_bstr(),問題類似,以下只以AnsiString和c_str為例)。
首先我們看看第二個問題(它和第一個問題直接相關),看下面的
//代碼:    AnsiString src = "test AnsiString";
AnsiString strTest = src; //拷貝構造
char* cp = strTest.c_str();
cp[0] = 'T';    運行完後,strTest和src的值是什麼呢?結果可能與你所預想的大不相同,兩都的值都
變成了"Test AnsiString"!也就是說cp[0] = 'T'的操作同時改變了兩個AnsiString變數
的值。為什麼會這樣呢,執行時按下Ctrl滑鼠單擊兩個變數名,你會發現它們兩個所指
向內部字串是同一個!也就是說在拷貝構造(賦值也一樣)時並沒有象我們想象的那
樣進行內部字串的複製!好了到現在為至我們至少不用為第一個問題擔心了,沒有了
字串的複製,單單是物件的構造與析構算不了什麼問題了(AnsiString只有一個Data
成員變數)。
然而第二個問題就很嚴重了,再看下面的
//代碼:    AnsiString src = "test AnsiString";
AnsiString strTest = src; //拷貝構造
strTest[1] = 'x';
char* cp = strTest.c_str();
cp[0] = 'T';    運行結果就是我們的預期了,為什麼加了句strTest[1] = 'x'; 就"正常"了呢?很明顯
AnsiString為了我們第一個問題中的效率問題採用了copy on write技術,也就是唯讀
共用,寫時拷貝。這樣只有在物件要改變其內部資料的值時才做一份自己的拷貝然後在
自己的拷貝中進行修改(就種技術在作業系統中被廣泛使用)。同時在物件析構時如果
引用計數大於0,資料也不會被刪除,它保證資料的有效性。這樣返回AnsiString變數的
函數也就沒有嚴重的效率問題了。      到目前為止,已經真象大白了,結論就是我們不用擔心VCL中AnsiString變數傳值的
效率問題,另外即使是傳值得到的AnsiString物件,我們也不能對其內部資料直接進行
修改(否則你的程式的某些功能模組可以會出現第一次運行正常第二次後就亂七八糟),
尤其是在多線程環境下。原因就不必多說了,大不了複製一份了事。    請參考!

沒有留言:

張貼留言