資料結構

62
資資資資 資資資資 3 3 第第第第第 第第第第第 Pointers and Strings Pointers and Strings

description

資料結構. 第 3 章 指標與字串 (Pointers and Strings). 第 3 章 課 程大綱. 3-1 C 語言的 指標 3-2 指標與 陣列 3-3 指標與 結構 3-4 指標與 字串 3-5 指標的 應用 - 字串處理. 3-1 C語言的指標. 3-1-1 指標變數 (Pointer Variable) 的使用 3-1-2 指向指標 的 指標變數. 3-1 C語言的指標. C 語言的 「指標」( Points ) 屬於一種低階的程式處理功能 可以直接存取 記憶體位址 - PowerPoint PPT Presentation

Transcript of 資料結構

Page 1: 資料結構

資料結構資料結構第第 33 章 章 指標與字串指標與字串

(( Pointers and StringsPointers and Strings ))

Page 2: 資料結構

2008/3/18 2

第第 33 章 課程大綱章 課程大綱• 3-1 C3-1 C 語言的語言的指標指標• 3-2 3-2 指標與指標與陣列陣列• 3-3 3-3 指標與指標與結構結構• 3-4 3-4 指標與指標與字串字串• 3-5 3-5 指標的指標的應用應用 - - 字串處理字串處理

Page 3: 資料結構

2008/3/18 3

3-1 C3-1 C語言的指標語言的指標

• 3-1-1 3-1-1 指標變數指標變數 (Pointer Variable)(Pointer Variable) 的的使用使用

• 3-1-2 3-1-2 指向指標指向指標的的指標變數指標變數

Page 4: 資料結構

2008/3/18 4

3-1 C3-1 C語言的指標語言的指標

• CC 語言的語言的「指標」(「指標」( PointsPoints ))屬於一種低屬於一種低階的程式處理功能階的程式處理功能– 可以直接存取可以直接存取記憶體位址記憶體位址– 指標變數的指標變數的變數內容變數內容並不是字元或數值等基本資料型並不是字元或數值等基本資料型

態的值,而是其它變數的態的值,而是其它變數的「位址」(「位址」( AddressAddress ))。。• 換句話說,單獨存在的指標變數換句話說,單獨存在的指標變數並沒有意義並沒有意義,,

因為它的值是因為它的值是其它變數的位址其它變數的位址,程式需先宣告,程式需先宣告其它變數,才能取得指標變數的值,即其它變數,才能取得指標變數的值,即指向其它指向其它變數的儲存位址變數的儲存位址。。

Page 5: 資料結構

2008/3/18 5

3-1-1 3-1-1 指標變數指標變數的使用的使用 -- 說明說明• CC 語言的「指標變數」(語言的「指標變數」( Pointer Pointer

VariablesVariables )是一種)是一種變數變數,其變數值是,其變數值是其其它變數的位址(它變數的位址( AddressAddress )),如下圖,如下圖所示:所示:

間接索引

Page 6: 資料結構

2008/3/18 6

3-1-1 3-1-1 指標變數指標變數的使用的使用 --宣告宣告

• 指標變數指標變數的宣告和的宣告和基本資料型態變數基本資料型態變數的宣告的宣告稍有稍有不同不同,其宣告格式,如下所示:,其宣告格式,如下所示:

資料型態 資料型態 ** 變數名稱變數名稱 ;;

• 指標變數宣告和變數宣告指標變數宣告和變數宣告只差變數名稱前的只差變數名稱前的「「 ** 」星號」星號,簡單的說,這個變數是指向宣告,簡單的說,這個變數是指向宣告資料型態的指標變數,資料型態的指標變數,– 例如:指向整數例如:指向整數 intint 的指標變數宣告,如下所示:的指標變數宣告,如下所示:int *ptr;int *ptr;

Page 7: 資料結構

2008/3/18 7

3-1-1 3-1-1 指標變數指標變數的使用的使用 --取得取得變數位址變數位址

• 將將指標變數指標變數 ptrptr 指向指向變數變數 jj 的的位址位址– 取得變數位址是使用單運算元的取得變數位址是使用單運算元的「「 && 」」取址運取址運

算子,如下所示:算子,如下所示:ptr = &j; ptr = &j; //// 取得變數 取得變數 J J 的位置的位置

Page 8: 資料結構

2008/3/18 8

3-1-1 3-1-1 指標變數指標變數的使用的使用 --初值初值• 指標變數也可以在指標變數也可以在宣告時指定初值宣告時指定初值,不過,不過取得取得

位址的變數一定需要在指標變數前宣告位址的變數一定需要在指標變數前宣告,如,如下所示:下所示:int i;int i;int *ptr1 = &i;int *ptr1 = &i;– 上述程式碼先宣告整數變數上述程式碼先宣告整數變數 ii ,然後是指標變數,然後是指標變數 ptr1ptr1 ,,

指標變數的初值是變數指標變數的初值是變數 ii 的位址。的位址。• 因為因為 CC 語言的指標變數語言的指標變數並沒有預設值並沒有預設值,為了避免,為了避免

程式錯誤,例如:尚未指向其它變數的位址就使程式錯誤,例如:尚未指向其它變數的位址就使用指標變數,可以用指標變數,可以在宣告時指定成在宣告時指定成 NULLNULL 常數常數,,如下所示:如下所示:int *ptr = NULL;int *ptr = NULL;

Page 9: 資料結構

2008/3/18 9

3-1-1 3-1-1 指標變數指標變數的使用的使用 --取得取得變數值變數值

• 在在 CC 程式取得指標變數指向的程式取得指標變數指向的變數值變數值– 是使用單運算元的是使用單運算元的「「 ** 」」星號運算子星號運算子,稱為,稱為

「取值」「取值」(( IndirectionIndirection ))或或「解參考」「解參考」(( DereferencingDereferencing )運算子)運算子,,

– 例如:例如: ptrptr 是指向整數變數是指向整數變數 jj 的指標變的指標變數,數, **ptrptr 就是變數就是變數 jj 的值,如下所示:的值,如下所示:

printf("*ptr :printf("*ptr : 位址位址 %p%p 的值的值 =%d\n", ptr, =%d\n", ptr, *ptr);*ptr);• 上述上述 printf()printf() 函數使用函數使用 %p%p 格式字元顯示指標變數格式字元顯示指標變數

的值,的值, ptrptr 是變數是變數 jj 的位址,的位址, **ptrptr 是變數是變數 jj 的值。的值。

Page 10: 資料結構

2008/3/18 10

程式範例程式範例 Ch3-1-1.cCh3-1-1.c

• 程式目標程式目標– 在在 CC 程式中宣告數個變數和指標變數程式中宣告數個變數和指標變數 , , 然後測試 然後測試 ”” &” &”

取址運算子和 取址運算子和 ““ *” *” 取值運算子取值運算子• 執行結果如下執行結果如下

– i=1 i=1 位址位址 =0022FF74=0022FF74– j=2j=2 位址位址 =0022FF70=0022FF70– ptr=0022FF70ptr=0022FF70 位址位址 =0022FF6C=0022FF6C– *ptr=*ptr= 位址位址 0022FF700022FF70 的值的值 =2=2– ptr1=0022FF74ptr1=0022FF74 位址位址 =0022FF68=0022FF68– *ptr1=*ptr1= 位址位址 0022FF740022FF74 的值的值 =1=1

Page 11: 資料結構

2008/3/18 11

• /* /* 程式範例程式範例 : Ch3-1-1.c */: Ch3-1-1.c */• #include <stdio.h>#include <stdio.h>• #include <stdlib.h>#include <stdlib.h>• /* /* 主程式 主程式 **//• int main() {int main() {• /* /* 宣告變數 宣告變數 **//• int i, j;int i, j;• int *ptr = NULL;int *ptr = NULL;• int *ptr1 = &i; /* int *ptr1 = &i; /* 指標變數的初值 指標變數的初值 **/ / • i = 1;i = 1;• j = 2; j = 2; • /* /* 取得指標變數的值 取得指標變數的值 **//• ptr = &j;ptr = &j;• printf("i =%8d printf("i =%8d 位址位址 =%p\n", i, &i);=%p\n", i, &i);• printf("j =%8d printf("j =%8d 位址位址 =%p\n", j, &j);=%p\n", j, &j);• printf("ptr =%p printf("ptr =%p 位址位址 =%p\n", ptr, &ptr);=%p\n", ptr, &ptr);• printf("*ptr :printf("*ptr : 位址位址 %p%p 的值的值 =%d\n", ptr, *ptr);=%d\n", ptr, *ptr);• printf("ptr1=%p printf("ptr1=%p 位址位址 =%p\n", ptr1, &ptr1);=%p\n", ptr1, &ptr1);• printf("*ptr1:printf("*ptr1: 位址位址 %p%p 的值的值 =%d\n", ptr1, *ptr1);=%d\n", ptr1, *ptr1);• system("PAUSE");system("PAUSE");• return 0; return 0; • }}

Page 12: 資料結構

2008/3/18 12

3-1-2 3-1-2 指向指標的指標變數指向指標的指標變數 --說明說明

• 指向指標的指標變數指向指標的指標變數是說指標變數是是說指標變數是指向其指向其它的指標變數它的指標變數。。– 首先在程式宣告一個整數 首先在程式宣告一個整數 i i 和指標變數 和指標變數 ptrptr ,如下所示:,如下所示:int i = 5;int i = 5;int int *ptr*ptr = &i; = &i;

– 接著再宣告一個接著再宣告一個指向指標的指標變數指向指標的指標變數 ptr1ptr1 ,如下所示:,如下所示:intint ** **ptr1 = &ptr;ptr1 = &ptr;– 指標變數指標變數 ptr1ptr1 共有共有 22 個星號,第個星號,第 11 個星號指出變數是一個指標個星號指出變數是一個指標

變數,第變數,第 22 個星號表示它是指向指標變數,即個星號表示它是指向指標變數,即 ptrptr 。。– 接著再宣告接著再宣告指標變數指向指標的指標變數指標變數指向指標的指標變數,如下所示:,如下所示:int ***ptr2 = &ptr1;int ***ptr2 = &ptr1;– 指標變數指標變數 ptr2ptr2 共有共有 33 個星號,第個星號,第 11 個星號指出變數是指標變數,個星號指出變數是指標變數,後後 22 個星號表示它是指向指標的指標變數,即個星號表示它是指向指標的指標變數,即 ptr1ptr1 。。

Page 13: 資料結構

2008/3/18 13

3-1-2 3-1-2 指向指標的指標變數指向指標的指標變數 --圖例圖例

Page 14: 資料結構

2008/3/18 14

程式範例程式範例 Ch3-1-2.cCh3-1-2.c• 程式目標程式目標

– 在在 CC 程式中宣告指標變數程式中宣告指標變數 , , 指向指標的指標變數和指向指標的指指向指標的指標變數和指向指標的指標的指標變數標的指標變數 , , 然後分別執行取值運算然後分別執行取值運算 , , 以顯示其位址與值以顯示其位址與值 !!!!

• 執行結果如下執行結果如下– i=5 i=5 位址位址 =0022FF74=0022FF74– ptr=0022FF74 ptr=0022FF74 位址位址 =0022FF70=0022FF70– ptr1=0022FF70 ptr1=0022FF70 位址位址 =0022FF6C=0022FF6C– ptr2=0022FF6C ptr2=0022FF6C 位址位址 =0022FF68=0022FF68– *ptr=*ptr= 位址位址 0022FF740022FF74 的值的值 =5=5– *ptr1=*ptr1= 位址位址 0022FF700022FF70 的值的值 =0022FF74=0022FF74– *ptr2=*ptr2= 位址位址 0022FF6C0022FF6C 的值的值 =0022FF70=0022FF70– **ptr = 5ptr = 5– **ptr1 = 5**ptr1 = 5– ***ptr2 = 5***ptr2 = 5

Page 15: 資料結構

2008/3/18 15

• /* /* 程式範例程式範例 : Ch3-1-2.c */: Ch3-1-2.c */• #include <stdio.h>#include <stdio.h>• #include <stdlib.h>#include <stdlib.h>• /* /* 主程式 主程式 **//• int main() {int main() {• /* /* 宣告變數 宣告變數 **//• int i = 5;int i = 5;• int *ptr = &i;int *ptr = &i;• int **ptr1 = &ptr;int **ptr1 = &ptr;• int ***ptr2 = &ptr1; int ***ptr2 = &ptr1; • /* /* 取得指標變數的值 取得指標變數的值 **//• printf("i =%8d printf("i =%8d 位址位址 =%p\n", i, &i);=%p\n", i, &i);• printf("ptr =%p printf("ptr =%p 位址位址 =%p\n", ptr, &ptr);=%p\n", ptr, &ptr);• printf("ptr1=%p printf("ptr1=%p 位址位址 =%p\n", ptr1, &ptr1);=%p\n", ptr1, &ptr1);• printf("ptr2=%p printf("ptr2=%p 位址位址 =%p\n", ptr2, &ptr2);=%p\n", ptr2, &ptr2);• printf("*ptr :printf("*ptr : 位址位址 %p%p 的值的值 =%8d\n", ptr, *ptr);=%8d\n", ptr, *ptr);• printf("*ptr1:printf("*ptr1: 位址位址 %p%p 的值的值 =%p\n", ptr1, =%p\n", ptr1,

*ptr1);*ptr1);• printf("*ptr2:printf("*ptr2: 位址位址 %p%p 的值的值 =%p\n", ptr2, =%p\n", ptr2,

*ptr2);*ptr2);• printf("*ptr = %d\n", *ptr);printf("*ptr = %d\n", *ptr);• printf("**ptr1 = %d\n", **ptr1);printf("**ptr1 = %d\n", **ptr1);• printf("***ptr2= %d\n", ***ptr2); printf("***ptr2= %d\n", ***ptr2); • system("PAUSE");system("PAUSE");• return 0; return 0; • }}

Page 16: 資料結構

2008/3/18 16

3-2 3-2 指標與陣列 指標與陣列 (Pointers and (Pointers and Arrays)Arrays)

• 3-2-1 3-2-1 指標與指標與陣列陣列• 3-2-2 3-2-2 指標與指標與二維陣列二維陣列• 3-2-3 3-2-3 指標陣列指標陣列

Page 17: 資料結構

2008/3/18 17

3-2-1 3-2-1 指標與陣列指標與陣列 -- 說明說明

• CC 語言的語言的陣列配置陣列配置– 是一塊連續的記憶體空間,然後是一塊連續的記憶體空間,然後使用索引值存使用索引值存

取陣列元素取陣列元素• 如果改成如果改成指標變數指標變數,只需將,只需將指標變數指標變數

指向陣列的第指向陣列的第 11 個元素個元素,,– 元素存取就可以使用元素存取就可以使用指標的數運算加和減來完指標的數運算加和減來完

成成。。

Page 18: 資料結構

2008/3/18 18

3-2-1 3-2-1 指標與陣列指標與陣列 -- 指向陣列指向陣列元素元素

• 宣告指標變數宣告指標變數指向陣列的第指向陣列的第 11 個元素個元素,如下所示:,如下所示:int *ptr = array;int *ptr = array;

• CC 語言的語言的陣列名稱陣列名稱就是就是陣列第陣列第 11 個元素的位址個元素的位址,,因為因為陣列名稱本身是一個指標變數陣列名稱本身是一個指標變數,如,如果使用果使用取址運算子取址運算子「「 && 」,其程式碼如下所示:」,其程式碼如下所示:ptr = &array[0];ptr = &array[0];

Page 19: 資料結構

2008/3/18 19

3-2-1 3-2-1 指標與陣列指標與陣列 -- 走訪陣列走訪陣列(( 方法方法 1)1)

• 一共有一共有 22 種方法種方法存取其它陣列元素的值存取其它陣列元素的值,,如下所示:如下所示:for ( i = 0; i < LEN; i++ )for ( i = 0; i < LEN; i++ )

printf("ptr+%d=%d ", i, printf("ptr+%d=%d ", i, *(ptr+i)*(ptr+i)););

Page 20: 資料結構

2008/3/18 20

3-2-1 3-2-1 指標與陣列指標與陣列 -- 走訪陣列走訪陣列(( 方法方法 2)2)

• 第第 22 個方法是使用個方法是使用指標變數指標變數的的遞增運算遞增運算 ptr+ptr+++ ,,如下所示:如下所示:

for ( i = 0; i < LEN; i++ )for ( i = 0; i < LEN; i++ ) printf("ptr+%d=%d ", i, printf("ptr+%d=%d ", i, *ptr++*ptr++););

– 上述上述 forfor 迴圈使用指標走訪陣列元素,指標運算迴圈使用指標走訪陣列元素,指標運算 ptr+ptr+++ 移到下一個元素,元素值是取值運算移到下一個元素,元素值是取值運算 **(ptr++)(ptr++) ,,

– 這個方法會這個方法會真正移動指標變數的位址真正移動指標變數的位址,等到執,等到執行完迴圈,指標變數行完迴圈,指標變數 ptrptr 是指向陣列的最後是指向陣列的最後 11 個元素。個元素。

Page 21: 資料結構

2008/3/18 21

程式範例程式範例 Ch3-2-1.cCh3-2-1.c

• 程式目標程式目標– 在在 CC 程式中宣告一維陣列後程式中宣告一維陣列後 , , 分別使用陣列索引分別使用陣列索引 , , 指指

標運算與遞增標運算與遞增 , , 遞減運算顯示陣列所有元素的值遞減運算顯示陣列所有元素的值 !!!!

• 執行結果如下執行結果如下– array[0] = 1 array[1] = 23 array[2] = 23 array[0] = 1 array[1] = 23 array[2] = 23

array[3] = 17 array[4] = -40 array[5] =100array[3] = 17 array[4] = -40 array[5] =100– ptr+0=1 ptr+1=23 ptr+2=23 ptr+3=17 ptr+0=1 ptr+1=23 ptr+2=23 ptr+3=17

ptr+4=-40 ptr+5=100ptr+4=-40 ptr+5=100– ptr-0=100 ptr-1 = -40 ptr-2=17 ptr-3=23 ptr-ptr-0=100 ptr-1 = -40 ptr-2=17 ptr-3=23 ptr-

4=23 ptr-5 =1 4=23 ptr-5 =1

Page 22: 資料結構

2008/3/18 22

/* /* 程式範例程式範例 : Ch3-2-1.c */: Ch3-2-1.c */#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#define LEN 6#define LEN 6/* /* 主程式 主程式 **//int main() {int main() { /* /* 宣告變數 宣告變數 **// int i;int i; /* /* 建立建立 intint 陣列且指定初值 陣列且指定初值 **// int array[LEN] = { 1, 23, 33, 17, -int array[LEN] = { 1, 23, 33, 17, -

40, 100 };40, 100 }; int *ptr = array; /* int *ptr = array; /* 第一個元素 第一個元素 **/ / /* /* 顯示陣列元素的值 顯示陣列元素的值 **/ / for ( i = 0; i < LEN; i++ )for ( i = 0; i < LEN; i++ ) printf("array[%d]=%d printf("array[%d]=%d

",i,array[i]);",i,array[i]); printf("\n");printf("\n"); ptr = array; /* ptr = array; /* 第一個元素 第一個元素 **/ / for ( i = 0; i < LEN; i++ )for ( i = 0; i < LEN; i++ ) printf("ptr+%d=%d ", i, printf("ptr+%d=%d ", i, *(ptr+i)*(ptr+i));); printf("\n");printf("\n");

ptr = &array[0]; /* ptr = &array[0]; /* 第一個元素 第一個元素 **/ /

for ( i = 0; i < LEN; i++ )for ( i = 0; i < LEN; i++ ) printf("ptr+%d=%d ", i, printf("ptr+%d=%d ", i,

*ptr++*ptr++);); printf("\n");printf("\n"); ptr = &array[LEN-1]; /* ptr = &array[LEN-1]; /* 最後最後

一個元素 一個元素 **/ / for ( i = 0; i < LEN; i++ )for ( i = 0; i < LEN; i++ ) printf("ptr-%d=%d ", i, printf("ptr-%d=%d ", i,

*ptr--);*ptr--); printf("\n");printf("\n"); system("PAUSE");system("PAUSE"); return 0; return 0; }}

Page 23: 資料結構

2008/3/18 23

3-2-2 3-2-2 指標與指標與二維陣列二維陣列 -- 範例範例• CC 語言的語言的二維陣列二維陣列也可以使用也可以使用指標變數指標變數來存取來存取

陣列元素,例如:宣告一個二維整數陣列陣列元素,例如:宣告一個二維整數陣列tables[][]tables[][] ,如下所示:,如下所示:#define ROWS 4#define ROWS 4

#define COLS 5#define COLS 5

int tables[ROWS][COLS];int tables[ROWS][COLS];

Page 24: 資料結構

2008/3/18 24

3-2-2 3-2-2 指標與二維陣列指標與二維陣列 -- 方法方法 11

• 視為視為一維陣列存取一維陣列存取,因為二維陣列配置的記憶體空,因為二維陣列配置的記憶體空間是將每一列結合起來的連續記憶體位置,間是將每一列結合起來的連續記憶體位置,如同如同 44列合一的一維陣列列合一的一維陣列,如下所示:,如下所示:int *ptr;int *ptr;ptr = &tables[0][0];ptr = &tables[0][0];– 指標變數指標變數 ptrptr 指向陣列指向陣列第第 11 個元素的位址個元素的位址。。– 接著使用接著使用指標運算指標運算取得每一個陣列元素,如下所示:取得每一個陣列元素,如下所示:for ( i=0; i < ROWS; i++) { for ( i=0; i < ROWS; i++) { //// 先控制先控制 RowRow 在控制在控制

COLSCOLS for ( j=0; j < COLS; j++)for ( j=0; j < COLS; j++) printf("%d*%d=%2d ", (i+1), (j+1), printf("%d*%d=%2d ", (i+1), (j+1), *(ptr+*(ptr+

(i*COLS)+j)(i*COLS)+j));); printf("\n");printf("\n");}}

Page 25: 資料結構

2008/3/18 25

3-2-2 3-2-2 指標與二維陣列指標與二維陣列 -- 方法方法 22• 第二個方法是使用第二個方法是使用 tables[ ][ ]tables[ ][ ] 陣列名稱的指標變陣列名稱的指標變

數數,其運算式如下所示:,其運算式如下所示:**(*(tables + i) + j)(*(tables + i) + j)– tablestables 是二維陣列的名稱,可以將它視為是一個是二維陣列的名稱,可以將它視為是一個指向指向

指標的指標變數指標的指標變數,在中間括號部分的運算式,如下,在中間括號部分的運算式,如下所示:所示:

**(tables+i)(tables+i)– 上述指標運算可以當作是第一欄上述指標運算可以當作是第一欄 tables[ROWS][0]tables[ROWS][0] 的的

指標運算,取值運算取得的是:指標運算,取值運算取得的是:• tables[0][0]tables[0][0](( tables+0tables+0 ))• tables[1][0]tables[1][0](( tables+1tables+1 ))• tables[2][0]tables[2][0](( tables+2tables+2 ))• tables[3][0]tables[3][0](( tables+3tables+3 ))

Page 26: 資料結構

2008/3/18 26

程式範例程式範例 Ch3-2-2.cCh3-2-2.c• 程式目標程式目標

– 在在 CC 程式中宣告 程式中宣告 2 2 維陣列維陣列儲存部分的儲存部分的九九乘法表九九乘法表 , , 然後使用指標然後使用指標方式顯示部分的九九乘法表方式顯示部分的九九乘法表 !!!!

• 執行結果如下執行結果如下– 1*1=1 1*2=2 1*3=3 1*4=4 1*5=51*1=1 1*2=2 1*3=3 1*4=4 1*5=5– 2*1=2 2*2=4 2*3=6 2*4=8 2*5=102*1=2 2*2=4 2*3=6 2*4=8 2*5=10– 3*1=3 3*2=6 3*3=9 3*4=12 3*5=153*1=3 3*2=6 3*3=9 3*4=12 3*5=15– 4*1=4 4*2=8 4*3=12 4*4=16 4*5=204*1=4 4*2=8 4*3=12 4*4=16 4*5=20– 上方上方是用是用一維陣列的指標存取一維陣列的指標存取 , , 下方下方是用是用二維陣列的指標存取二維陣列的指標存取

來顯示部分的九九乘法表來顯示部分的九九乘法表– 1*1=1 1*2=2 1*3=3 1*4=4 1*5=51*1=1 1*2=2 1*3=3 1*4=4 1*5=5– 2*1=2 2*2=4 2*3=6 2*4=8 2*5=102*1=2 2*2=4 2*3=6 2*4=8 2*5=10– 3*1=3 3*2=6 3*3=9 3*4=12 3*5=153*1=3 3*2=6 3*3=9 3*4=12 3*5=15– 4*1=4 4*2=8 4*3=12 4*4=16 4*5=204*1=4 4*2=8 4*3=12 4*4=16 4*5=20

Page 27: 資料結構

2008/3/18 27

/* /* 程式範例程式範例 : Ch3-2-2.c */: Ch3-2-2.c */#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#define ROWS 4#define ROWS 4#define COLS 5#define COLS 5/* /* 主程式 主程式 **//int main() {int main() { /* /* 宣告變數 宣告變數 **// int i, j;int i, j; /* /* 建立建立 intint 的二維陣列 的二維陣列 **// int tables[ROWS][COLS];int tables[ROWS][COLS]; int *ptr;int *ptr; /* /* 指定二維陣列的元素值 指定二維陣列的元素值 **/ / for ( i=0; i < ROWS; i++)for ( i=0; i < ROWS; i++) for ( j=0; j < COLS; j++)for ( j=0; j < COLS; j++) tables[i][j] = (i+1)*(j+1);tables[i][j] = (i+1)*(j+1);

/* /* 顯示二維陣列的元素值 顯示二維陣列的元素值 **/ / ptr = &tables[0][0];ptr = &tables[0][0]; for ( i=0; i < ROWS; i++) {for ( i=0; i < ROWS; i++) { for ( j=0; j < COLS; j++)for ( j=0; j < COLS; j++) printf("%d*%d=%2d ", (i+1), printf("%d*%d=%2d ", (i+1),

(j+1), *(ptr+(i*COLS)+j));(j+1), *(ptr+(i*COLS)+j)); printf("\n");printf("\n"); }} printf("\n");printf("\n"); for ( i=0; i < ROWS; i++) {for ( i=0; i < ROWS; i++) { for ( j=0; j < COLS; j++)for ( j=0; j < COLS; j++) printf("%d*%d=%2d ", (i+1), printf("%d*%d=%2d ", (i+1),

(j+1), *(*(tables + i) + j));(j+1), *(*(tables + i) + j)); printf("\n");printf("\n"); }} system("PAUSE");system("PAUSE"); return 0; return 0; }}

Page 28: 資料結構

2008/3/18 28

• /* /* 程式範例程式範例 : Ch3-2-2.c-1 */: Ch3-2-2.c-1 */• /* /* 九九乘法表九九乘法表 **//• #include <stdio.h>#include <stdio.h>• #include <stdlib.h>#include <stdlib.h>• #define ROWS 9#define ROWS 9• #define COLS 9#define COLS 9• /* /* 主程式 主程式 **//• int main() {int main() {• /* /* 宣告變數 宣告變數 **//• int i, j;int i, j;• /* /* 建立建立 intint 的二維陣列 的二維陣列 **//• int tables[ROWS][COLS];int tables[ROWS][COLS];• int *ptr;int *ptr;• /* /* 指定二維陣列的元素值 指定二維陣列的元素值 **/ / • for ( i=0; i < ROWS; i++)for ( i=0; i < ROWS; i++)• for ( j=0; j < COLS; j++)for ( j=0; j < COLS; j++)• tables[i][j] = (i+1)*(j+1);tables[i][j] = (i+1)*(j+1);• • /* /* 顯示二維陣列的元素值 顯示二維陣列的元素值 **/ / • ptr = &tables[0][0];ptr = &tables[0][0];• for ( i=0; i < ROWS; i++) {for ( i=0; i < ROWS; i++) {• for ( j=0; j < COLS; j++)for ( j=0; j < COLS; j++)• printf("%d*%d=%2d ", (i+1), (j+1), *(ptr+printf("%d*%d=%2d ", (i+1), (j+1), *(ptr+

(i*COLS)+j));(i*COLS)+j));• printf("\n");printf("\n");• }}• printf("\n");printf("\n");• for ( i=0; i < ROWS; i++) {for ( i=0; i < ROWS; i++) {• for ( j=0; j < COLS; j++)for ( j=0; j < COLS; j++)• printf("%d*%d=%2d ", (i+1), (j+1), *(*(tables printf("%d*%d=%2d ", (i+1), (j+1), *(*(tables

+ i) + j));+ i) + j));• printf("\n");printf("\n");• }}• system("PAUSE");system("PAUSE");• return 0; return 0; • }}

Page 29: 資料結構

2008/3/18 29

3-2-3 3-2-3 指標陣列指標陣列 -- 宣告宣告• 「指標陣列」「指標陣列」(( Arrays of PointerArrays of Pointer )是指)是指

陣列的每一個元素都是一個指標變數陣列的每一個元素都是一個指標變數– 也就是說,也就是說,陣列元素的值陣列元素的值都是都是指向其它變數的位址指向其它變數的位址。。

• 指標陣列的宣告方式類似指標變數,如下所示:指標陣列的宣告方式類似指標變數,如下所示:#define ROWS 4#define ROWS 4int *tables[ROWS];int *tables[ROWS];– 上述程式碼宣告指標陣列上述程式碼宣告指標陣列 tables[]tables[] ,一共擁有,一共擁有 44 個元個元

素,每一個元素是一個整數的指標變數,可以指向整素,每一個元素是一個整數的指標變數,可以指向整數或一個一維陣列,數或一個一維陣列,

– 如果都是指向如果都是指向 55 個元素的一維陣列,相當於是宣告一個元素的一維陣列,相當於是宣告一個個 4 X 54 X 5 的二維陣列。的二維陣列。

Page 30: 資料結構

2008/3/18 30

3-2-3 3-2-3 指標陣列指標陣列 -- 差異差異

• 指標陣列和二維陣列的指標陣列和二維陣列的差異差異在在– 指標陣列並不能指定初值,指標陣列並不能指定初值,– 二維陣列在宣告後就配置二維陣列在宣告後就配置 ROWS X COLSROWS X COLS 個個

元素,指標陣列只配置元素,指標陣列只配置 ROWSROWS 個元素,個元素,– 指標陣列的最大好處是每一個指標指向的變數指標陣列的最大好處是每一個指標指向的變數

可以是不同長度,可以是不同長度,• 例如:不同元素分別指向整數或整數陣列。例如:不同元素分別指向整數或整數陣列。

Page 31: 資料結構

2008/3/18 31

3-2-3 3-2-3 指標陣列指標陣列 -- 圖例圖例

Page 32: 資料結構

2008/3/18 32

3-2-3 3-2-3 指標陣列指標陣列 -- 存取存取• 使用使用指標運算指標運算存取指標陣列的元素,如存取指標陣列的元素,如

下所示:下所示:for ( i=0; i < ROWS; i++ ) {for ( i=0; i < ROWS; i++ ) {

printf("*tables[%d]=%2d ", i, *tables[i]);printf("*tables[%d]=%2d ", i, *tables[i]);

printf("**(tables+%d)=%2d ", i, **(tables + i));printf("**(tables+%d)=%2d ", i, **(tables + i));

printf("**(ptr+%d)=%2d ", i, **(ptr + i));printf("**(ptr+%d)=%2d ", i, **(ptr + i));

}}

• 上述上述 forfor 迴圈可以走訪指標陣列,然後使用迴圈可以走訪指標陣列,然後使用**tables[i]tables[i] 、、 ****(tables + i)(tables + i) 和和 ****(ptr + i)(ptr + i) 取得取得陣列元素的值。陣列元素的值。

Page 33: 資料結構

2008/3/18 33

程式範例程式範例 Ch3-2-3.cCh3-2-3.c• 程式目標程式目標

– 在在 CC 程式中宣告程式中宣告一個指標陣列一個指標陣列和和一維陣列一維陣列 , , 將將指標陣列指標陣列的每一個元素指向一維陣列的元素的每一個元素指向一維陣列的元素 , , 然後然後用指標運算顯用指標運算顯示出指標陣列的元素值示出指標陣列的元素值 !!!!

• 執行結果如下執行結果如下– **ptr=&tables[0];**ptr=&tables[0];– *tables[0]=10 **(tables+0)=10 **(ptr+0)=10 *tables[0]=10 **(tables+0)=10 **(ptr+0)=10 位位址址 =0022FF50=0022FF50

– *tables[1]=4 **(tables+0)=4 **(ptr+0)=10 *tables[1]=4 **(tables+0)=4 **(ptr+0)=10 位址位址=0022FF54=0022FF54

– *tables[2]=5 **(tables+0)=5 **(ptr+0)=10 *tables[2]=5 **(tables+0)=5 **(ptr+0)=10 位址位址=0022FF58=0022FF58

– *tables[3]=19 **(tables+0)=19 **(ptr+0)=10 *tables[3]=19 **(tables+0)=19 **(ptr+0)=10 位位址址 =0022FF5C=0022FF5C

Page 34: 資料結構

2008/3/18 34

/* /* 程式範例程式範例 : Ch3-2-3.c */: Ch3-2-3.c */#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#define ROWS 4#define ROWS 4/* /* 主程式 主程式 **//int main() {int main() { /* /* 宣告變數 宣告變數 **// int i;int i; int values[ROWS] = { 10, 4, 5, 19 };int values[ROWS] = { 10, 4, 5, 19 }; /* /* 建立建立 intint 的指標陣列 的指標陣列 **// int *tables[ROWS];int *tables[ROWS]; int **ptr = &tables[0]; /* int **ptr = &tables[0]; /* 指向指標的指標變數 指向指標的指標變數 **/ / /* /* 指定指標陣列的元素值 指定指標陣列的元素值 **/ / for ( i=0; i < ROWS; i++)for ( i=0; i < ROWS; i++) tables[i] = &values[i]; /* tables[i] = &values[i]; /* 取得陣列元素位址 取得陣列元素位址 **/ / /* /* 顯示指標陣列的元素值 顯示指標陣列的元素值 **// printf("**ptr = &tables[0];\n");printf("**ptr = &tables[0];\n"); for ( i=0; i < ROWS; i++ ) {for ( i=0; i < ROWS; i++ ) { printf("*tables[%d]=%2d ", i, *tables[i]);printf("*tables[%d]=%2d ", i, *tables[i]); printf("**(tables+%d)=%2d ", i, **(tables + printf("**(tables+%d)=%2d ", i, **(tables +

i));i)); printf("**(ptr+%d)=%2d ", i, **(ptr + i));printf("**(ptr+%d)=%2d ", i, **(ptr + i)); printf("printf(" 位址位址 =%p\n", tables[i]);=%p\n", tables[i]); }} system("PAUSE");system("PAUSE"); return 0; return 0; • }}

Page 35: 資料結構

2008/3/18 35

3-3 3-3 指標與指標與結構結構 -- 宣告宣告• 指標也可以指標也可以指向結構指向結構。。

– 例如:宣告例如:宣告 labellabel 結構結構儲存員工的姓名和年齡,如下所儲存員工的姓名和年齡,如下所示:示:

struct label {struct label { char name[20];char name[20]; int age;int age;};};– 上述結構擁有上述結構擁有 22 個成員變數個成員變數– 因為指標需要指向結構變數的位址,所以需要因為指標需要指向結構變數的位址,所以需要先宣告先宣告

結構變數,然後才能建立指向結構的指標結構變數,然後才能建立指向結構的指標,如下所示:,如下所示:struct label worker;struct label worker;struct label *ptr;struct label *ptr;

Page 36: 資料結構

2008/3/18 36

3-3 3-3 指標與指標與結構結構 -- 存取存取• 接著接著將結構指標指向結構將結構指標指向結構,如下所示:,如下所示:

ptr = &worker;ptr = &worker;

• 結構指標結構指標 ptrptr 指向結構變數指向結構變數 workerworker 的位址,的位址,– 換個方式,可以換個方式,可以使用指標變數存取結構的成員變數使用指標變數存取結構的成員變數,,

如下所示:如下所示:(*ptr).age = 50;(*ptr).age = 50;– 程式碼相當於是程式碼相當於是 worker.age = 50;worker.age = 50; 。。

• CC 語言提供另一種語法,語言提供另一種語法,結構指標結構指標可以直接使用可以直接使用「「 ->-> 」運算子」運算子存取結構的成員變數存取結構的成員變數,如下所示:,如下所示:ptr->age = 50;ptr->age = 50;

Page 37: 資料結構

2008/3/18 37

程式範例程式範例 Ch3-3.cCh3-3.c

• 程式目標程式目標– 在在 CC 程式中宣告程式中宣告結構結構 labellabel 儲存員工資料儲存員工資料 , , 然後建立結然後建立結

構變數與指標構變數與指標 , , 分別使用分別使用結構變數結構變數與與指標指標來存取成員變來存取成員變數數 !!!!

• 執行結果如下執行結果如下– 姓名姓名 : : 陳會安陳會安– 年齡年齡 : 30: 30– 員工名牌 員工名牌 ------------------------– 姓名姓名 : : 陳會安陳會安– 年齡年齡 : 30: 30– 員工名牌 員工名牌 ------------------------

Page 38: 資料結構

2008/3/18 38

/* /* 程式範例程式範例 : Ch3-3.c */: Ch3-3.c */#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#include <string.h>#include <string.h>/* /* 結構結構 labellabel 的宣告 的宣告 **/ / struct label {struct label { char name[20];char name[20]; int age;int age;};};/* /* 函數函數 : : 顯示結構指標的成員變數 顯示結構指標的成員變數 **// void showlabel(struct label *ptr) {void showlabel(struct label *ptr) { printf("--------------------\n");printf("--------------------\n"); printf("printf(" 員工名牌員工名牌 \n"); \n"); printf("printf(" 姓名姓名 : %s\n", ptr->name);: %s\n", ptr->name); printf("printf(" 年齡年齡 : %d\n", ptr->age);: %d\n", ptr->age); printf("------------------\n");printf("------------------\n");}}

/* /* 主程式 主程式 **//int main() {int main() { /* /* 宣告變數 宣告變數 **// struct label worker;struct label worker; struct label *ptr;struct label *ptr; /* /* 將結構指標指向結構 將結構指標指向結構 **// ptr = &worker; ptr = &worker; /* /* 指定結構的成員變數 指定結構的成員變數 **// strcpy(worker.name, "strcpy(worker.name, " 陳會安陳會安 ");"); ptr->age = 30;ptr->age = 30;

printf("printf(" 員工基本資料員工基本資料 \n");\n"); printf("printf(" 姓名姓名 : %s\n", : %s\n",

worker.name);worker.name); printf("printf(" 年齡年齡 : %d\n", : %d\n",

worker.age);worker.age); /* /* 呼叫函數 呼叫函數 **// showlabel(ptr); showlabel(ptr); system("PAUSE");system("PAUSE"); return 0; return 0; }}

Page 39: 資料結構

2008/3/18 39

3-4 3-4 指標與字串指標與字串

• 3-4-1 3-4-1 指標與字串指標與字串• 3-4-2 3-4-2 字串的指標陣列字串的指標陣列

Page 40: 資料結構

2008/3/18 40

3-4 3-4 指標與字串指標與字串

• 在在 CC 語言的語言的字串字串是是一種字元陣列一種字元陣列,指標運算,指標運算也一樣適用在字元陣列的字串。也一樣適用在字元陣列的字串。– 例如:宣告一個字元陣列來儲存字串,其宣告如下所例如:宣告一個字元陣列來儲存字串,其宣告如下所

示:示:char line[80];char line[80];– 存取字元陣列元素存取字元陣列元素是使用是使用

line[0]line[0]、、 line[1]~line[79]line[1]~line[79] 來存取,如下所示:來存取,如下所示:line[i] = c;line[i] = c;– 在字元陣列的結束加上在字元陣列的結束加上字元字元 '\0''\0' 當作當作結束字元結束字元,如下,如下

所示:所示:line[i] = '\0';line[i] = '\0';

Page 41: 資料結構

2008/3/18 41

3-4-1 3-4-1 指標與字串指標與字串

• 字串指標字串指標是一個是一個 charchar 資料型態資料型態的指標,可以的指標,可以用來指向用來指向字元陣列字元陣列或或字串常數字串常數。。– 宣告一個宣告一個字元陣列字元陣列的字串,如下所示:的字串,如下所示:#define LEN 16#define LEN 16

char str[LEN] = "This is a book.";char str[LEN] = "This is a book.";– 上述字元陣列是一個字串且指定初值,接著上述字元陣列是一個字串且指定初值,接著宣告指標宣告指標

變數指向此字串變數指向此字串,如下所示:,如下所示:char *ptr = str;char *ptr = str;

Page 42: 資料結構

2008/3/18 42

程式範例程式範例 Ch3-4-1.cCh3-4-1.c

• 程式目標程式目標– 在在 CC 程式中宣告程式中宣告指標變數指標變數分別指向分別指向字元陣列的字串與字元陣列的字串與

字串常數字串常數 , , 然後使用然後使用指標運算指標運算來來複製字串內容複製字串內容 !!!!

• 執行結果如下執行結果如下– str = This is a book.str = This is a book.– ptr = This is a book.ptr = This is a book.– ptr1ptr1 = This is a book.= This is a book.– 將字串將字串 strstr 複製到複製到 str1:str1:– str1 = This is a book.str1 = This is a book.– ptr1ptr1 = This is a book.= This is a book.

Page 43: 資料結構

2008/3/18 43

/* /* 程式範例程式範例 : Ch3-4-1.c */: Ch3-4-1.c */#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#define LEN 16#define LEN 16/* /* 主程式 主程式 **//int main() {int main() { /* /* 字元陣列宣告 字元陣列宣告 **// char str[LEN] = "This is a char str[LEN] = "This is a

book.";book."; char str1[LEN];char str1[LEN]; /* /* 字元指標 字元指標 **// char *ptr = str;char *ptr = str; char *ptr1;char *ptr1; int i; int i; /* /* 顯示字串內容 顯示字串內容 **// ptr1 = "This is a pen.";ptr1 = "This is a pen."; printf("str = %s\n", str);printf("str = %s\n", str); printf("ptr = %s\n", ptr);printf("ptr = %s\n", ptr); printf("ptr1 = %s\n", ptr1);printf("ptr1 = %s\n", ptr1);

/* /* 字串複製的迴圈 字串複製的迴圈 **// printf("printf(" 將字串將字串 strstr 複製到複製到 str1: \n"); str1: \n"); i = 0;i = 0; ptr1 = str1;ptr1 = str1; while ( *ptr != '\0' ) {while ( *ptr != '\0' ) { *(ptr1+i) = *ptr++;*(ptr1+i) = *ptr++; i++;i++; }} *(ptr1+i) = '\0';*(ptr1+i) = '\0'; printf("str1 = %s\n", str1);printf("str1 = %s\n", str1); printf("ptr1 = %s\n", ptr1);printf("ptr1 = %s\n", ptr1); system("PAUSE");system("PAUSE"); return 0; return 0; }}

Page 44: 資料結構

2008/3/18 44

3-4-2 3-4-2 字串的指標陣列字串的指標陣列 -- 說明說明• CC 語言的語言的指標陣列指標陣列最常是應用在最常是應用在字串的指標字串的指標

陣列陣列,如下所示:,如下所示:#define ROWS 4#define ROWS 4

char *name[ROWS] = { "char *name[ROWS] = { " 陳會安陳會安 ", "", " 江小魚江小魚 ", "", " 張張無忌無忌 ", "", " 楊過楊過 " };" };

Page 45: 資料結構

2008/3/18 45

3-4-2 3-4-2 字串的指標陣列字串的指標陣列 -- 字字串交串交換換

• 使用指標陣列來儲存字串,使用指標陣列來儲存字串,– 不只可以節省記憶空間,而且因為是指標,不只可以節省記憶空間,而且因為是指標,如如

果指標陣列的元素需要交換字串,只需更改指果指標陣列的元素需要交換字串,只需更改指標指向的字串即可標指向的字串即可,如下圖所示:,如下圖所示:

Page 46: 資料結構

2008/3/18 46

程式範例程式範例 Ch3-4-2.cCh3-4-2.c• 程式目標程式目標

– 在在 CC 程式中宣告程式中宣告二維字元陣列二維字元陣列和和字串的指標陣列字串的指標陣列儲存數個字串儲存數個字串 , , 然後使用然後使用巢狀迴圈巢狀迴圈顯示各字串顯示各字串 !!!!

• 執行結果如下執行結果如下– 顯示二維字元陣列的內容顯示二維字元陣列的內容

• names[0]=[ names[0]=[ 陳會安 陳會安 ]]• names[1]=[ names[1]=[ 江小魚 江小魚 ]]• names[2]=[ names[2]=[ 張無忌 張無忌 ]]• names[3]=[ names[3]=[ 楊過 楊過 ]]

– 顯示指標陣列的內容顯示指標陣列的內容• name[0]=[ name[0]=[ 陳會安陳會安 ]]• name[1]=[ name[1]=[ 江小魚江小魚 ]]• name[2]=[ name[2]=[ 張無忌張無忌 ]]• name[3]=[ name[3]=[ 楊過楊過 ]]

Page 47: 資料結構

2008/3/18 47

/* /* 程式範例程式範例 : Ch3-4-2.c */: Ch3-4-2.c */#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#define ROWS 4#define ROWS 4#define COLUMNS 10#define COLUMNS 10/* /* 主程式 主程式 **//int main() {int main() { /* /* 宣告變數 宣告變數 **// int i, j;int i, j; /* /* 建立二維的字元陣列且指定初值 建立二維的字元陣列且指定初值 **// char names[ROWS][COLUMNS] = { "char names[ROWS][COLUMNS] = { " 陳會安陳會安 ", ",

" " 江小魚江小魚 ", "", " 張無忌張無忌 ", "", " 楊過楊過 " };" }; /* /* 指標陣列 指標陣列 **/ / char *name[ROWS] = { "char *name[ROWS] = { " 陳會安陳會安 ", "", " 江小魚江小魚 ",", "" 張無忌張無忌 ", "", " 楊過楊過 " };" }; char *ptr;char *ptr; /* /* 顯示二維陣列的元素值 顯示二維陣列的元素值 **// printf("printf(" 顯示二維字元陣列的內容顯示二維字元陣列的內容 : \n"); : \n"); for ( i = 0; i < ROWS; i++ ) {for ( i = 0; i < ROWS; i++ ) { printf("names[%d]=[", i);printf("names[%d]=[", i); ptr = names[i]; ptr = names[i]; for ( j = 0; j < COLUMNS; j++)for ( j = 0; j < COLUMNS; j++) printf("%c", *(ptr+j));printf("%c", *(ptr+j)); printf("]\n");printf("]\n"); } }

/* /* 顯示指標陣列的元素值 顯示指標陣列的元素值 **//

printf("--------------------\n");printf("--------------------\n"); printf("printf(" 顯示指標陣列的內容顯示指標陣列的內容 : \n");: \n"); for ( i = 0; i < ROWS; i++ ) {for ( i = 0; i < ROWS; i++ ) { printf("name[%d] =[", i);printf("name[%d] =[", i); ptr = name[i]; /* ptr = name[i]; /* 取得每一個指標 取得每一個指標

**/ / for ( j = 0; *(ptr+j) != '\0'; j++)for ( j = 0; *(ptr+j) != '\0'; j++) printf("%c", *(ptr+j));printf("%c", *(ptr+j)); printf("]\n");printf("]\n"); }} system("PAUSE");system("PAUSE"); return 0; return 0; }}

Page 48: 資料結構

2008/3/18 48

3-5 3-5 指標的應用 指標的應用 - - 字串處理字串處理(( 說明說明 ))

• CC 語言的語言的字串字串並不是一種基本資料型態,並不是一種基本資料型態,而是一種而是一種字元陣列字元陣列– 所以並沒有支援指定、連結和比較等運算子所以並沒有支援指定、連結和比較等運算子– 取而代之的是在標準函式庫取而代之的是在標準函式庫 <string.h><string.h> 提供提供多種字串處理函數。多種字串處理函數。

• 接下來接下來 , , 將討論一些基本字串函數的實作,將討論一些基本字串函數的實作,著重於說明如何設計這些字串函數所需的著重於說明如何設計這些字串函數所需的程式技巧,這些技巧都屬於指標的應用。程式技巧,這些技巧都屬於指標的應用。

Page 49: 資料結構

2008/3/18 49

3-5 3-5 指標的應用 指標的應用 - - 字串處理字串處理(( 標頭檔標頭檔 ))

01: /* 01: /* 程式範例程式範例 : Ch3-5.h */: Ch3-5.h */02: char str[81]; /* 02: char str[81]; /* 儲存字串的字元陣列 儲存字串的字元陣列 **//03: /* 03: /* 抽象資料型態的操作函數宣告 抽象資料型態的操作函數宣告 **//04: extern int strLen(char *str);04: extern int strLen(char *str);05: extern char *strCpy(char *dest, char *source);05: extern char *strCpy(char *dest, char *source);06: extern char *strCat(char *dest, char *source);06: extern char *strCat(char *dest, char *source);07: extern int strCmp(char *source, char *target);07: extern int strCmp(char *source, char *target);08: extern char *strPos(char *source, char *target);08: extern char *strPos(char *source, char *target);

Page 50: 資料結構

2008/3/18 50

3-5 3-5 指標的應用 指標的應用 - - 字串處理字串處理(1)(1)

函數函數 strLen()strLen() ::取得字串長度取得字串長度– 字串是一個字元陣列字串是一個字元陣列– 計算字串長度的方法就是計算字串長度的方法就是一維陣列的走訪和指一維陣列的走訪和指

標的遞增運算標的遞增運算,如下所示:,如下所示:char *ptr = str;char *ptr = str;while ( *ptr != '\0' ) ptr++;while ( *ptr != '\0' ) ptr++;return ptr - str;return ptr - str;– 上述程式碼使用上述程式碼使用 whilewhile 迴圈走訪到字串的最後迴圈走訪到字串的最後

11 個字元,然後使用個字元,然後使用 ptr-strptr-str 指標減法運算取指標減法運算取得字串長度。得字串長度。

Page 51: 資料結構

2008/3/18 51

strlen()strlen()• #include <string.h>#include <string.h>

size_t strlen(const char *s);size_t strlen(const char *s);////傳進來的常數不可改變內容傳進來的常數不可改變內容

• 計算字串的長度計算字串的長度 ,, 其單位長度以一個其單位長度以一個 bytebyte 為單位為單位 ,,但不包括’但不包括’ \0’\0’ 這個字元這個字元 ..

Page 52: 資料結構

2008/3/18 52

輸入一個字串輸入一個字串 , , 計算出該字串的長計算出該字串的長度度

#include <string.h> #include <string.h> #include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>

int main()int main(){{ char fun[80]; char fun[80]; int a;int a; printf("printf(" 請你輸入一字串請你輸入一字串 :\n");:\n"); gets(fun); gets(fun); a=strlen(fun); a=strlen(fun); printf("\nprintf("\n 此字串長度為此字串長度為 : %d",a); : %d",a); system("pause");system("pause"); return 0;return 0; }}

Page 53: 資料結構

2008/3/18 53

3-5 3-5 指標的應用 指標的應用 - - 字串處理字串處理(2)(2)

函數函數 strCpy()strCpy() ::字串複製字串複製– 字串複製是將字串內容複製到其它的字元陣列,其目字串複製是將字串內容複製到其它的字元陣列,其目

的是為了保留原始字串,以避免執行其它字串處理時,的是為了保留原始字串,以避免執行其它字串處理時,更改到原始字串的內容。如下所示:更改到原始字串的內容。如下所示:

char *ptr = dest;char *ptr = dest;

while ( (*ptr++=*source++) != '\0' );while ( (*ptr++=*source++) != '\0' );

return dest;return dest;– 上述程式碼使用上述程式碼使用 whilewhile 迴圈複製字串,因為先執行迴圈複製字串,因為先執行

**ptr++ptr++==*source++*source++ 指定運算指定運算,再進行比較,所以,再進行比較,所以連原始字串的結束字元也會複製到新字串。連原始字串的結束字元也會複製到新字串。

Page 54: 資料結構

2008/3/18 54

strcpy()strcpy()

• #include <string.h>#include <string.h>char *strcpy(char *dest, const char char *strcpy(char *dest, const char *src);*src);

• 將將 srcsrc 字串內容複製到字串內容複製到 destdest 字串中字串中 (( 包含包含空字元空字元 ).).

Page 55: 資料結構

2008/3/18 55

使用者輸入一個字串使用者輸入一個字串 ,, 程式會將該字程式會將該字串覆蓋原程式內定的字串串覆蓋原程式內定的字串

#include <stdio.h>#include <stdio.h>#include <string.h>#include <string.h>#include <stdlib.h>#include <stdlib.h>

int main()int main(){{ char target[30]="Hello Everyone",input[30];char target[30]="Hello Everyone",input[30]; printf("printf(" 請你輸入一字串請你輸入一字串 :");:"); gets(input);gets(input); printf("printf(" 原先的內定字串的內容為原先的內定字串的內容為 : %s\n",target);: %s\n",target); strcpy(target,input);strcpy(target,input); printf("printf(" 拷貝過後的字串內容拷貝過後的字串內容 : %s",target);: %s",target); system("pause");system("pause"); return 0;return 0;}}

Page 56: 資料結構

2008/3/18 56

3-5 3-5 指標的應用 指標的應用 - - 字串處理字串處理(3)(3)

函數函數 strCat()strCat() ::字串連結字串連結– 字串連結是將兩個字串結合成一個字串,也就是從第字串連結是將兩個字串結合成一個字串,也就是從第 11

個字串的最後開始複製第個字串的最後開始複製第 22 個字串。個字串。– 字串連結字串連結函數是函數是結合字串長度和複製函數結合字串長度和複製函數,如下所示:,如下所示:while ( *ptr++ != '\0' );while ( *ptr++ != '\0' );

ptr--;ptr--;– 上述程式碼使用上述程式碼使用 whilewhile 迴圈迴圈走訪到字串的最後走訪到字串的最後 11 個的個的

結束字元結束字元– 然後就使用迴圈然後就使用迴圈複製字串複製字串,如下所示:,如下所示:while ( (*ptr++=*source++) != '\0' );while ( (*ptr++=*source++) != '\0' );

Page 57: 資料結構

2008/3/18 57

strcat()strcat()

• #include <string.h>#include <string.h> char *strcat(char *dest, const char char *strcat(char *dest, const char *src);*src);

• 將將 srcsrc 字串內容連結到字串內容連結到 destdest 字串的結尾字串的結尾 ,,覆覆蓋蓋 srcsrc 字串的空字元’字串的空字元’ \0’,\0’, 並且保留本身並且保留本身的’的’ \0’.\0’.

• ..

Page 58: 資料結構

2008/3/18 58

使用使用 strcat()strcat() 函數函數 ,, 將兩個字串合將兩個字串合併為一併為一 ,, 並且將之輸出並且將之輸出

#include <stdio.h>#include <stdio.h>#include <string.h>#include <string.h>#include <stdlib.h>#include <stdlib.h>

int main()int main(){{ char first[20]="Hello ";char first[20]="Hello "; char last[]="Bill";char last[]="Bill"; printf("printf(" 合併前 合併前 first: %s last : %s\first: %s last : %s\

n",first,last);n",first,last); strcat(first,last);strcat(first,last); printf("printf(" 合併後 合併後 first: %s last : first: %s last :

%s",first,last);%s",first,last); system("pause");system("pause"); return 0;return 0;}}

Page 59: 資料結構

2008/3/18 59

3-5 3-5 指標的應用 指標的應用 - - 字串處理字串處理(4)(4)

函數函數 strCmp()strCmp() ::字串比較字串比較– 字串比較是比較兩個字串的內容字串比較是比較兩個字串的內容– 如果兩個字串完全相同的話,就傳回如果兩個字串完全相同的話,就傳回 00 ,如果不相同,,如果不相同,

使用使用 ASCIIASCII 的字元碼的字元碼比較不同的哪一個字元。比較不同的哪一個字元。– 函數是使用迴圈從頭開始比較兩個字串中的每一個字函數是使用迴圈從頭開始比較兩個字串中的每一個字

元,如下所示:元,如下所示:for ( ; *source == *target; source++, target++)for ( ; *source == *target; source++, target++) if ( *source == '\0')if ( *source == '\0') return 0;return 0;– 如果不相等,接著比較如果不相等,接著比較最後不相等的兩個字元最後不相等的兩個字元來決定來決定

字串大小,如下所示:字串大小,如下所示:if ((*source-*target) < 0 ) return -1;if ((*source-*target) < 0 ) return -1;else return 1;else return 1;

Page 60: 資料結構

2008/3/18 60

strcmp() strcmp() 比較字串比較字串• #include <string.h>#include <string.h>

int strcmp(const char *s1, const char int strcmp(const char *s1, const char *s2);*s2);

• 比較兩個字串比較兩個字串 str1str1跟跟 str2,str2, 比較其內容是比較其內容是否相同否相同 ,,若相同若相同 ,,則傳回則傳回 0; 0; 若不同若不同 ,,則比則比較兩個字串第一個不同字元的較兩個字串第一個不同字元的 ASCIIASCII碼碼 ,,若若 str1>str2,str1>str2, 則傳回正數則傳回正數 ,,反之反之 ,,則傳回則傳回負數負數 ..

Page 61: 資料結構

2008/3/18 61

設計一個程式設計一個程式 ,, 檢查輸入的字串是否檢查輸入的字串是否相同相同

#include <stdio.h>#include <stdio.h>#include <string.h> #include <string.h> #include <stdlib.h>#include <stdlib.h>

int main()int main(){{ char input1[30];char input1[30]; char input2[30];char input2[30]; int a;int a; printf("printf("請輸入第一個字串 請輸入第一個字串 ");"); gets(input1);gets(input1); printf("printf("請輸入第二個字串 請輸入第二個字串 ");"); gets(input2);gets(input2); a=strcmp(input1,input2); //a=strcmp(input1,input2); //比較字串比較字串

if(a==0)if(a==0) puts("puts("你輸入的兩個字串是相同的你輸入的兩個字串是相同的 !");!");

elseelse puts("puts("你輸入的是不相同的字串你輸入的是不相同的字串 !");!"); system("pause");system("pause"); return 0; return 0; }}

Page 62: 資料結構

2008/3/18 62

3-5 3-5 指標的應用 指標的應用 - - 字串處理字串處理(5)(5)

函數函數 strPos()strPos() ::子字串的搜尋子字串的搜尋• 子字串的搜尋是指在原始字串中找尋子字串的搜尋是指在原始字串中找尋某特定字串是否存在某特定字串是否存在

– 如果存在,這個特定字串就是原始字串的如果存在,這個特定字串就是原始字串的子字串子字串。。• 函數使用函數使用二層的巢狀迴圈二層的巢狀迴圈來執行字串比較,如下所示:來執行字串比較,如下所示:

while ( *s != '\0' ) {while ( *s != '\0' ) { ptr = s;ptr = s; t = target;t = target; while ( *t != '\0' && *ptr == *t ) {while ( *t != '\0' && *ptr == *t ) { ptr++; t++;ptr++; t++; }} if ( *t == '\0' ) return s;if ( *t == '\0' ) return s; s++;s++;}}