《c++ primer》5——c風格字符串

字符串字面值的類型就是const char類型的數組。

c風格字符串

c風格字符串既不能確切地歸結爲C語言的類型,也不能歸結爲c++類型,而是以空字符null結束的字符數組。

     char ch1[] = { 'a', 'b', 'c' };
     char ch2[] = { 'a', 'b', 'c', '\0' };
     char ch3[] = "abc";
     char *ch = ch2;    
可以理解成沒有以\0結尾的字符數組只是普通的字符數組,而以\0結尾的字符數組,就是字符串,c風格的字符串。

1.c風格字符串的使用
int main()
{
     char s[] = "hello";
     char *ps = s;
     cout << s << endl;
     cout << ps << endl;
     while (*ps)//若*ps==null則循環終止
     {
          *ps = toupper(*ps);
          ++ps;
     }
     cout << s << endl;
     //cout<<ps<<endl;注意此時輸出ps指向的字符串沒有意義,因爲ps指向的位置早已到了字符串末端的下一個位置
     getchar();
     return 0;

}
如果ps指向的字符串中沒有\0(null結束符)則會一直循環下去,知道在內存中找到\0

2.c風格字符串的標準庫函數
使用時,添加頭文件
#include <cstring>
strlen(s)
strcmp(s1,s2)
strcat(s1,s2)
strcpy(s1,s2)
strncat(s1,s2,n)
strncpy(s1,s2,n)

3.永遠不要忘記字符串結束符null
int main()
{
     char ch[] = { 'a', 'b', 'c' };
     char ch1[] = { 'a', 'b', 'c' ,'\0'};
     cout << strlen(ch) << endl;
     cout << strlen(ch1) << endl;
     getchar();
     return 0;
}
對於第一種輸出情況,結果是不確定的,strlen遍歷字符串,知道遇到空字符才停止,所以一定不要忘記空字符。

4.調用者必須保證目標字符串具有足夠的大小
在調用strcpy和strcat等函數時,strcpy(char*,char*);必須確保第一個實參數據有足夠的大小,能夠實現字符串的拷貝,並且在第二個實參長度發生變化時,第一個參數需要做適當的調整。

5.使用strn函數處理c風格字符串
strncpy和strncat在複製和連接函數時能夠控制複製和連接的函數的個數
int main()
{
     char *ch1 = "hello";
     char *ch2 = "world";
     char ch3[20];
     strncpy(ch3, ch1, 6);//複製ch1中6個字符到ch3,包括null
     cout << ch3 << endl;
     cout << strlen(ch3) << endl;//輸出ch3字符串的長度,不包括null
     strncat(ch3," ", 2);//ch3連接兩個字符,一個空格,一個null字符,其中空格會覆蓋前面的null
     cout << strlen(ch3) << endl;//共有7個字符,字符串的長度爲6
     strncat(ch3, ch2, 6);//ch3連接ch2中6個字符,包括null,最前面的字符會覆蓋前面的null
     cout << ch3 << endl;
     cout << strlen(ch3) << endl;
     getchar();
     return 0;
}

6.儘可能的使用標準庫類型string
標準庫將負責處理所有的內存管理問題



創建動態數組

普通數組在編譯時必須知道其長度,動態數組則不必在編譯時知道其長度,可以在運行時確定數組長度
普通數組只在定義他的域內存在,動態數組則一直存在,直到程序顯式釋放
普通數組與動態數組長度都是固定的。
堆區(heap)是程序在運行過程用於存放動態分配的對象的內存空間。

1.動態數組的定義和初始化
int *p=new int[10];//返回分配的內存空間的第一個位置的指針。
初始化:
1)數組元素是類類型,用該類的默認構造函數初始化
2)數組元素是內置類型,不會初始化,可以顯式的初始化
     int *p=new int[10]();
注意:只能初始化爲元素的默認值,不能像數組一樣,用初始化列表提供各個元素的初值
int main()
{
     int *p = new int[10]();
     for (size_t index = 0; index != 10; ++index)
     {
          cout << p[index] << " ";
     }
     cout << endl;
     getchar();
     return 0;
}
int類型的默認值0,char類型的默認值空白字符(空格)

2.const對象的動態數組:
const對象在創建時必須進行初始化
const int *p=new int[10];//error
const int *p=new int[10]();//ok
const string *s=new string[10];//ok default construct function

3.允許動態分配空數組:
char ch[0];//error不允許創建0長度的數組
char *pc=new char[0];//ok
用new創建長度爲0的數組時,new返回有效的非零指針,該指針與new返回的其他指針不同,不能進行解引用操作,因爲他沒有指向任何對象,允許進行比較運算。

4.動態空間的釋放
delete [] p;//釋放p指向的數組,把相應的內存還給自由存儲區(堆區)
[]表示指針指向的是自由存儲區的數組,而非單個對象
int main()
{
     int *p = new int[10];
     for (size_t index = 0; index != 10; ++index)
     {
          p[index] = index;
          cout << p[index] << " ";
     }
     cout << endl;
     cout << p << endl;
     delete[] p;
     cout << p << endl;//空間釋放後,p指向的位置發生變化
     getchar();
     return 0;


}


新舊代碼兼容:

1.混合使用標準庫類string和c風格字符串

c風格字符串和字符串字面值具有相同的數據類型,因此可以把c風格字符串用在任何可以使用字符串字面值的地方:
int main()
{
     char *s = "hello world";
     string s1(s);//ok
     string s2("hello world");//ok
     cout << s << endl << s1 << endl;
     cout << s << endl << s2 << endl;
     getchar();
     return 0;

}
2.在要求c風格字符串的地方不可直接使用標準庫string類型對象
int main()
{
     string s("hello world");
     //char *p = s;//error
     //char *p1 = s.c_str();c_str()返回const類型的c風格字符串
     const char *p2 = s.c_str();

     cout << p2 << endl;
     getchar();
     return 0;
}
c_str()返回const類型的c風格字符串。
注意:如果下面的操作改變s的值,則函數的返回值會失效,所以如果持續訪問s數據,則應該複製c——str的返回值
int main()
{
     string s("hello world");
     //char *p = s;//error
     //char *p1 = s.c_str();
     const char *p2 = s.c_str();
     s = "hello";
     cout << p2 << endl;
     getchar();
     return 0;
}
運行結果輸出hello

3.使用數組初始化vector對象
必須指出初始化數組的第一個元素和最後一個元素的下一個位置
int a[]={1,2,3,4,5,6};
vector<int> ivec(a,a+3);//1,2,3






























































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章