山不在高,有仙則名。水不在深,有龍則靈。 ----CSDN 時時三省
如在printf函數中輸出一個字符串。這些字符串都是以直接形式(字面形式)給出的,在一對雙撇號中包含若干個合法的字符。使用字符串的更加靈活方便的方法——通過指針引用字符串。
字符串的引用方式
在C程序中,字符串是存放在字符數組中的。想引用一個字符串,可以用以下兩種方法。
( 1 )用字符數組存放一個字符串,可以通過數組名和下標引用字符串中一個字符,也可以通過數組名和格式聲明“% s”輸出該字符串。
例題1:
定義一個字符數組,在其中存放字符串" I love China !”,輸出該字符串和第8個字符。
解題思路:
定義字符數組string,對它初始化,由于在初始化時字符的個數是確定的,因此可不必指定數組的長度。用數組名string和輸出格式%s可以輸出整個字符串。用數組名和下標可以引用任一數組元素。
編寫程序:
運行結果:
程序分析:
在定義字符數組string時未指定長度,由于對它初始化,因此它的長度是確定的,長度應為14,其中13個字節存放" I love China ! "13個字符,最后一個字節存放字符串結束符' \0 '。數組名string代表字符數組首元素的地址。題目要求輸出該字符串第8個字符,由于數組元素的序號從0起算,所以應當輸出string [ 7 ],它代表數組中序號7的元素的值(它的值是字母C)。實際上string [ 7 ]就是* ( string + 7 ),string + 7是一個地址,它指向字符“C”。
( 2 )用字符指針變量指向一個字符串常量,通過字符指針變量引用字符串常量。
例題2:
通過字符指針變量輸出一個字符串。
解題思路:
可以不定義字符數組,只定義一個字符指針變量,用它指向字符串常量中的字符。通過字符指針變量輸出該字符串。
編寫程序:
運行結果:
I love China!
程序分析:
在程序中沒有定義字符數組,只定義了一個char*型的指針變量(字符指針變量)string,用字符串常量" I love China !”對它初始化。C語言對字符串常量是按字符數組處理的,在內存中開辟了一個字符數組用來存放該字符串常量,但是這個字符數組是沒有名字的,因此不能通過數組名來引用,只能通過指針變量來引用。
對字符指針變量string初始化,實際上是把字符串第1個元素的地址(即存放字符串的字符數組的首元素地址)賦給指針變量string,使string指向字符串的第1個字符,由于字符串常量“Ilove China !”已由系統分配在內存中連續的14個字節中,因此,string就指向了該字符串的第一個字符。在不致引起誤解的情況下,為了簡便,有時也可說string指向字符串" I love China !”,但應當理解為“指向字符串的第1個字符”。
說明:有人誤認為string是一個字符串變量,以為在定義時把“I love China !”這幾個字符賦給該字符串變量,這是不對的。在C語言中只有字符變量,沒有字符串變量。
分析定義string的行:
char * string = " I love China !”;
等價于下面兩行:
char * string ;
string = " I love China ! ";
注意:string被定義為一個指針變量,基類型為字符型。請注意它只能指向一個字符類型數據,而不能同時指向多個字符數據,更不是把“Ilove China ! "這些字符存放到string中(指針變量只能存放地址),也不是把字符串賦給* string。只是把" I love China !”的第1個字符的地址賦給指針變量string。
不要認為上述定義行等價于
char * string ;
* string = " I love China !”;
可以對指針變量進行再賦值,如:
string = " I am a student , " ;
把字符串" I am a student .”的第一個字符的地址賦給指針變量string。此后string就指向" I am a student .”的第一個字符,不再指向" I love China !”的第一個字符了,因此不能再通過string引用字符串" I love China !”。
可以通過字符指針變量輸出它所指向的字符串,如:
printf ( " % s\n " , string );
% s是輸出字符串時所用的格式符,在輸出項中給出字符指針變量名string,則系統會輸出string所指向的字符串第1個字符,然后自動使string加1,使之指向下一個字符,再輸出該字符…如此直到遇到字符串結束標志 \0 為止。注意,在內存中,字符串的最后被自動加了一個\0 ,因此在輸出時能確定輸出的字符到何時結束。可以看到,用%s可以對一個字符串進行整體的輸入輸出。
?
對字符串中字符的存取,可以用下標方法,也可以用指針方法。
例題3:
將字符串a復制為字符串b,然后輸出字符串b。
解題思路:
定義兩個字符數組a和b,用“I am a student .”對a數組初始化。將a數組中的字符逐個復制到b數組中。可以用不同的方法引用并輸出字符數組元素,今用地址法算出各元素的值。
編寫程序:
運行結果:
程序分析:?
程序中a和b都定義為字符數組,今通過地址訪問其數組元素。在for語句中,先檢查a [ i ]是否為 \0 ?( a [ i ]是以* ( a + i )形式表示的)。如果不等于 \0 ,表示字符串尚未處理完,就將a [ i ]的值賦給b [ i ],即復制一個字符。在for循環中將a串中的有效字符全部復制給了b數組。最后還應將\0復制過去,作為字符串結束標志。故有
* ( b + i ) =' \0 ';
在第2個for循環中輸出b數組中的元素,在printf函數中用下標法表示一個數組元素(即一個字符)。也可以用輸出a數組的方法輸出b數組。用以下一行代替程序的10?~13行。
printf ( " string b is : % s\n " , b ) ;
程序中用逐個字符輸出的方法只是為了表示可以用不同的方法輸出字符串。
也可以用另一種方法,用指針變量訪問字符串。通過改變指針變量的值使它指向字符串中的不同字符。
例題4:
用指針變量來處理例3問題。
解題思路:
定義兩個指針變量p1和p2,分別指向字符數組a和b。改變指針變量pl和p2的值,使它們順序指向數組中的各元素,進行對應元素的復制。
編寫程序:
運行結果:
程序分析:?
p1和p2是指向字符型數據的指針變量。先使p1和p2分別指向字符串a和b的第1個字符。*p1最初的值是字母' I '。賦值語句“* p2 = * p1;”的作用是將字符' I ' ( a串中第1個字符)賦給p2所指向的元素,即b[ 0 ]。然后p1和p2分別加1,分別指向其下面的一個元素,直到*p1的值為'\0'止。
注意,p1和p2的值是不斷在改變的,在for語句中的p1 ++和p2++使pl和p2同步移動。