字 串 9 子曰:「質勝文則野,文勝質則史。 文質彬彬,然後君子。」 《論語﹒雍也第六》 字 串 子曰:「質勝文則野,文勝質則史。 文質彬彬,然後君子。」 《論語﹒雍也第六》 標準的 C++ 提供了方便的程式庫,讓我們能將「字串」視為獨立的單元,以進行各種存取和剪接的處理。
字串 9.1 字串的基本概念 9.2 字串的輸入與輸出 9.3 字串的處理 9.4 字串的指標陣列 9.5 字串處理在編碼上的應用
字串的基本概念 字串 (string) 是由雙引號“ ”所包括起來的一串 文字: “Hello!” “嗨! 您好!” “Good boy.” 字串除了文字部份外,其後又多加了一個空字元 (NULL character),做為字串的結束記號。
字串在記憶體內的儲存方式
字串的宣告方式 字串的資料型態為「char *」 char S1[20] = “Hello, 您好!”; // 陣列式的宣告 char* pS2 = “Hello, 您好!”; // 指標式的宣告,C-style string 字串的資料型態為「char *」
以一維陣列的方式逐一列舉字元定義字串 char S4[10] = {‘\n’, ‘G’, ‘o’, ‘!’ , ‘\0’}; char S3[] = {‘T’, ‘h’, ‘e’, ‘ ’, ‘b’, ‘o’, ‘y’, ‘\0’}; char S4[10] = {‘\n’, ‘G’, ‘o’, ‘!’ , ‘\0’};
以指標的方式定義字串 這個敘述在執行時發生了兩件事情: char* pS2 = “嗨! 您好!”; char* pS = { ‘b’, ‘o’, ‘y’}; // 錯誤! 這個敘述在執行時發生了兩件事情: (1) 在記憶單元內存入字串 “嗨! 您好!”。 (2) 將此字串第一個字元的位址存入指標 pS2裏面。 如下圖所示:
先後儲存兩個字串 char* pS2 = “嗨! 您好!”; pS2 = “Good boy.”;
字元和字串的輸出入相關函數及管道 iostream 標準函數或管道 功 能 cout 輸出資料流 cin 輸入資料流 功 能 cout 輸出資料流 cin 輸入資料流 cin.getline() 字串輸入函數 cin.get() 字元輸入函數
字串的輸出指令 以下各種輸出敘述都得到同的字串: char S1[20] = “Hello,您好!”; char* pS = S1; 以下各種輸出敘述都得到同的字串: cout << S1; cout << pS; cout << &S1[0]; cout << &pS[0]; cout在遇到字串的指標或是字串的起始位址時,會自動將輸出改為字串的內容,而不是將位址輸出。
輸出字串的位址 必需使用下列特殊語法: cout << (void *)S1; cout << (void *)pS;
字串的輸入指令 cin輸入資料流在遇到空隔,或新行符號都會停止。如果要輸入“Hello 您好!”的字串時,必須分兩次擷取: char S1[20], S2[20]; cin >> S1 >> S2; 可以改用函數cin.getline()。它的參數有三個: cin.getline(字串名稱,最大字串長度,結束字元); 其中「結束字元」的預設值是’\n’。 cin.getline(S1, 20); // 輸入字串並存入S1
cin.get()函數 cin.get() 一次只能輸入一個字元: char C1; cin.get(C1); // 輸入字元並存入C1
範例程式BasicString.cpp (1/2) #include <iostream> using namespace std; // ---主程式------------------------ int main() { const int SLength = 20; char S1[SLength] = "Hello, 您好!"; int I[5]={1, 2, 4, 5, 6}; char* pS; int* pI=I; pS=S1; cout << "S1 is: " << S1 << endl; cout << "pS is: " << pS << endl;
範例程式BasicString.cpp (2/2) cout << "I is: " << I << endl; cout << "pI is: " << pI << endl; cout << "*S1 is: " << *S1 << endl; cout << "&S1[0] is: " << &S1[0] << endl; cout << "S1[0] is: " << S1[0] << endl; cout << "(void*)S1[0] is: << (void*)S1[0] << endl; cout << "(void*)S1 is: " << (void*)S1 << endl; cout << "\n請輸入 S1 的新值:\n"; cin.getline(S1,SLength); cout << "輸入新值後, S1 的值為: \n" << S1 << endl; return 0; }
操作結果 S1 is: Hello, 您好! pS is: Hello, 您好! I is: 0012FF1C pI is: 0012FF1C *S1 is: H &S1[0] is: Hello, 您好! S1[0] is: H (void*)S1[0] is: 00000048 (void*)S1 is: 0012FF30 請輸入 S1 的新值: As seen by you. 輸入新值後, S1 的值為:
字串的處理 const Length = 40; char S1[Length] = “Good luck!”; char* pS = S1; 字串S1的第4個字元 (亦即’d’) 可以使用下列四種寫法來存取: S1[3] *(S1+3) pS[3] *(pS+3)
常用的字串處理函數 (需要標頭檔 <cstring>) 函數名稱 功 能 strlen(字串) 求出不包括’\0’的字串長度。 strcpy(字串1,字串 2) 將「字串 2」的內容複製到「字串1」內。 strcat(字串1,字串2) 將「字串 2」銜接到「字串 1」之後。 strcmp(字串1,字串2) 將「字串 1」和「字串 2」作比較。 如果 (字串 1 < 字串 2) 則輸出負整數 如果(字串1 = = 字串 2) 則輸出 0 如果(字串 1 > 字串 2) 則輸出正整數 strchr(字串,字元) 尋找字串中第一個與指定的字元相同處的位址。
範例程式- 檔案 tringProc.cpp (1/3) // StringProc.cpp #include <iomanip> #include <iostream> #include <cstring> using namespace std; // ---主程式------------------------ int main() { const int SLength = 20; char S1[SLength] = "Hello, 您好!"; char S2[SLength] = "Good boy."; char *pS1, *pS2; pS1=S1; pS2=S2;
檔案 tringProc.cpp (2/3) cout << "\n" << "pS1 的值為 : " << pS1 << "\n" << "pS1 的長度為: " << strlen(pS1) << " 字元." << endl; << "S1 的值為 : " << S1 << "\n" << "S1 的長度為: " << strlen(S1) << " 字元." << endl; << "pS2 的值為 : " << pS2 << "\n" << "pS2 的長度為: " << strlen(pS2) << " 字元." << endl;
檔案 tringProc.cpp (3/3) strcat(S1, S2); cout << "執行 strcat(S1, S2); 後," << "S1 的值為: \n" << S1 << endl; cout << "執行 strcmp(S1, S2); 的值為: " << strcmp(S1, S2) << endl; char* p = strchr(S1, 'l'); cout << "第1個 'l' 位於 S1 的第 " << (p - pS1)+1 << " 個字元的位置" << endl; cout << "執行 strchr(S1, 'l'); 的值為: " << strchr(S1, 'l') << endl; strcpy(S1, S2); cout << "執行 strcpy(S1, S2); 後," return 0; }
操作結果 pS1 的值為 : Hello, 您好! pS1 的長度為: 12 字元. S1 的值為 : Hello, 您好! pS2 的值為 : Good boy. pS2 的長度為: 9 字元. 執行 strcat(S1, S2); 後,S1 的值為: Hello, 您好!Good boy. 執行 strcmp(S1, S2); 的值為: 1 第1個 'l' 位於 S1 的第 3 個字元的位置 執行 strchr(S1, 'l'); 的值為: llo, 您好!Good boy. 執行 strcpy(S1, S2); 後, S1 的值為: Good boy.
字串與數字的轉換(conversion between strings and numbers) 標準字串轉換函數 (需要標頭檔 <cstdlib>) 函數名稱 功 能 atoi(字串) 將字串轉成整數,遇到非數字字元時,停止轉換。 atof(字串1,字串 2) 將字串轉double數字,遇到非數字或小數點字元時,停止轉換。 itoa(整數,字串,基底) 將整數轉成以基底為進位數的 ASCII字串。例如基底為 10 表示十進位數字。
範例程式 St2Num.cpp (1/2) 示範了atoi(),atof(),和itoa()共3個函數的用法。 // St2Num.cpp #include <iomanip> #include <iostream> #include <cstdlib> using namespace std; // ---主程式------------------------ int main() { const int SLength = 20; char S1[SLength] = " 320"; char S2[SLength] = " 60.5"; char *pS1, *pS2; int Num = 365;
範例程式 St2Num.cpp (2/2) pS1=S1; pS2=S2; cout << "\n320 + 5 的值為 : " << atoi(pS1)+5 << endl; cout << "\n60.5 + 5 的值為: " << atof(pS2)+5 << endl; itoa(Num, S2, 10); cout << "\nS2 的值 (十進位) 為 : " << S2 << endl; itoa(Num, S2, 16); cout << "\nS2 的值 (十六進位) 為 : 0x" << S2 << endl; itoa(Num, S2, 2); cout << "\nS2 的值 (二進位) 為 : " << S2 << endl; return 0; }
操作結果 320 + 5 的值為 : 325 60.5 + 5 的值為: 65.5 S2 的值 (十進位) 為 : 365 320 + 5 的值為 : 325 60.5 + 5 的值為: 65.5 S2 的值 (十進位) 為 : 365 S2 的值 (十六進位) 為 : 0x16d S2 的值 (二進位) 為 : 101101101
標準字元檢查與轉換函數 (需要標頭檔 <cctype>) 函 數 功 能(假設 ch 是個 char 資料) isalpha(Ch) 判斷 Ch 是否為英文字母 isupper(Ch) 判斷 Ch 是否為大寫英文字母 islower(Ch) 判斷 Ch 是否為小寫英文字母 isdigit(Ch) 判斷 Ch 是否為 0 至 9 的數字 isascii(Ch) 判斷 Ch 是否為 ASCII 字元 isspace(Ch) 判斷 Ch 是否為空白間隔 isprint(Ch) 判斷 Ch 是否為可以印出來或看得見的字元 iscntrl(Ch) 判斷 Ch 是否為控制字元 ispucnt(Ch) 判斷 Ch 是否為標點符號字元 toupper(Ch) 如果 Ch 為小寫,則將其轉為大寫英文字母 tolower(Ch) 如果 Ch 為大寫,則將其轉為小寫英文字母
範例程式 CharConv.cpp (1/2) 示範字元的大小寫轉換和判斷的函數toupper() 和isalpha() 的使用方式 #include <iomanip> #include <iostream> #include <cctype> using namespace std; // ---主程式------------------------ int main() { const int SLength = 60; char S1[SLength], Ch; cout << "請輸入一句英文:" << endl; cin.getline(S1,SLength);
範例程式 CharConv.cpp (1/2) for (int i=0; S1[i]!='\0';i++) S1[i] = toupper(S1[i]); cout << "此句英文轉成大寫後是:\n" << S1 << endl; cout << "請輸入一個字元:" << endl; Ch = cin.get(); if (isalpha (Ch)) cout << "您輸入了一個英文字母" << endl; else cout << "您輸入的不是英文字母" << endl; return 0; }
操作結果 請輸入一句英文: How I love you 此句英文轉成大寫後是: HOW I LOVE YOU! 請輸入一個字元: g 您輸入了一個英文字母
字串的指標陣列 把具有相同特質的一群字串以指標陣列 (pointer array) 來代表: const Number = 3; char* Classmates[Number] = {“丁大丙”, “林昱為”, “丁小雨”}; 使用Classmates[i] 可以取用第i個成員。 cout << “班上同學的名單是:\n”; for (int i=0; i<Number; i++) cout << Classmates[i] << ‘\n’;
範例程式檔案 StringPArray.cpp (1/2) #include <iomanip> #include <iostream> using namespace std; // --- 函數FindSeason()的宣告 --------------- char* FindSeason(int); // --- 主程式 ------------------------------- int main() { int Num; cout << "\n請輸入一個月份 : " << endl; cin >> Num; cout << "\n" << Num << "月是" << FindSeason(Num) << endl; return 0; }
檔案 StringPArray.cpp (1/2) // --- 函數 FindSeason() 的定義 -------------- char* FindSeason(int Month) { int N; char* Seasons[]={"冬季","春季","夏季","秋季"}; if (Month < 1 || Month >12) return "(您輸入的月份沒有意義)"; N =(Month%12)/3; return Seasons[N]; } 操作結果 請輸入一個月份 : 9 9月是秋季
範例程式檔案 EncodeText.cpp (1/3) 將英文字母依對照表轉換後輸出,對於其他不是英文字母的符號則以空白取代。 // EncodeText.cpp #include <iomanip> #include <iostream> #include <cstring> using namespace std; // --- 函數 Encode() 的宣告 ------------------------- void Encode(char* ); // --- 主程式 -------------------------------------- int main() { const MaxLength=40; char InputString[MaxLength]; cout << "Please input your original code:\n"; cin.getline(InputString, MaxLength);
檔案 EncodeText.cpp (2/3) Encode(InputString); cout << "The answer is:\n"; cout << InputString; return 0; } // --- 函數 Encode() 的定義 ------------------------- void Encode(char* String) { char Codes[28]="DOJKZCTMYPAWHUQNBVGSRFXLIE "; char ABC[28] ="ABCDEFGHIJKLMNOPQRSTUVWXYZ "; char abc[28] ="abcdefghijklmnopqrstuvwxyz ";
檔案 EncodeText.cpp (3/3) 操作結果 int i, j, Size = strlen(String); for(i=0; i<Size;i++) { j=0; while (String[i]!=ABC[j] && String[i]!=abc[j] && j<26) j++; String[i]=Codes[j]; } return; 操作結果 Please input your original code: I love you The answer is: Y WQFZ IQR