1 / 34

Chapter 08

Chapter 08. Pointers and Pointer-Based Strings (Part II). 8.8 指標運算式與指標算式. 指標可做遞增 / 遞減運算 指標可加上一個整數以得到一個新的位址。 除非是使用指標來指向一個陣列,否則指標運算式不具意義的。. 8.8 指標運算式與指標算式. 假設我們宣告一個擁有五個元素的整數陣列 v ,且令一個整數( integer )為 4 個 bytes 令 vPtr 是一個指標,且 vPtr 指向第一個元素 v[0] ,假設其記憶體位址在 3000 vPtr = &v[ 0 ];

buffy-floyd
Download Presentation

Chapter 08

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. Chapter 08 Pointers and Pointer-Based Strings (Part II)

  2. 8.8 指標運算式與指標算式 • 指標可做遞增/遞減運算 • 指標可加上一個整數以得到一個新的位址。 • 除非是使用指標來指向一個陣列,否則指標運算式不具意義的。

  3. 8.8 指標運算式與指標算式 • 假設我們宣告一個擁有五個元素的整數陣列v,且令一個整數(integer)為4個bytes • 令vPtr是一個指標,且vPtr指向第一個元素v[0],假設其記憶體位址在3000 vPtr = &v[ 0 ]; • 「vPtr += 2;」的結果將使得vPtr指向3008 • 因為3000 + 2 * 4=3008,換句話說,vPtr將指向v[ 2 ]的位址。 • 註: • 一個整數到底以幾個bytes表示?這是machine dependent的。意指這是可能隨著平台/作業系統不同而不同。

  4. vPtr = &v[ 0 ]; • vPtr += 2;

  5. 常見的程式設計錯誤8.9 • 如果對一個指向非陣列的指標來做指標運算的話,將有可能會造成邏輯錯誤。 • 錯誤示範: • 如果對一個指向陣列的指標來做指標運算時,注意不要超過陣列範圍。 int x; int *xPtr = &x; xPtr++; cout << *xPtr << endl;

  6. 8.8 指標運算式與指標算式 • 指標的指定 • 指標變數的內容(記憶體位址)可以被指定給另一個同型態的指標變數 • 範例: int x; int *xPtr = &x; int *yPtr = xPtr; double *d = xPtr; //錯誤

  7. 8.10 指標陣列 • 一個指標變數 • char *s = “hello”; • s代表指向字元陣列的指標變數。 • 所以一般我們看到char *、int *時,除了想到這是一個位址的指標變數之外,也會把他看成是一個(未定義長度的)陣列。 • 「char *」一般看成是一個字串的型態。 h e l l o s

  8. 8.10 指標陣列 • 很多指標變數 • 存在陣列當中,每一個元素都是指標變數(每一個元素都儲存記憶體位址) • 範例 const char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" }; • Each element of suit points to a char * (string) • 回答以下問題: suit是一個陣列 • 有_______個元素(固定大小)。 • 每一個元素的型態是______________,代表每一個元素儲存的是一個_____________________。 • 每一個元素所指向的字串長度不一。

  9. 指標陣列圖示 char * suit [ 4 ];

  10. 指標陣列與二維陣列的差別 char s[3][4]; char *s[3]; 0 1 2 3 s[0] s[0] s[1] s[1] s[2] s[2] s s[0] s[1] s[2]

  11. 8.13 指標字串處理簡介 • 本節將介紹輔助字串處理的標準函式庫函式。 • 字串處理主要是以字元為基礎。 • 字元常數 • 整數值,代表字元的ASCII編碼。 • 以字元兩邊加上單引號來表示,例如: • ' z ' 代表z的整數值 • ASCII碼為122 • ' \n ' 代表換行字元(newline)的整數值 • ASCII碼為10

  12. 8.13.1 字串與指標字串基礎 • 字串 • 一連串字元的組合。 • 字串常數,以雙引號將字串的內容括起來。如: "I like C++“ • 字串可視為一個以結束字元(’\0’)結尾的字元陣列。或一個指向字元陣列的指標。

  13. 8.13.1 字串與指標字串基礎 • 宣告字串與初始化 • 字元陣列 • char color[] = "blue"; • 以上的敘述產生一個有五個元素的字元陣列 • 自動補‘\0’到最後一個元素 • 指向字元的指標變數(char *) • char *colorPtr = "blue"; • 產生一個指標變數colorPtr指向字串(字元陣列)“blue”的第一個元素。 • 注意:“blue”所在的位址在記憶體的其他地方。 • 字串的其他宣告法 • char color[] = { 'b', 'l', 'u', 'e', '\0' }; • 如果字串是一個字元一個字元指定,必須要特別給予結束字元。

  14. 常見的程式設計錯誤 • 雖然我們常把char *看成是一個字串,但如果沒有為其配置記憶體就直接存取其中的元素,在執行時便會出現「memory access violations」的錯誤訊息。 char *s; cin >> s; • 因為s是一個指標變數,必須指定給他一個合法的字元陣列,而此字元陣列尚未被宣告(未有配置記憶體來記錄資料)。

  15. 常見的程式設計錯誤 • 沒有給予足夠的陣列長度。 • 沒有給予結束字元。

  16. 8.13.1字串與指標字串基礎 • 讀取字串 • 指定鍵盤輸入至字串陣列word[ 20 ] • cin >> word; • 此行敘述將讀取字串,直到遇到空白或檔尾(EOF)為止(其他的沒有尚未被讀入的資料將被保留在輸入的暫存區中)。 • 為避免字串的輸入超過陣列的長度,利用setw()設定最多讀取的字元數目: • cin >> setw( 20 ) >> word; • 讀入的字元最多19個,程式自動保留一個空間給結束字元。

  17. 8.13.1字串與指標字串基礎 • cin.getline • 讀入一整行的文字;例如 • cin.getline( array, size, delimiter ); • 將一直讀入字元直到以下兩種情況: • 讀入的字元數超過size-1。 • 遇到分界符號(delimiter)。 • 範例: char sentence[ 80 ];cin.getline( sentence, 80, '\n' ); • 讀到79個字元或遇到換行符號('\n')便停止,結果存入sentence中。

  18. 8.13.2 字串處理函式庫的字串操作函式 • 必須載入標頭檔<cstring>,可用來 • 處理字串資料。 • 比較字串。 • 搜尋字串內的字元與其他字串。 • 切割字串。 • 資料型別:size_t • 定義於<cstring>,通常為無號整數(unsigned int)或無號長整數(unsigned long)。

  19. include<cstring>標頭檔以載入strcpy and strncpy的宣告 將字串y中的內容拷貝至字串x

  20. 將x當中的前14個字元拷貝到y;請注意,這個函式並不會自動補結束字元。將x當中的前14個字元拷貝到y;請注意,這個函式並不會自動補結束字元。 因此呼叫這個函式後一定要記得補結束字元。

  21. include<cstring>標頭檔以載入strcat and strncat的宣告 將s2串接到s1結尾 將s1中的前6個字元加到 s3的結尾,請注意此結果會自動補結束字元。

  22. 將s1加到s3的結尾

  23. 8.13.2 字串處理函式庫的字串操作函式 • 比較字串 • int strcmp(const char *s1,constchar *s2) • 回傳: • 0:代表兩字串相等 • 負值:代表s1 < s2。 • 正值:代表s1 > s2。 • int strncmp(constchar *s1, constchar *s2, size_t n ) • 比較兩字串前n個字元 • 如果其中一個已經比到結尾,就會提早結束比對。

  24. 列印s1與s2比較後的結果 列印s1與s3比較後的結果 列印s3與s1比較後的結果

  25. 執行結果

  26. Portability Tip 8.6 • 請勿直接比較字元的ASCII碼,例如: if ( rating == 65 ) 最好使用 if ( rating == 'A' ) • 因為不同作業平台上所採用的編碼方式不一,第二種寫法較能提升可攜性。

  27. 8.13.2 字串處理函式庫的字串操作函式 • 分割字串 • 將字串分隔成tokens • Tokens指的是由分界字元(delimiting characters,例如空白字元)隔開而成的字組/符記。 • 例: char *s1 = “ ”; char *s2 = “ \t\n”; • 範例: • “This is my string”裡有 4 個word tokens (如果以空白隔開的話)。

  28. 8.13.2 字串處理函式庫的字串操作函式 • 利用strtok函式分割字串 • char *strtok( char *s1, constchar *s2 ) • 需要重複的呼叫來擷取tokens • 第一次呼叫時需要兩個引數,第一個引數代表需要被擷取的字串,第二個則是包含分界字元的字串。 • 連續地呼叫來將token一一地擷取出來 • 第二次呼叫開始,第一個參數用NULL替代。 • 該函式會將下一次開頭的位址把指標用一個靜態變數(static variable)儲存起來。 • 回傳一個指標指向目前所讀取到的token。

  29. 必須include 標頭檔<cstring> 第一次呼叫strtok,回傳的指標指向第一個token的開頭 接下來連續呼叫strtok來讀取下一個token,第一個參數改用NULL代替。當strtok回傳NULL,就代表已經讀到字串結尾了。

  30. 執行結果

  31. 常見的程式設計錯誤8.22 • 要瞭解使用strtoken時,會修改到第一個參數所指向的內容,如果在呼叫完strtoken之後再繼續拿第一個參數所代表的字串來做運算,將有可能會發生錯誤。 • 如果日後需要使用該字串,建議在呼叫strtoken之前,先把原字串複製一份,再拿其負本來做strtoken。

  32. strlen()的使用範例 使用strlen來計算字串的長度。

More Related