Presentation is loading. Please wait.

Presentation is loading. Please wait.

1/46 物件導向的字串處理 內建的完整類別 string 具有豐富的 成員函數,能以物件導向的語法處 理字串,讓程式設計者免除空間安 排及安插結尾符號等瑣碎的工作。 內建的完整類別 string 具有豐富的 成員函數,能以物件導向的語法處 理字串,讓程式設計者免除空間安 排及安插結尾符號等瑣碎的工作。

Similar presentations


Presentation on theme: "1/46 物件導向的字串處理 內建的完整類別 string 具有豐富的 成員函數,能以物件導向的語法處 理字串,讓程式設計者免除空間安 排及安插結尾符號等瑣碎的工作。 內建的完整類別 string 具有豐富的 成員函數,能以物件導向的語法處 理字串,讓程式設計者免除空間安 排及安插結尾符號等瑣碎的工作。"— Presentation transcript:

1 1/46 物件導向的字串處理 內建的完整類別 string 具有豐富的 成員函數,能以物件導向的語法處 理字串,讓程式設計者免除空間安 排及安插結尾符號等瑣碎的工作。 內建的完整類別 string 具有豐富的 成員函數,能以物件導向的語法處 理字串,讓程式設計者免除空間安 排及安插結尾符號等瑣碎的工作。 22

2 2/46 Chap 22 物件導向的字串處理 22.1 C 風格的字串和物件導向的 string 類別 22.2 String 物件的定義 22.3 字串的更改、清除、剪接與部份複製 22.4 字串之間的比對和比較 22.5 字串物件與 C-style 字串的互換

3 3/46 22.1 C 風格的字串和物件導向的 string 類別 C-style string (C 風格的字串 ) 由資料型態為 char 構成的一維陣列,結尾處加上 ‘\0’ 做為 字串的結束符號。 宣告 C 風格字串的三種方式 char s1[20] = "Hello, 您好 !"; // 陣列式的宣告 char* ps2 = "Hello, 您好 !"; // 指標式的宣告 char s3[10] = {'G', 'o', '!', '\0'}; // 列舉陣列元素式的宣告

4 4/46 使用自動設定字元陣列長度的語法宣 告 C 風格的字串 // 自動設定字元陣列的長度 char s4[] = "Hello, 您好 !"; char s5[] = {'\n', 'G', 'o', '!', '\0'};

5 5/46 物件導向的 string 類別 在 STL (the Standard Template Library) 中定義。 使用前要在程式開頭處加上 #include 以含入標頭檔 ,完成 string 類別的宣 告。 可以動態地配置記憶空間。 有完整的成員函數,提供了許多方便的運算子。

6 6/46 22.2 定義 String 物件 (1/2) string S1; // 定義一個空的 string 物件 S1 string S2, S3, S4; // 同時定義三個空的 string 物件 string S5("A 是 123"); // S5 的容是 "A 是 123" string S51 = "A 是 123"; // S51 的容是 "A 是 123" string S6(S5) ; // 複製 S5 的內容,另造一個新物件 S6

7 7/46 string S61 = S5; // 複製 S5 的內容,另造一個新物件 S61 string S7(s); // S4 的內容由 C-style 字串 s 構成

8 8/46 定義 String 物件 (1/2) string S5("A 是 123"); // S5 的內容是 "A 是 123“ string S8(5, ‘c’); // S8 由 5 個 ‘c’ 字元所構成 string S9(S5, 2); // S9 由 S5[2] 及其後的所有字元 // 構成,亦即 " 是 123"; string S91 (S5, 2, 4); // S91 由 S5[2] 起算,長度為 4 個字元的 // 部份所構成,亦即 " 是 1“ string* pS = new string[2]; // 動態配置了兩個 string 物件, // pS 指向第一個物件的起頭處

9 9/46 使用下標指定 string 物件的元素 S1[0] 代表 string 物件 S1 的第一個字元。 S1[1] 代表 string 物件 S1 的第二個字元。

10 10/46 22.3 字串的更改、清除、剪接與部份 複製 (1/5) ( 假設 S1 和 S2 為兩個先前已定義過的字串 物件 ) : S1[2]='G'; // 將 S1 的第 3 個字元改成 'G' S1.at(2)=‘G’; // 與 S1[2]=‘G’; 相同 S2.insert(2,S1);// 在 S2[2] 前插入字串 S1

11 11/46 字串的更改、清除、剪接與部份複製 (2/5) swap(S1,S2); // 將 S1 和 S2 的內容互相交換 S1.swap(S2); // 將 S1 和 S2 的內容互相交換 S1.resize(3); // 只保留 S1[0] 到 S1[2] 共 3 個字元, // 其餘字元全數清除 S1.resize(5,‘A’); // 如果 S1 原來的字串長度大於 5 , // 只保留前 5 個字元,如果原來的字串長度 // 小於 5 ,則不足之處全補上字元 'A'

12 12/46 字串的更改、清除、剪接與部份複製 (3/5) S2.erase(2); // 清除自 S2[2] 起之後的所有字元 S2.erase(2,3); // 清除從 S2[2] 起共 3 個字元 S2.erase(); // 將 S2 的內容全部清除 S2.erase(2,5); // 將 S2[2] 到 S2[6] 共 5 個字元清除 S2.replace(2,3,S1); // 將 S2[2] 到 S2[4] 共 3 個 // 字元清除並以 S1 取代

13 13/46 字串的更改、清除、剪接與部份複製 (4/5) S2=S1; // S2 的內容與 S1 相同,但兩者為獨立物件 S2.assign(S1); // 與 S2=S1 相同 S2.assign(S1,2,3); // S2 的內容為 S1[2] 到 S1[4] 共 3 個字元 S2=S1.substr(2); // 將 S1[2] 及其後的所有內容存到 S2 中 S2=S1.substr(2,3); // 將 S1[2] 到 S1[4] 共 3 個字元存到 // S2 中,與 S2.assign(S1,2,3) 相同

14 14/46 字串的更改、清除、剪接與部份複製 (5/5) S2.append(S1); // 在 S2 之後串接上 S1 S2.append(S1,2,3); // 在 S2 之後串接上 S1[2] 到 S2[4] // 共 3 個字元 S3=S1+S2; // S3 的內容改為由 S1 和 S2 串接而成 S2+=S1; // 在 S2 之後串接上 S1

15 15/46 使用 begin() 和 end() 兩個指標物件直 接指定 string 物件的起頭和結尾處 // 將 S2[2] 到 S2 倒數第 4 個字元間的內容附加到 S1 之後: S1.append(S2.begin()+2, S2.end()-3); // 將 S2[2] 到 S2 倒數第 4 個字元間的內容清除: S1.erase(S1.begin()+2, S1.end()-3); // 將 S1 的前 3 個字元複製到 S2[2] 至 S2[4] 的位置: S1.copy(S2.begin()+2, 3);

16 16/46 範例程式 ( 字串物件的操作 ) 檔案 ModifyString.cpp // ModifyString.cpp #include using namespace std; int main() { string S1("0123456789"), S2("abcdefghi"); string S3(" 必需 do it"), S4, S5 (" 長度是 123"); string S6(1,'A'), S7(S3,1,3), S8 (S3, 2, 5); cout << "(1) S3 原來的內容是 : " << endl; cout << " " << S3 << endl; cout << " 執行 string S8 (S3, 2, 5); 後 \n" << " S8 = " << S8 << endl; cout << "(2) S1 原來的內容是 : " << endl; cout << " " << S1 << endl; S1.resize(7); cout << " 執行 S1.resize(7); 後 \n " << " S1 = " << S1 << endl; cout << "(3) S5 原來的內容是 : " << endl; cout << " " << S5 << endl; S5='A';

17 17/46 cout << " 執行 S5 ='A'; 後 \n " << " S5 = " << S5 << endl; cout << "(4) S1 原來的內容是 :" << endl; cout << " " << S1 << endl; cout << " S3 原來的內容是 :" << endl; cout << " " << S3 << endl; S3.copy(S1.begin()+2,4); cout << " 執行 S3.copy(S1.begin()+2,4) 後." << endl; cout << " S1 的內容是 :" << endl; cout << " " << S1 << endl; cout << " S3 的內容是 :" << endl; cout << " " << S3 << endl; cout << "(5) S1 原來的內容是 :" << endl; cout << " " << S1 << endl; cout << " S3 原來的內容是 :" << endl; cout << " " << S3 << endl;

18 18/46 S3=S1.substr(2,5); cout << " 執行 S3=S1.substr(2,5); 後." << endl; cout << " S3 的內容是 :" << endl; cout << " " << S3 << endl; cout << "(6) S1 原來的內容是 :" << endl; cout << " " << S1 << endl; S1.erase(1,3); cout << " 執行 S1.erase(1,3); 後." << endl; cout << " S1 的內容是 :" << endl; cout << " " << S1 << endl; cout << "(7) 執行 S4=S1+S3; 後." << endl; S4=S1+S3; cout << " S4 的內容是 :" << endl; cout << " " << S4 << endl; return 0; };

19 19/46 程式執行結果 (1)S3 原來的內容是 : 必需 do it 執行 stringS8 (S3, 2, 5); 後 S8 = 需 do (2)S1 原來的內容是 : 0123456789 執行 S1.resize(7); 後 S1 = 0123456 (3)S5 原來的內容是 : 長度是 123 執行 S5 ='A'; 後 S5 = A

20 20/46 (4)S1 原來的內容是 : 0123456 S3 原來的內容是 : 必需 do it 執行 S3.copy(S1.begin()+2,4) 後. S1 的內容是 : 01 必需 6 S3 的內容是 : 必需 do it (5)S1 原來的內容是 : 01 必需 6 S3 原來的內容是 : 必需 do it 執行 S3=S1.substr(2,5); 後. S3 的內容是 : 必需 6

21 21/46 (6)S1 原來的內容是 : 01 必需 6 執行 S1.erase(1,3); 後. S1 的內容是 : 0 需 6 (7) 執行 S4=S1+S3; 後. S4 的內容是 : 0 需 6 必需 6

22 22/46 22.4 字串之間的比對和比較 (1/2) S1.find(S2); // 在 S1 中尋找 S2 的組成字元所在的位置 S1.find(S2,S3); // 由 S1[3] 開始尋找 // S2 的組成字元所在的位置 S1.find_first_of(S2); // 在 S1 中尋找第一個吻合 // S2 的組成字元所在的位置 S1.find_first_of(S2,3);// 由 S1[3] 開始尋找第一個吻合 // S2 的組成字元所在的位置

23 23/46 字串之間的比對和比較 (2/2) // 在 S1 中尋找第一個不吻合 S2 的組成字元所在的位置 S1.find_first_not_of(S2); // 在 S1 中尋找最後吻合 S2 的組成字元所在的位置 S1.find_last_of(S2); // 在 S1 中尋找最後不吻合 S2 的組成字元所在的位置 ; S1.find_last_not_of(S2);

24 24/46 字串內容的檢查 S1.size(); // 檢查 S1 內的字元數目 S1.length(); // 與 S1.size(); 相同 S1.empty(); // 檢查 S1 是否為空字串,輸出為 // true 或 false

25 25/46 範例程式 檔案 FindSub.cpp 使用 find() 在字串物件 (S1 和 S2) 中尋找吻合另 一個字串物件 (Sub1 和 Sub2) 的位置。 // FindSub.cpp #include using namespace std; int main() { string S1="I do not know it at all."; string S2=" 說真的,我不知道她是否愛我。 "; int Site, Length1, Length2, Count; string Sub1 = "no"; string Sub2 = " 我 "; Length1 = Sub1.size(); Count = 0; Site = 0; cout << " 字串 \"" << Sub1 << "\" 位於字串 \"" << S1 << "\" 的位置在 :" << endl;

26 26/46 while ((Site = S1.find(Sub1,Site)) !=-1) { cout << Site << " "; Site=Site+Length1; Count++; }; cout << "\n 共有 " << Count << " 個 \"" << Sub1 << "\" 在其中." << endl; Length2 = Sub2.size(); Count = 0; Site = 0; cout << " 中文字 \"" << Sub2 << "\" 位於字串 \"" << S2 << "\" 的位置在 :" << endl; while ((Site = S2.find(Sub2,Site)) !=-1) { cout << Site << " "; Site=Site+Length2; Count++; }; cout << "\n 共有 " << Count << " 個 \"" << Sub2 << "\" 在其中." << endl; return 0; }

27 27/46 程式執行結果 (1) 字串 “no" 位於字串 "I do not know it at all." 的位置在 : 5 10 共有 2 個 "no" 在其中. (2) 中文字 " 我 " 位於字串 " 說真的,我不知道她是否愛我。 " 的位置在 : 8 24 共有 2 個 " 我 " 在其中

28 28/46 字串之間的比較 字串由 char 構成,依照 ASSII 碼的編號方式可以比較大小。 字串有兩種比較方式 : (1) 使用重載運算子, (2) 使用成員函數 compare()

29 29/46 使用重載運算子比較字串 S1 = S2+S3; // 將 S2 和 S3 串接合併,存入 S1 S1 += S2; // S1 的尾端串接了 S2 的內容 cout << S1; // 將 S1 透過資料流輸出 cin >> S2; // 透過資料流將資料輸入 S2 內其中 //cin >> S2; 可以寫成 //getline(cin,S2);

30 30/46 使用成員函數 Compare() 指令 S1.compare(S2); 的輸出值有 1 、 0 和 -1 三種: 1 如果 S1 > S2 0 如果 S1 = S2 -1 如果 S1 < S2

31 31/46 範例程式 檔案 StringBubble.cpp 改寫 10.6 節的範例程式 Bubble.cpp ,使用比較大小的 運算子「 > 」將字串依照字典的次序排列。 還運用了 22.3 節介紹的字串成員函數 swap() 代替原來自行定義的樣 版函數 Exchange() 以互相交換字串的內容。

32 32/46 // StringBubble.cpp #include using namespace std; // --- 定義樣版函數 Bubble() ------------------- template void Bubble(T * const V, int N ) { for (int i=0; i<N; i++) for (int j=N-1; j>i; j--) if (V[j]<V[j-1]) swap(V[j],V[j-1]); return; }

33 33/46 // ---- 主程式 --------------------------------- int main() { const int Size = 5; int i; string Students[Size]= {"Nancy","Lulu", "Margaret","Stephanie","Monica"}; cout << "\n 執行 Bubble() 之前, Data 的值是 :" << endl; for (i=0; i<Size; i++) cout << "(" << i+1 << ") " << Students[i] << endl; Bubble(Students, Size); cout << "\n 執行 Bubble() 之後, Data 的值是 :" << endl; for (int i=0; i<Size; i++) cout << "(" << i+1 << ") " << Students[i] << endl; return 0; }

34 34/46 程式執行結果 執行 Bubble() 之前, Data 的值是 : (1) Nancy (2) Lulu (3) Margaret (4) Stephanie (5) Monica 執行 Bubble() 之後, Data 的值是 : (1) Lulu (2) Margaret (3) Monica (4) Nancy (5) Stephanie

35 35/46 使用 C_str() 成員函數將字串物件轉 換為 C-style 字串 使用資料型態為「 const char * 」的指標 pSc , 以代表 C-style 字串: string S1("FileName"); const char* pSc; pSc = S1.c_str(); 這時 pSc 只是指向原先 S1 物件內字元陣列的指標, 並沒有另外複製產生新的字串。

36 36/46 c_str() 的轉換結果屬於資料型態 「 const char * 」 S1.c_str() 無法直接由「 char * 」的指標接收: char* pS2; // pS2 為 「 char * 」的指標 pS2 = S1.c_str(); // 錯誤!

37 37/46 將字串物件的內容複製到字元陣列 char [] string S1("FileName"); char CS[10]; strcpy(CS, S1.c_str());

38 38/46 使用 strcpy() 將 S1 的內容複製到字元 陣列指標「 char * 」 指標所代表的位置必需有夠的空間: stringS1("FileName"); char* pS = new char[S1.length()+1]; strcpy(pS, S1.c_str());

39 39/46 使用 data() 成員函數將字串物件轉換 為 C-style 字串 stringS2("abcdefghi"); const char* pSc; pSc = S2.data(); 這個語法並沒有另外複製產生新的字串。

40 40/46 將 C-style 字串轉換為 string 物件 string S3, S4; char CS2[20] = "Hello! 您好! "; char* pS2 = " 早安! "; S3 = CS2; // 「 = 」在 string 類別中已正確重載過 S4 = pS2; 此時 S3 和 S4 為複製產生的新字串物件。

41 41/46 範例程式 檔案 CString.cpp // CString.cpp #include using namespace std; // --- 主程式 ------------------------ int main() { string S1("012345678"), S2("abcdefghi"), S3, S4; // -----(1)-------------------------- cout << S1.c_str() << endl; char CS[10]; char* pS = new char[S1.length()+1]; 示範和驗證字串物件和 C-style string 之間的轉換。

42 42/46 // -----(2)-------------------------- strcpy(pS, S1.c_str()); cout << pS << endl; // -----(3)-------------------------- strcpy(CS, S1.c_str()); // -----(4)-------------------------- S1.resize(4); cout << pS << endl; const char* pSc; // -----(5)-------------------------- pSc = S1.c_str(); cout << pSc << endl; S1[2]='A'; // -----(6)-------------------------- cout << pSc << endl; // -----(7)-------------------------- pSc = S2.data(); cout << pSc << endl; S2.resize(4);

43 43/46 // -----(8)-------------------------- cout << pSc << endl; char Cs2[20] = "Hello, 您好! "; char* ps2 = "Good morning, 早安! "; // -----(9)-------------------------- S3 = Cs2; S4 = ps2; cout << S3 << S4 << endl; // -----(10)------------------------- Cs2[0]='G'; ps2[0]='A'; cout << S3 << S4 << endl; return 0; }

44 44/46 程式執行結果 (1) S1 原來的內容是 : 012345678 S1.c_str() 可以直接以 cout 輸出 : 012345678 (2) pS 是一個由 strcpy(pS, S1.c_str()) 產生的 C-style string: 012345678 (3) CS 是一個由 strcpy() 複製而來的字串陣列 : 012345678 (4) S1 在此以 S1.resize(4) 更動. pS 是 ( 沒有改變 ): 012345678 (5) pSc = S1.c_str(): pSc 是 : 0123

45 45/46 (6) S1[2] 在此以 S1[2]='A' 更動. pSc 是 : 01A3 (7) S2 原來的內容是 : abcdefghi pSc = S2.data(): pSc 是 : abcdefghi (8) S2 在此以 S2.resize(4) 更動. pSc 是 : abcd (9) 定義 Cs2 和 ps2 經由 S3 = Cs2 後. S3 是 : Hello, 您好! 經由 S4 = ps2 後. S4 是 : Good morning, 早安!

46 46/46 (10)Cs2[0] 和 ps2[0] 在此更動. Cs2 是 : Gello, 您好! ps2 是 : Aood morning, 早安! S3 是 : Hello, 您好! S4 是 : Good morning, 早安!


Download ppt "1/46 物件導向的字串處理 內建的完整類別 string 具有豐富的 成員函數,能以物件導向的語法處 理字串,讓程式設計者免除空間安 排及安插結尾符號等瑣碎的工作。 內建的完整類別 string 具有豐富的 成員函數,能以物件導向的語法處 理字串,讓程式設計者免除空間安 排及安插結尾符號等瑣碎的工作。"

Similar presentations


Ads by Google