500 likes | 624 Views
第 九 章. 字串 (String) 及其函數. 大綱. 字串與字元陣列 固定長字串 — 字元陣列之宣告 指標字串之宣告 字串陣列 字串之輸出 字串之輸入 字串函數. 9-1 字串 (String). 字串 是一串儲存在 連續記憶體 之字元集合,相當於 字元陣列 ,每一個陣列元素儲存一個字元。 字串之表示方式在輸出上皆以 雙引號 圍起 ,如: “ Please say you love me.” 字串需有一結束符號加在字串尾,該結束符號為
E N D
第九章 字串(String)及其函數
大綱 • 字串與字元陣列 • 固定長字串—字元陣列之宣告 • 指標字串之宣告 • 字串陣列 • 字串之輸出 • 字串之輸入 • 字串函數
9-1字串(String) • 字串是一串儲存在連續記憶體之字元集合,相當於字元陣列,每一個陣列元素儲存一個字元。 • 字串之表示方式在輸出上皆以雙引號圍起,如: “Please say you love me.” • 字串需有一結束符號加在字串尾,該結束符號為 字元 ’\0’,即NULL,使用NULL不必用單引號,NULL在C++內為一個內定常數值。
字元陣列 • 字元陣列與一般資料型態陣列相同,處理資料仍是一個一個字元,如: • char st[5]; • 設定資料給各元素之方式為st[0]='A';st[1]='B';…. • 給以初值或常數之方式為: • char st[5]={'A', 'B', 'C', 'D', 'E'}; • 輸出入也需以陣列加註標值為之,如輸出: • for (n=0;n<5;n++) • cout << st[n]; • 輸入為: • for (n=0;n<5;n++) • cin >> st[n];
字串之尾「\0」 • 設字元陣列常數之宣告: • char ch[5]={'A', 'B', 'C', 'D', 'E'}; • 若多加一NULL字元或「\0」,就變成字串。 • char ch[6]= 'A', 'B', 'C', 'D', 'E', '\0'}; • 輸出入方式除了可用陣列方式之外,可使用簡便方法,如: • cout << ch;及 cin >> ch; • 字元陣列後加上一個結束符號「\0」或NULL就是字串,「\0」或NULL稱為空字元,它是ASCII內第一個字元,其內碼為「0」,基本上其操作與字元陣列相同。 • 宣告為字元陣列,而沒設初始值或設定初值但有一空字元則都是字串。
字串之宣告 • 字串之宣告:字元陣列方式,指標方式來宣告,如下: • 字元陣列: • char str[20];字串最長為19個字元。 • 字串指標宣告: • char *s;需配置記憶體,字串最長為配置數減1。
字串陣列 • 字串之陣列宣告如下: • 字串陣列: • char str[4][20];有4列字串,每列最長19個字元。 • 字串指標陣列: • char *s[4];有4列字串,每列最長為配置數減1。
字串常數 • 字串在使用上可須事先設定初值 • 字元陣列後加結束符號NULL • char str[6]={‘A’,’B’,’C’,D’,’E’,NULL}; • 字元陣列後加結束符號’\0’ • char str[6]={‘A’,’B’,’C’,D’,’E’,’\0’}; • 字串常數,自動加上結束符號’\0’ • char str[ ]=”ABCDE”; 長度為6 • 字串指標常數,自動加上結束符號’\0’ • char *str=”ABCDE”;長度為6
宣告字串與字元陣列之不同有: • 字串需有結束符號,字元陣列不必。 • 字串可用陣列、指標表示。 • 字串常數值需用雙引號,表示上比陣列設定初值簡便。 • 以陣列表示字串時之長度須比字元陣列多1。 • 字串之輸出當cout遇到結束符號就結束。 • 佔用記憶體之差異。 • 字串常數在使用上為固定大小,如陣列無彈性。
char ch[5]={‘A’,’B’,’C’,’D’,’E’}; ch ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ch[0] ch[1] ch[2] ch[3] ch[4] char str[6]= {‘A’,’B’,’C’,’D’,’E’,NULL}; char str[6]= {‘A’,’B’,’C’,’D’,’E’,’\0’}; str ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ NULL str ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ‘\0’ char str[ ]=”ABCDE”; str ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ‘\0’ 字串(str)與字元(ch)陣列
例題:字元陣列與字串之常數設定 cout <<"字串輸出st[N+1]=" << st << endl; cout <<"字串輸出str[ ]=" << str << endl; cout <<"字串輸出*string=" << string << endl; return 0; } #include <iostream> //cout using namespace std; const int N=5; int main( ){ int i; char s[N]={'A','B','C','D','E'}; char st[N+1]={'A','B','C','D','E','\0'}; char str[ ]=”ABCDE”: char *string=”ABCDE”; cout<<"字元陣列輸出s[N]="; for (i=0;i<N;i++) cout << s[i]; cout << endl; 字元陣列輸出s[N]=ABCDE 字串輸出st[N+1]=ABCDE 字串輸出str[]=ABCDE 字串輸出*string=ABCDE
例題:以字元陣列方式輸出字串 #include <iostream> //cout using namespace std; int main( ){ unsigned int i; char str[ ]="Sun Moon Lake"; char *string="Great Wall"; cout<<"以字元陣列輸出字串:\n"; cout <<"str[ ]="; for (i=0;i<strlen(str);i++) cout << str[i]; cout << endl; cout <<"*string="; i=0; while (string[i] != ’\0’) //判斷’\0’是否到結尾 cout << string[i++]; cout << endl; return 0; } 以字元陣列輸出字串: str[]=Sun Moon Lake *string=Great Wall
9-2 固定長字串—字元陣列之宣告 • 字元陣列就是字串,只要所輸入之字串不超過陣列大小減1就可使字串運作順利,如: • char s[20]; • 當字串之輸入輸出為: • cin >> s; • cout << s;
例題:以字元陣列方式輸出入字串 #include <iostream> //cout using namespace std; int main( ){ char st[20]; cout <<"輸入字串:"; cin >> st; //按空白鍵或輸入鍵即結束(不能輸入空格) cout << "直接輸出字串為:"<< st; return 0; } 輸入字串:Sun Moon Lake 直接輸出字串為:Sun
9-3 指標字串之宣告 • 字串與指標是相連的,可說字串是指標的應用,因字串之可變長度會影響對記憶體的需求,因此利用指標動態的觀念可使不用的資源釋放出來,提高資源之使用率,為達此目的,需配合new(配置記憶體)與delete(釋放記憶體)之使用。 • char *string; • string = new char[n]; //配置n bytes 記憶體 • delete [ ] string; //資源回收 • char *string = new char[n]; • delete [ ] string;
例題:以動態指標配置記憶體大小以儲存字串。例題:以動態指標配置記憶體大小以儲存字串。 cout <<“輸入所需字串長度值:"; cin >> n; string = new char[n+1]; cout << "再輸入最長" << n <<"字元之字串:"; cin >> string; cout<<"該字串為:" <<string<<endl; delete[ ] string; return 0; } #include <iostream> //cout using namespace std; const short N=16; int main( ){ unsigned int n; char *string; string = new char[N]; cout << "輸入最長“ << (N-1) <<"字元之字串:"; cin >> string; cout<<"該字串為:" <<string<<endl; delete[ ] string;
9-4字串陣列 • 字元二維陣列:以字元二維陣列來儲存字串會浪費許多空間,因字元二維陣列之大小是固定的。 • char s[4][6]; // 佔用4×6=24 bytes • 指標陣列:彈性空間 • char *s[4]
0 1 2 3 4 5 0 ‘B’ ‘l’ ‘a’ ‘c’ ‘k’ ‘\0’ 1 ‘W’ ‘h’ ‘i’ ‘t’ ‘e’ ‘\0’ 2 ‘R’ ‘e’ ‘d’ ‘\0’ 3 ‘G’ ‘r’ ‘e’ ‘e’ ‘n’ ‘\0’ 字串陣列 • 字元二維陣列: • char s[4][6]={“Black”, ”White”, ”Red”, ”Green”}; • 佔用24 Bytes
0 1 2 3 4 5 0 ‘B’ ‘l’ ‘a’ ‘c’ ‘k’ ‘\0’ 1 ‘W’ ‘h’ ‘i’ ‘t’ ‘e’ ‘\0’ 2 ‘R’ ‘e’ ‘d’ ‘\0’ 3 ‘G’ ‘r’ ‘e’ ‘e’ ‘n’ ‘\0’ 字串陣列 • 指標陣列: • char *s[4]={“Black”, ”White”, ”Red”, ”Green”}; • 佔用22 Bytes • char *s[ ]={“Black”, ”White”, ”Red”, ”Green”};
9-5字串之輸出 • 字串之輸出與其它輸出相同,最簡單的為使用物件cout,並配合cout內之成員函數put()與write() • cout之直接輸出; cout << 字串; • cout.put()之輸出 • cout.write()之輸出
字串之輸出 • cout.put()函數是字元之輸出,其意是將字元送到cout後再輸出,其語法如下: • cout.put(char ch); • 參數內為字元變數,在輸出字串時須以陣列方式來輸出各元素,例如: cout.put(string[i++]); • cout.write()函數此成員函數之輸出並不因碰到字串之結束字元’\0’而結束,功用為輸出字串前n個字元,若前n個字元有多個’\0’仍照常輸出,其語法如下: • cout.write(char *ch, int n);
例題:以字元方式輸出字串 #include <iostream> //cout using namespace std; int main( ){ unsigned int i=0; char *string="President of Taiwan"; while (string[i]!='\0') cout.put(string[i++]); //字元變數 char ch='\n'; cout.put(ch); cout<<"Next line\n"; return 0; } President of Taiwan Next line
例題:以write方式輸出字串 #include <iostream> //cout using namespace std; int main( ){ char *string; string = new char[21]; cout << "日月潭英文名為:"; cin.getline(string,21); //可輸入含空白之字串 string[3]='\0'; cout << string<<endl; //輸出遇到'\0'就停止 cout.write(string,21); //不因'\0'而停止 return 0; } 日月潭英文名為:Sun Moon Lake Sun Sun Moon Lake
9-6 字串之輸入 • cin之直接輸入 • cin.getline()之輸入 • cin.get()之輸入 • 數字與字串混合輸入
字串之輸入 • cin:字串在輸入時最簡單的方式為使用cin輸入物件,但因cin只要遇到空白(Space)、定位鍵(Tab)與輸入鍵(Enter)就會結束輸入,並自動在字串結尾加入NULL (‘\0’),若字串本身包含空白在內,如字串”This is a book.”句子,要輸入給字串變數,cin最多只取得字串”This”,其餘將被捨去。 • cin.getline():此函數在讀資料時只有在輸入字串後遇到Enter鍵(‘\n’)才取得資料交給字串變數,並捨去’\n’後在字串尾加上’\0’。 • 以getline來輸入20個字元之字串之敘述為: • cin.getline(name,21); • 此敘述會將整行字串放入name內,但輸入字元需小於21。
例題: cin之直接輸入後輸出 #include <iostream> //cout using namespace std; const int SIZE=21; int main( ){ char name[SIZE],sport[SIZE]; cout <<"輸入姓名:"; cin >> name; cout <<"喜好運動名:"; cin >> sport; cout <<"\n"<< name <<" ,你的運動"<<sport<<"我也很喜歡\n"; return 0; } 輸入姓名:Bill Gates 喜好運動名: Bill ,你的運動Gates我也很喜歡
例題: getline()輸入後輸出 #include <iostream> //cout using namespace std; const int SIZE=21; int main( ){ char name[SIZE],sport[SIZE]; cout <<"輸入姓名:"; cin.getline(name,SIZE); cout <<"喜好運動名:"; cin.getline(sport,SIZE); cout <<"\n"<< name <<" ,你的運動"<<sport<<"我也很喜歡\n"; return 0; } 輸入姓名:Bill Gates 喜好運動名:Golf Bill Gates,你的運動Golf我也很喜歡
cin.get() 輸入 • cin.get(char ch, int len); • 讀取字串時若碰到輸入鍵(‘\n’)就結束,並將NULL加在字串後,字串最長為len。 • ‘\n’在輸入串列內(及輸入緩衝區)不處理。 • 數字與字串輸入時常常會讀不到資料,正如用連續兩個輸入函數cin.get(name,SIZE)與cin.get(sport,SIZE)一樣,第二個將只讀到’\n’就結束了。
例題:以cin.get()輸入後輸出 #include <iostream> //cout using namespace std; const int SIZE=21; int main( ){ char name[SIZE],sport[SIZE]; cout <<"輸入姓名:"; cin.get(name,SIZE); cout <<"喜好運動名:"; cin.get(sport,SIZE); cout <<"\n"<< name <<" ,你的運動“<<sport<<"我也很喜歡\n"; return 0; } 輸入姓名:Bill Gates 喜好運動名: Bill Gates,你的運動我也很喜歡 運動名sport無法輸入Why?
第一字串 輸入鍵 Bill Gates ‘\n’ 讀入name內並加入’\0’ 讀入sport並加入’\0’ ‘\n’仍留在輸入串列內 運動名sport無法輸入Why? • 原因乃在讀取姓名後輸入鍵(Enter)(‘\n’)保留在輸入串列內,因此下一輸入cin.get(sport,20)就讀到’\n’,造成sport得到一NULL字元而已,圖示如下:
解決cin.get()讀取資料時留住’\n’在輸入緩衝區之困擾解決cin.get()讀取資料時留住’\n’在輸入緩衝區之困擾 • 利用無參數之cin.get();在接下來讀取’\n’,因無參數之cin.get()之功能乃讀取下一字元,讓輸入緩衝區空無一物後,下一輸入才能正常運作,即: • cin.get(name,SIZE);//讀取Bill Gates • cin.get();//讀取\n • 或將上述兩列合併如下: • cin.get(name,SIZE).get();
例題:以get()參數輸入後輸出 #include <iostream> //cout using namespace std; const int SIZE=21; int main( ){ char name[SIZE],sport[SIZE]; cout <<"輸入姓名:"; cin.get(name,SIZE); cin.get(); //此兩列可合併為cin.get(name,SIZE).get(); cout <<"喜好運動名:"; cin.get(sport,SIZE); cout <<"\n"<< name <<" ,你的運動"<<sport<<"我也很喜歡\n"; return 0; }
第一字串 第二字串 Bill Gates ‘\n’ Golf ‘\n’ get(name,SIZE) get( ); get(sport,SIZE) get( ); 讀入name 讀入sport Bill Gates\0 Golf\0 (續前)讀取資料方式如下圖:
get(name,SIZE)及get() • 由上面使用之函數get(name,SIZE)及get()一個有參數一個沒有參數,而且又可相互搭配使用,可知C++讓你可以在不同的時機下使用不同的函數,而且名稱又相同,像get()函數,一個可處理字串、一個可處理單一字元,此種函數在類別內,稱為函數重載(Function Overloading)。
例題:輸入一英文句子計算其共有幾字元後輸出(cin.get(ch)之應用)例題:輸入一英文句子計算其共有幾字元後輸出(cin.get(ch)之應用) #include <iostream> //cout using namespace std; const int SIZE=21; int main( ){ char sentense[SIZE],ch; int i=0; cout <<"英文句子:"; do{ cin.get(ch); //此列可改為ch=cin.get(); if (ch!='\n') sentense[i++]=ch; else sentense[i]='\0'; }while (ch!='\n' || i==SIZE); cout << "句子 "<< sentense << "有" << i <<"個字元"<< endl; return 0; } 英文句子:This is a book. 句子This is a book. 有15個字元
9-7字串函數 • 善用C++之字串函數可提高程式設計的能力,同時也可增加對處理字串的效率,如字串長度、字串比較、字串拷貝、字串大小寫與字串合併等都有函數協助處理,在使用這些函數時需加入字串標題檔#include <string.h>。 • 字串長度strlen() • 字串比較strcmp()、strncmp() • 字串拷貝strcpy()、stpcpy() • 字串大小寫轉換strupr()、strlwr() • 字串合併strcat()、strncat()
字串長度strlen() • 字串長度strlen() • 語法: size_t strlen(const char *s); • 傳回字串s之字元個數,但不包括NULL(或’\0’)結束字元 char st[ ]="Normal distribution"; //字串 char *s="It is a nice homework"; char str[ ]={'T','A','I','W','A','N','\0'}; cout<<"各字串長度為:\n"; cout <<st<<"= "<<strlen(st)<<" 字元\n"; cout <<s<<"= "<<strlen(s)<<" 字元\n"; cout <<str<<"= "<<strlen(str)<<" 字元\n"; 各字串長度為: Normal distribution=19 字元 It is a nice homework=21 字元 TAIWAN=6 字元
字串比較strcmp()、strncmp() • 資料的比較在資料庫裡或應用程式內佔用相當的比重,如索引檔之建立需依由小到大或由大到小來建立,僅管建立之演算法不同,但資料總須要互相比較,這是非常重要的一件工作,C++提供比較函數供使用。 • int strcmp(const char *s1, const char *s2); • 兩字串s1與s2自第1字元開始作比較,若相等再比較第2字元,依此類推,直到不相等或已到字串結尾,才停止比較 • int strncmp(const char *s1, const char *s2, size_t maxlen); • 比較字串前面maxlen字元長度,若maxlen大於或等於s1,s2之最大長度,其使用方式則與strcmp()相同
若 s1 是... 傳回值為... 小於 s2 < 0 即s1<s2 傳回小於0之值 相等於 s2 == 0 即s1==s2 傳回0之值 大於 s2 > 0 即s1>s2 傳回大於0之值 字串比較結果之傳回值(Return Value)
字串比較大小 #include <iostream> //cout #include <string.h> using namespace std; int main( ){ char *s1="ABC",*s2="ABC";//字串 cout <<s1<<"="<<s2<<" 值為:"; cout << strcmp(s1,s2)<<endl; s1="AB"; cout <<s1<<"<"<<s2<<" 值為:"; cout << strcmp(s1,s2)<<endl; s1="ABC"; s2="AB"; cout <<s1<<">"<<s2<<" 值為:"; cout << strcmp(s1,s2)<<endl; return 0; } ABC=ABC 值為:0 AB<ABC 值為:-1 ABC>AB 值為:1
字串排序,輸入任意字串,由小到大排列後輸出字串排序,輸入任意字串,由小到大排列後輸出 for (j=0;j<i;j++) for (k=0;k<i-j-1;k++) if (strcmp(line[k],line[k+1])>0){ ptr=line[k]; //位址交換 line[k]=line[k+1]; line[k+1]=ptr; } cout <<"排序後結果如下:\n"; for (j=0;j<i;j++) cout <<(j+1)<<":"<<line[j]<<endl; } #include <iostream> #include <string.h> using namespace std; const int SIZE=5; void main( ) { char s[SIZE][SIZE],*line[SIZE],*ptr; int i,j,k; cout <<"請輸入字串(q:結束):\n"; for (i=0;i<SIZE;i++) { cout <<"s["<<i<<"]="; cin.getline(s[i],20); if (strcmp(s[i],“q”)==0) break;//比較字串 line[i]=s[i];}
字串拷貝strcpy()、stpcpy() • C++語言與其它語言如VB、Delphi(Pascal為基礎之視覺化語言)不同之處,乃其處理字串之方式需用到函數,如在VB、Delphi內要將某一字串設定給另一變數可寫為: • To_String = From_String;//VB,但Delphi須將”=”改為”:=” • 或 • To_String = "This is a string. ";//VB • 在C++則不可,須用字串拷貝函數,如: • strcpy(To_String,From_String); • 或 • strcpy(To_String,"This is a string. ");
字串拷貝strcpy()、stpcpy() • 語法 • char *strcpy(char *dest, const char *src); • char *stpcpy(char *dest, const char *src); • 兩函數皆將第二參數src來源(source)字串複製到第一參數dest目的(destination)字串內,拷貝結果在dest內傳回或以函數名稱傳回。 • 如:char string[10]; • char *str1 = "abcdefghi"; • stpcpy(string, str1); //或strcpy(string, str1); • cout<< string; //輸出abcdefghi
拷貝n字串 • char *strncpy(char *dest, const char *src, size_t maxlen); • 本函數自src內拷貝maxlen長度之字元到dest內,拷貝過去可能沒有’\0’字元,因此必需在dest拷貝後在dest尾加入’\0’,才算完成。 • 如:char string[10]; • char *str1 = "abcdefghi"; • strncpy(string, str1, 3); • string[3] = '\0'; • cout<< string; //輸出abc
清除字串可設定第1字元為’\0’ • 要清除字串之內容只要複製空字串即可,或以結尾字元當第一字元 • destination[0]= ' \0 '; • strcpy(destination); • destination[0]=NULL;
字串大小寫轉換strupr()、strlwr() • char *strupr(char *s);//upper • 將參數列字串s轉為大寫字母即(' a '… ' z ')(' A '… ' Z '),非字母不轉換 • char *strlwr(char *s);//lower • 將參數列字串s轉為小寫字母即(' A'… ' Z ') (' a'… ' z '),非字母不轉換
字串合併strcat()、strncat() • 語法: • char *strcat(char *dest, const char *src); • 將第二參數之來源src字串加在第一參數之目的dest字串後面,結果以dest傳回,或以函數傳回指標,字串總長度為strlen(dest)+strlen(src),但在使用上需注意dest有足夠空間在容納src之字串。 • char *strncat(char *dest, const char *src, size_t maxlen); • 將第二參數之來源src加maxlen長之字串在第一參數之目的dest字串後面,並在字串尾自動加上' \0 ',結果以dest傳回,或以函數傳回指標,字串總長度為strlen(dest)+maxlen,同樣亦須注意dest有足夠空間。
將三個字串合併後輸出 #include <iostream> //cout #include <string.h> using namespace std; int main( ) { char *destination; char *R="Republic",*O=" Of ",*C="China"; destination = new char[strlen(R)+strlen(O)+strlen(C)+1]; strcpy(destination, R); strcat(destination, O); strcat(destination, C); cout<<destination << endl; delete[ ] destination; return 0; } Republic Of China
將一字串輸出形成一三角形 #include <iostream> //cout #include <string.h> using namespace std; int main( ){ char *triangle,*R="Republic"; int len; len = strlen(R)+1; triangle = new char[len+1]; for (int i=1;i<len;i++){ triangle[0]='\0'; //清除字串 strncat(triangle,R,i); cout<< triangle << endl; } delete[ ] triangle; return 0; } R Re Rep Repu Repub Republ Republi Republic
第9章作業 • 設三個字串變數First, Mid, Final分別存自己的英文名字 1. 將三個字串合併成Name字串輸出。 2. Name的長度。 3. Name轉成大寫後輸出。