C語言字串總結
c語言中的c風格字串常有以下兩種儲存方式,做一個總結,希望以後不需要再出現模稜兩可。
char陣列
如果是char str[5]= {'a','b','c','d','e'},這存的就是一個字元陣列,而不是一個字串
如果是char str[6]= {'a','b','c','d','e','\0'} 這寸的就是一個字串 為“abcde” (c風格的字串),要留出一個空間儲存\0表示字串終止,等價於如下定義方式:
char str[6] = "abcde"
可以看出c風格的字串 如果是用陣列方式定義的,就要在字串長度的基礎上 + 1用來儲存\0,
char 指標
還有一種可以儲存字串的方式就是使用char型別的指標,比如
char *str = "abcde"
這種方式要注意,str儲存的並不是字串的內容,而是字串的起始地址,在visual studio 的debug模式下,能看到str的值通常為 地址+ 字串內容比如0x7fffffffeffc "abcde"表示str指向的地址,(也就是字元a的地址)也就是str指標的值是0x7fffffffeffc,以這個地址為起始地址的字串的值是“abcde”
當使用printf()輸出時,格式化時選擇%s,會輸出abcde,這是printf遇到結尾符號‘\0’即停止顯示列印。
所以在使用char 型別的指標儲存字串的時候會發生很多意想不到的錯誤及問題,這就是C語言中指標讓人頭疼的地方。
與字串有關的輸入輸出函式
以下說的所有字串都是用陣列儲存的
scanf
scanf輸入一個字串而且是遇見空格就會停,比如輸入“hello world”之後,他只會讀入hello。要使用scanf("%s%s",str1,str2),才能讀入hello 和world,而且hello存在str1中,world存在str2中。
scanf("%s",str);是沒有取地址符號的,而且系統會自動在str最後補上\0
while(scanf("%s",str) != 1) 作用是持續讀入資料 在讀不到資料的時候停止迴圈
gets,puts
gets(str)就是從游標開始的地方讀到換行符,和scanf的區別就是空格也能被讀入,只有輸入回車才會停止讀入
puts(str)就是輸出一個字串和一個換行符,等價於printf("%s\n",str);
cin>>str1>>str2
這個也可以直接讀入兩個字串
其他函式
strcat(s1,s2) 將字串s2連線到s1之後
strcpy(s1,s2) 將字串2複製到字串1,返回字串1的值。
strcmp(s1,s2) 比較字串1和字串2的大小。如果1 > 2 返回正數,如果兩字串完全相等返回0,如果1< 2返回負數
strlen(s1) 計算字串的長度,而且不把\0算進去
strlwr(str) 將字串全部轉化為小寫
strupr(str),將字串全部轉化為大寫。
使用上述函式 如果是在c語言中要包含string.h標頭檔案,如果是在c++中要包含cstring,也可以包含string.h標頭檔案,兩者區別在於cstring是對string.h標頭檔案進行了一些修改讓它更能相容c++罷了
C字串的儲存問題
程式的記憶體分配基礎,看我的另一篇部落格https://www.cnblogs.com/yizhanwillsucceed/p/13578076.html
C字串一般放在常量區,data段上.而且陣列方式儲存和指標方式有著很大區別。
看下面這個例子
//main.cpp
int a = 0; 全域性初始化區
char *p1; 全域性未初始化區
main()
{
int b; 棧
char s[] = "abc"; 陣列方式儲存的字串存放在棧上,“abc”
char *p2; 棧
char *p3 = "123456"; 123456\0在常量區(Data段),p3在棧上。
static int c =0; 全域性(靜態)初始化為0(放在BSS段),就是
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得來得10和20位元組的區域就在堆區。但是p1,p2指標是存在棧中的
strcpy(p1, "123456"); 123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。所以這個地方有時候會導致意想不到的錯誤。
}
一定注意:陣列s儲存的內容是在執行的時候賦值的,但是指標p3指向的常量區中的字串內容是編譯時就賦值的。