一,C語言的字符串 在C語言裏,對字符串的處理一項都是一件比較痛苦的事情,因爲通常在實現字符串的操作的時候都會用到最不容易駕馭的類型——指針。 比如下面這個例子: //example 1: char str[12] = "Hello"; char *p = str; *p = ''h''; //改變第一個字母
//example 2: char *ptr = "Hello"; *ptr = ''h''; //錯誤
第一個字符串時用數組開闢的,它是可以改變的變量。而第二個字符串則是一個常量,也就是字面值。ptr只是指向它的指針而已,而不能改變指向的內容。 看兩者的彙編即可明瞭: char p[] = "Hello"; char *ptr = "Hello"; 可見用數組和用指針是完全不相同的。 要想通過指針來改變常量是錯誤,正確的寫法應該是用const指針。 const char *ptr = "Hello";
二,初識string類 正是因爲C風格字符串(以空字符結尾的字符數組)太過複雜難於掌握,不適合大程序的開發,所以C++標準庫定義了一種string類,定義在頭文件<string>。注意<string.h>和<cstring>都是錯誤的,這兩個頭文件主要定義C風格字符串操作的一些方法,譬如strlen(), strcpy()等。第一個是C的頭文件格式,而第二個是C++風格的頭文件,但是和<string.h>是一樣的,它的目的是爲了和C兼容。 看下面例子: //example 3: string str("world"); //可以用C風格字符串初始化 string words = "Hello"; string greet = words; string join = greet + words; //可以像基本類型一樣操作
但是如果試圖把string類型的對象直接賦給C風格的字符串的話,編譯器會報錯的。 string var = "**"; char *ptr = var; //error!
但是實際應用中這個問題也難以避免,很多時候我們還是需要將string類型的轉化爲char*來實現自定義的操作,C++標準庫也爲了和之前用C寫的程序兼容,於是可以用string的c_str()函數。 string var = "**"; char *ptr = var.c_str(); //還不能被編譯
但是c_str()爲了防止意外地修改string對象,返回的是const指針,所以上面這段代碼是不能被編譯的。正確的應該是用const指針。 string var = "**"; const char *p = var.c_str(); //Correct!
這個c_str()方法在C++IO流操作上也被廣泛應用。 在打開文件時,如果要指定文件名,可以用C風格的字符串。如果用到string類型的字符串作爲文件名時,就必須調用c_str()方法將其轉換爲一個C風格字符串。 //example 4: string filename; //定義文件名稱 cin >> filename; ifstream.open(filename.c_str()); //要使用C風格字符串
三, 深入瞭解string類 對string有一定了解以後,我們可以來了解C++標準庫定義的一系列豐富的字符串操作,當然都是基於string類型。從某一種程度上來說,string就是一種字符容器。 標準庫爲string定義了很多方法,包括構造、插入(insert)、替換(assign和replace)、比較(compare)、查找(find)、刪除(erase)、連接(append)以及對子串的操作(substr)。而每一種操作都有很多種重載。 比如插入,除了包括標準容器的插入方式以外,string類本身還有一些特有的插入方法。 //example 5: //與標準容器相同的插入操作: str.insert(iter, value) //在迭代器iter之前插入value, 返回新元素的迭代器 str.insert(iter, n, value); //在迭代器iter之前插入n個value,返回void str.insert(iter, begin, end); //在迭代器iter之前插入迭代器begin和end標記範圍內的元素,返回void //string類特有的插入方法: str.insert(pos, n, ch); //在下標爲pos的字符之前插入n個字符ch str.insert(pos, str2); //在下標爲pos的字符之前插入string類型的對象str2的副本 str.insert(pos1, str2, pos2, len); //在下標爲pos1的z字符之前插入string類型str2中從下表爲pos2開始的len個字符 str.insert(pos, cp); //在下標爲pos的字符前插入字符指針cp指向的C風格字符串的副本
總之string是一種非常靈活的字符串類型,標準庫讓我們可以忽略內存管理和具體實現方式,我們只需要關注其接口就好。並且初學者在使用字符串的時候也應儘量使用這種類型,而不是C風格的字符串。 當然,無C語言學習經歷的人可以例外。
參閱書籍: <C++ Primer 4th>Stanley Lippman <The C++ Programming Language> Bjarne Stroustrup> |