【共讀Primer】19.<3.5> 數組-C風格字符串 Page109
阿新 • • 發佈:2018-08-13
lar 空格 特性 world 程序 c++ ges world! 所有
C風格的字符串是指以空字符‘\0’結尾的一個字符串。
這種字符串雖然在C++中兼容,但是極易引起內存安全問題,所以不建議使用。
但是作為一個語言特性,我們應該了解它,這樣才能在碰到的時候做到心中有數。
3.5.4 C標準庫string函數
這裏所說的string函數並不是std::string的函數,而是在C的標準庫中,對C風格字符串進行操作的一些全局函數。
strlen(p); //計算p的長度,不計入空字符結尾 strcmp(p1, p2); // 比較兩個字符串p1和p2是否相等,相等返回0,p1>p2返回正值, p1<p2返回負值 strcat(p1, p2); //將p2附加到p1後,返回p1 strcpy(p1, p2); // 將p2拷貝給p1, 返回p1
觀察以上函數,它們正常運行的基礎條件是在結尾有一個‘\0‘的空字符,如果這個條件沒有達到
,那麽對於上述的任何一個函數來說結果都將是災難性的。
對於下面的兩行代碼來說,返回的結果將是一個未知的值,因為ca這個字符串並沒有以空為結尾。
char ca[] = {‘C‘, ‘+‘, ‘+‘}; cout << strlen(ca) << endl;
比較字符串
在C風格的字符串進行比較的時候我們需要使用到strcmp函數來進行比較,而不是直接使用邏輯判斷符號進行比較
// 使用C++的string類型進行比較 string s1 = "A string example"; string s2 = "A different string"; if (s1 < s2) // false: s2 小於 s1 { cout << "s1 < s2" << endl; } else { cout << "s1 > s2" << endl; } // 直接使用C風格的字符串進行比較 constchar ca1[] = "A string example"; const char ca2[] = "A different string"; // if ( ca1 < ca2 ) // 這樣的比較結果是未定義的,因為比較的內容是兩個指針的值 if (strcmp(ca1, ca2)) // 這樣的寫法才會使結果與string對象的比較相同。 { cout << "s1 < s2" << endl; } else { cout << "s1 > s2" << endl; }
拼接字符串
我們在對C風格的字符串進行拼接的時候需要使用到如下的方法。
string largeStr = s1 + " " + s2; // 這種以加號的連等來拼接的方式不適用於C風格的字符串 // char ca3 = ca1 + " " + ca2; // 這個表達式是錯誤的 // 針對C風格的字符串我們需要使用一下的方式來拼接 strcpy(largeStr, ca1); // 把 ca1拷貝給largeStr strcat(largeStr, " "); // 把largeStr的末尾加上一個空格 strcat(largeStr, ca2); // 把 ca2連接到largeStr後面
但是一個潛在的問題是largeStr所需要的控件是不容易準確估計的,而一旦代碼發生改變,這個問題很可能被忽略,因為並不是每次都會出問題。
這將會成為程序運行的一個潛在風險
3.5.5 與舊代碼的接口
這裏的一些操作是,可以使用C風格字符串初始化string或對它進行賦值,在使用在加法操作中,允許使用C風格的字符串進行操作,但必須保證有string的出現。
string s("Hello World"); // s 使用C風格字符串進行初始化 // char *Cstr = s; // 這個等式是不成立的 const char *str = s.c_str(); // 將 string的對象內容返回為一個C風格的字符串
char Cstr[30] = {0};
stpcpy(Cstr, s.c_str());
而在上述代碼的最後一行中,我們無法保證c_str()的返回值一直有效,更安全的做法是對返回的C風格字符串進行拷貝。
// 使用數組來進行vector的初始化, begin和end兩個函數是C++11特性 int int_arr[] = {0,1,2,3,4,5}; vector<int> ivec(begin(int_arr), end(int_arr));
雖然以上代碼是正確的,但是非常不建議使用,因為對指針的操作總是存在一定的危險性。
以下是所有代碼,可編譯的版本,大家可自行編譯執行或修改來查看變化。
#include <iostream> #include <string> #include <vector> using std::cout; using std::endl; using std::string; using std::vector; using std::begin; using std::end; int main() { char p[] = "Hello World!"; char p1[] = "Hello World!p1"; char p2[] = "Hello World!p2"; strlen(p); //計算p的長度,不計入空字符結尾 strcmp(p1, p2); // 比較兩個字符串p1和p2是否相等,相等返回0,p1>p2返回正值, p1<p2返回負值 strcat(p1, p2); // 將p2附加到p1後,返回p1 strcpy(p1, p2); // 將p2拷貝給p1, 返回p1 char ca[] = {‘C‘, ‘+‘, ‘+‘}; cout << strlen(ca) << endl; // 使用C++的string類型進行比較 string s1 = "A string example"; string s2 = "A different string"; if (s1 < s2) // false: s2 小於 s1 { cout << "s1 < s2" << endl; } else { cout << "s1 > s2" << endl; } // 直接使用C風格的字符串進行比較 const char ca1[] = "A string example"; const char ca2[] = "A different string"; // if ( ca1 < ca2 ) // 這樣的比較結果是未定義的,因為比較的內容是兩個指針的值 if (strcmp(ca1, ca2)) // 這樣的寫法才會使結果與string對象的比較相同。 { cout << "s1 < s2" << endl; } else { cout << "s1 > s2" << endl; } string largeStr = s1 + " " + s2; // 這種以加號的連等來拼接的方式不適用於C風格的字符串 // char ca3 = ca1 + " " + ca2; // 這個表達式是錯誤的 // 針對C風格的字符串我們需要使用一下的方式來拼接 char largeCStr[30] = {0}; strcpy(largeCStr, ca1); // 把 ca1拷貝給largeStr strcat(largeCStr, " "); // 把largeStr的末尾加上一個空格 strcat(largeCStr, ca2); // 把 ca2連接到largeStr後面 string s("Hello World"); // s 使用C風格字符串進行初始化 // char *Cstr = s; // 這個等式是不成立的 const char *str = s.c_str(); // 將 string的對象內容返回為一個C風格的字符串 char Cstr[30] = {0}; strcpy(Cstr, s.c_str()); // 使用數組來進行vector的初始化, begin和end兩個函數是C++11特性 int int_arr[] = {0,1,2,3,4,5}; vector<int> ivec(begin(int_arr), end(int_arr)); }
【共讀Primer】19.<3.5> 數組-C風格字符串 Page109