1 / 50

第 九 章

第 九 章. 字串 (String) 及其函數. 大綱. 字串與字元陣列 固定長字串 — 字元陣列之宣告 指標字串之宣告 字串陣列 字串之輸出 字串之輸入 字串函數. 9-1 字串 (String). 字串 是一串儲存在 連續記憶體 之字元集合,相當於 字元陣列 ,每一個陣列元素儲存一個字元。 字串之表示方式在輸出上皆以 雙引號 圍起 ,如: “ Please say you love me.” 字串需有一結束符號加在字串尾,該結束符號為

zuri
Download Presentation

第 九 章

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第九章 字串(String)及其函數

  2. 大綱 • 字串與字元陣列 • 固定長字串—字元陣列之宣告 • 指標字串之宣告 • 字串陣列 • 字串之輸出 • 字串之輸入 • 字串函數

  3. 9-1字串(String) • 字串是一串儲存在連續記憶體之字元集合,相當於字元陣列,每一個陣列元素儲存一個字元。 • 字串之表示方式在輸出上皆以雙引號圍起,如: “Please say you love me.” • 字串需有一結束符號加在字串尾,該結束符號為 字元 ’\0’,即NULL,使用NULL不必用單引號,NULL在C++內為一個內定常數值。

  4. 字元陣列 • 字元陣列與一般資料型態陣列相同,處理資料仍是一個一個字元,如: • 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];

  5. 字串之尾「\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」,基本上其操作與字元陣列相同。 • 宣告為字元陣列,而沒設初始值或設定初值但有一空字元則都是字串。

  6. 字串之宣告 • 字串之宣告:字元陣列方式,指標方式來宣告,如下: • 字元陣列: • char str[20];字串最長為19個字元。 • 字串指標宣告: • char *s;需配置記憶體,字串最長為配置數減1。

  7. 字串陣列 • 字串之陣列宣告如下: • 字串陣列: • char str[4][20];有4列字串,每列最長19個字元。 • 字串指標陣列: • char *s[4];有4列字串,每列最長為配置數減1。

  8. 字串常數 • 字串在使用上可須事先設定初值 • 字元陣列後加結束符號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

  9. 宣告字串與字元陣列之不同有: • 字串需有結束符號,字元陣列不必。 • 字串可用陣列、指標表示。 • 字串常數值需用雙引號,表示上比陣列設定初值簡便。 • 以陣列表示字串時之長度須比字元陣列多1。 • 字串之輸出當cout遇到結束符號就結束。 • 佔用記憶體之差異。 • 字串常數在使用上為固定大小,如陣列無彈性。

  10. 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)陣列

  11. 例題:字元陣列與字串之常數設定 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

  12. 例題:以字元陣列方式輸出字串 #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

  13. 9-2 固定長字串—字元陣列之宣告 • 字元陣列就是字串,只要所輸入之字串不超過陣列大小減1就可使字串運作順利,如: • char s[20]; • 當字串之輸入輸出為: • cin >> s; • cout << s;

  14. 例題:以字元陣列方式輸出入字串 #include <iostream> //cout using namespace std; int main( ){ char st[20]; cout <<"輸入字串:"; cin >> st; //按空白鍵或輸入鍵即結束(不能輸入空格) cout << "直接輸出字串為:"<< st; return 0; } 輸入字串:Sun Moon Lake 直接輸出字串為:Sun

  15. 9-3 指標字串之宣告 • 字串與指標是相連的,可說字串是指標的應用,因字串之可變長度會影響對記憶體的需求,因此利用指標動態的觀念可使不用的資源釋放出來,提高資源之使用率,為達此目的,需配合new(配置記憶體)與delete(釋放記憶體)之使用。 • char *string; • string = new char[n]; //配置n bytes 記憶體 • delete [ ] string; //資源回收 • char *string = new char[n]; • delete [ ] string;

  16. 例題:以動態指標配置記憶體大小以儲存字串。例題:以動態指標配置記憶體大小以儲存字串。 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;

  17. 9-4字串陣列 • 字元二維陣列:以字元二維陣列來儲存字串會浪費許多空間,因字元二維陣列之大小是固定的。 • char s[4][6]; // 佔用4×6=24 bytes • 指標陣列:彈性空間 • char *s[4]

  18. 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

  19. 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”};

  20. 9-5字串之輸出 • 字串之輸出與其它輸出相同,最簡單的為使用物件cout,並配合cout內之成員函數put()與write() • cout之直接輸出; cout << 字串; • cout.put()之輸出 • cout.write()之輸出

  21. 字串之輸出 • cout.put()函數是字元之輸出,其意是將字元送到cout後再輸出,其語法如下: • cout.put(char ch); • 參數內為字元變數,在輸出字串時須以陣列方式來輸出各元素,例如: cout.put(string[i++]); • cout.write()函數此成員函數之輸出並不因碰到字串之結束字元’\0’而結束,功用為輸出字串前n個字元,若前n個字元有多個’\0’仍照常輸出,其語法如下: • cout.write(char *ch, int n);

  22. 例題:以字元方式輸出字串 #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

  23. 例題:以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

  24. 9-6 字串之輸入 • cin之直接輸入 • cin.getline()之輸入 • cin.get()之輸入 • 數字與字串混合輸入

  25. 字串之輸入 • 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。

  26. 例題: 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我也很喜歡

  27. 例題: 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我也很喜歡

  28. cin.get() 輸入 • cin.get(char ch, int len); • 讀取字串時若碰到輸入鍵(‘\n’)就結束,並將NULL加在字串後,字串最長為len。 • ‘\n’在輸入串列內(及輸入緩衝區)不處理。 • 數字與字串輸入時常常會讀不到資料,正如用連續兩個輸入函數cin.get(name,SIZE)與cin.get(sport,SIZE)一樣,第二個將只讀到’\n’就結束了。

  29. 例題:以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?

  30. 第一字串 輸入鍵 Bill Gates ‘\n’ 讀入name內並加入’\0’ 讀入sport並加入’\0’ ‘\n’仍留在輸入串列內 運動名sport無法輸入Why? • 原因乃在讀取姓名後輸入鍵(Enter)(‘\n’)保留在輸入串列內,因此下一輸入cin.get(sport,20)就讀到’\n’,造成sport得到一NULL字元而已,圖示如下:

  31. 解決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();

  32. 例題:以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; }

  33. 第一字串 第二字串 Bill Gates ‘\n’ Golf ‘\n’ get(name,SIZE) get( ); get(sport,SIZE) get( ); 讀入name 讀入sport Bill Gates\0 Golf\0 (續前)讀取資料方式如下圖:

  34. get(name,SIZE)及get() • 由上面使用之函數get(name,SIZE)及get()一個有參數一個沒有參數,而且又可相互搭配使用,可知C++讓你可以在不同的時機下使用不同的函數,而且名稱又相同,像get()函數,一個可處理字串、一個可處理單一字元,此種函數在類別內,稱為函數重載(Function Overloading)。

  35. 例題:輸入一英文句子計算其共有幾字元後輸出(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個字元

  36. 9-7字串函數 • 善用C++之字串函數可提高程式設計的能力,同時也可增加對處理字串的效率,如字串長度、字串比較、字串拷貝、字串大小寫與字串合併等都有函數協助處理,在使用這些函數時需加入字串標題檔#include <string.h>。 • 字串長度strlen() • 字串比較strcmp()、strncmp() • 字串拷貝strcpy()、stpcpy() • 字串大小寫轉換strupr()、strlwr() • 字串合併strcat()、strncat()

  37. 字串長度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 字元

  38. 字串比較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()相同

  39. 若 s1 是... 傳回值為... 小於 s2 < 0 即s1<s2 傳回小於0之值 相等於 s2 == 0 即s1==s2 傳回0之值 大於 s2 > 0 即s1>s2 傳回大於0之值 字串比較結果之傳回值(Return Value)

  40. 字串比較大小 #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

  41. 字串排序,輸入任意字串,由小到大排列後輸出字串排序,輸入任意字串,由小到大排列後輸出 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];}

  42. 字串拷貝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. ");

  43. 字串拷貝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

  44. 拷貝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

  45. 清除字串可設定第1字元為’\0’ • 要清除字串之內容只要複製空字串即可,或以結尾字元當第一字元 • destination[0]= ' \0 '; • strcpy(destination); • destination[0]=NULL;

  46. 字串大小寫轉換strupr()、strlwr() • char *strupr(char *s);//upper • 將參數列字串s轉為大寫字母即(' a '… ' z ')(' A '… ' Z '),非字母不轉換 • char *strlwr(char *s);//lower • 將參數列字串s轉為小寫字母即(' A'… ' Z ') (' a'… ' z '),非字母不轉換

  47. 字串合併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有足夠空間。

  48. 將三個字串合併後輸出 #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

  49. 將一字串輸出形成一三角形 #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

  50. 第9章作業 • 設三個字串變數First, Mid, Final分別存自己的英文名字 1. 將三個字串合併成Name字串輸出。 2. Name的長度。 3. Name轉成大寫後輸出。

More Related