C Primer+Plus(十一)
第11章 字符串和字符串函數
11.1字符串表示和字符串I/O
11.1.1在程序中定義字符串
字符串定義:
char s[10]="iamaboy!";//這是字符串
char s[]="uareagirl";//這是字符串
char *ps="heishandsome."; ?//這是字符串
char s[3]={'A','b','x'}; ?//這是字符數組,而非字符串
char s[3]={'A','b','x','\0'}; ?//增加字符串標志符,表示字符串?
一、字符串常量
字符串常量屬于靜態存儲類(static storage),是指如果在一個函數中使用字符串常量,即使多次調用了這個函數,該字符串在程序的整個運行過程只存儲一份。定義中引號的內容作為指向該字符串存儲位置的指針。
例11.2
#include<stdio.h> int main(void) {printf("%s,%p,%c\n","We","are",*"student wang");return0; } //輸出: //We,內存單元地址編號,s二、字符串數組及其初始化
const char m[40]="limit yuorself to one line's worth.";
//const表明變量m只讀,不可寫入。
//這小節想說明啥?字符串數組?標題寫錯了估計,應該是字符數組。
三、數組和指針
對于:
const char *m3[]="I am chinese.";
char m1[]="I am chinese.";
數組形式m1[]在內存中被分配“實際字符串內字符數量+1(字符串結束標志符)”個元素的數組空間(這里因為數組元素為字符),最后一個數組內存放'\0'。通常,被引用的字符串存儲在可執行文件的數據段部分,當程序被加載到內存中時,字符串也被加載到內存中。被引用的字符串位于靜態存儲區。但是程序運行后才開始為數組分配存儲空間,并把靜態存儲區的字符串數據依次復制到該數組存儲區。此后,編譯器會把數組名m1看成數組收元素的地址&m1[0]的同義詞,即一個地址常量,無法更改。
而指針形式(*m3)也在靜態存儲區為字符串預留“實際字符串內字符數量+1(字符串結束標志符)”個元素的空間;并且在程序執行后,系統要為變量m3預留一個存儲位置,變量m3初始指向靜態存儲區中字符串的首地址。m3為變量,可改變,如m3+=2;即使得m3指向了字符串第三個字符。另外,對于const char *m3[]...表示的含義是“指針變量m3指向的目標區域內的數值不能被修改”。
//重要的一個知識點
四、數組和指針的差別
對于:
char s1[]="...";
char *s2="...";
s1和s2均可以使用數組符號和指針加法:*(s1+1),s2[3];
區別在于s1如前面所說,為常量,不能改變,如不能進行自增減操作。
而s2是變量,是可以改變的。
五、字符串數組
對于:
const char *p[3]={"ts1","ts22","ts333"}; ? //定義方法1
//每個數組元素均為指向字符串首地址的指針
//而字符串又類似于一個字符數組,因此字符串數組也類似于二維字符數組,只不過各行的列數未必一致
p[0]="ts1";p[1]="ts22";p[2]="ts333";
*p[0]='t';*p[1]='t';
p[0][0]='t';p[2][2]='3';//這里也可看出與二維數組的類似。
同樣也可以用二維數組方式定義字符串數組:
char p[3][6]={"ts1","ts22","ts333"}; ? //定義方法2
方法1中各行的列數不一致,而這也可以節省存儲空間,因為每個字符串內部的字符在內存中連續存放,而各個字符串之間在內存空間中未必是連續的,這不影響邏輯關系上的依序。而方法二用二維數組方式的定義,一方面,各個字符串之間在內存空間里是連續的;另外一方面,為滿足列數的一致,對不足的列數要用‘\0'進行填充。
引申:為何兩種方式在各個字符串的存儲連續與否有區別?回顧前面數組和指針的區別,可以注意到:第一種方法是指針,指針引用的是靜態存儲區的地址;而數組方法是程序運行到數組定義時候分配一段連續空間以存放該數組,再將靜態存儲區中的字符串復制。
11.2字符串輸入
11.2.1創建存儲空間
例:
char *name;
scanf("%s",name);
//上述有問題么?
//有。第一句定義了字符指針變量,但未賦值,未賦值的指針是不能使用的;盡管這兩句也許可以通過編譯。
//正確方法如下:
char name[81]; ? //之前說到在程序運行到這句時,系統會給分配81個數組元素空間,一旦分配,即name的地址是確定的。
scanf(“%s”,name);
11.2.2gets()函數
gets()函數的返回值是字符串的地址。
11.2.3fgets()函數
gets()函數不檢查預留存儲區是否有足夠容納字符串的空間。fgets()提供參數可指定最大讀入字符數。
gets()函數讀取到換行符時則停止讀入,并丟棄換行符。而fgets()結束的標志是指定的讀取最大數-1個字符或者讀取到換行符則停止,但不丟棄換行符。
gets()函數是針對基本輸入文件,即鍵盤的讀入;而fgets()是針對文件的操作。因鍵盤也是屬于文件(基本輸入文件),fgets()也可對鍵盤讀入,只是要在第三個參數中明確為stdin(鍵盤文件);
11.2.4scanf()函數
11.3字符串輸出
puts()/fputs()/printf()
11.4自定義輸入輸出
11.5字符串函數
ANSI C用頭文件string.h給出字符串操作庫函數:
11.5.1 strlen()
返回值為字符串實際長度,不含結束標識符’\0'。
11.5.2strcat()
將第二個參數指向的字符串加到第一個結尾,返回值為第一個參數,即新字符串的首地址(其實該地址不變)。
11.5.3strncat()
與strcat()功能相同,只是多個參數指定最多添加的字符數量。
strncat(s1,s2,5);//將s2加到s1結尾處,當加了5個字符后或s2已結束后結束。
11.5.4strcmp()
若兩相比的字符串完全相同,則返回0;
若依序比較,直到第一對不相同的字符出現時候,若第一個字符串對應字符在ASCII碼表中順序位于第二個字符串對應字符之后(即大于),則返回正數,反之則負數。
11.5.5strncmp()
例:strcmp(s1,s2,int m) ?僅針對兩字符串中前m個字符進行比較。
*更多字符串函數詳見P307-308
?
?
?
?
?
轉載于:https://www.cnblogs.com/tsembrace/p/3144921.html
總結
以上是生活随笔為你收集整理的C Primer+Plus(十一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用post向webservice发送请
- 下一篇: spring mybatis 集成