1. 程式人生 > >c字串、string物件、字串字面值的區別

c字串、string物件、字串字面值的區別

一、字串字面值

字串字面值是一串常量字元,字串字面值常量用雙引號括起來的零個或多個字元表示,為相容C語言,C++中所有的字串字面值都由編譯器自動在末尾新增一個空字元。
字串沒有變數名字,自身表示自身

"Hello World!" //simple string literal"" //empty string literal"\nCC\toptions\tfile.[cC]\n" //string literal using newlines and tabs

字元字面值: 'A' //single quote:character literal
字串字面值: "A" //double quote:character string literal.包含字母A和空字元的字串

字串字面值的連線:

std::out << "a multi-line "+
"string literal"+
" using concatenation"
<< std::endl;

輸出:a multi-line string literal using concatenation

多行字面值:

std::out << "a multi-line \nstring literal\n
using a backslash"
<< std::endl;

輸出:a multi-line string literalusing a backslash

=================================================

1. string literal:字串直接量:

cout<<"hello"<<endl;

程式碼中通過包含"hello"字串自身來將其輸出,並未包含該字串的變數。


2. 字串直接量可以賦值給變數,但是與字串直接量相關聯的記憶體空間位於只讀部分,因此它是常量字元陣列。

char* ptr = "hello";
ptr[1] = 'a';//crash! attemps to write to read-only memory.

因此,當引用字串直接量的時候使用指向const的字元陣列:

const char* ptr = "hello";
ptr[1] = 'a';//bug! attempts to write to read-only memory.

3. 當將字串直接量賦值給字元陣列的初始值的時候。由於字元陣列存放與棧中,不允許引用其他地方的記憶體,因此編譯器會將字串直接量複製到站的陣列記憶體中。因此,可以進行相應的修改。

char stackArray[] = "hello";
stackArray[1] = 'a';

二、C++風格字串

C++風格字串:使用C++風格字串的時候,要將它當做是一個普通的型別,如int,這樣反而會避免將string作為一個類來理解所帶來的很多問題。


1. 支援<cstring>中許多函式完成的同樣操作。
2. 字串定義:

string myString = “hello”;

3. 操作符 = :複製字串;比如:

string newone = original;

會將後者複製給前者,不會出現兩個變數同樣指向一個記憶體的情況。
4. 可以像int一樣使用 == 之類的操作符
5. 可以改變字串中的某一個字元。 如

string myString = "hello"; mystring[0] = 'l'; 

這中操作是允許的。

2.1 C風格字串的使用

C++語言通過(const) char *型別的指標來操縱C風格字串。

複製程式碼
const char *cp = "some value"; // 一個C風格字串while(*cp) //判斷cp當前指向的字元是true還是false,true表明這是除null外的任意字元{
// do something to *cp ++cp;
}
複製程式碼

2.2 C風格字串的標準庫函式

複製程式碼
#include <cstring> // cstring是string.h標頭檔案中的C++版本,而string.h是C語言提供的標準庫

//操縱C風格字串的標準庫函式(引數型別省略,都是char *型別):strlen(s) // 返回s的長度,不包括字串結束符nullstrcmp(s1, s2) //當s1<s2時,返回值<0 ,當s1=s2時,返回值=0 ,當s1>s2時,返回值>0 strcat(s1, s2) // 將字串s2連線到s1後,並返回s1 strcpy(s1, s2) // 將s2複製給s1,並返回s1strncat(s1, s2, n) // 將s2的前n個字元連線到s1後面,並返回s1strncpy(s1, s2, n) // 將s2的前n個字元複製給s1,並返回s1if(cp1 < cp2) // compares address, not the values pointed toconst char *cp1 = "A string example";
const char *cp2 = "A different string";
int i=strcmp(cp1, cp2); // i is positivei=strcmp(cp2, cp1); // i is negativei=strcmp(cp1, cp1); // i is zero
複製程式碼

2.3 永遠不要忘記字串結束符null

char ca[]={'C', '+', '+'}; // not null-terminatedcout << strlen(ca) << endl; // disaster: ca isn't null-terminated

2.4 呼叫者必須確保目標字串具有足夠的大小

複製程式碼
// Dangerous:What happens if we miscalculate the size of largeStr?char largeStr[16+18+2]; // will hold cp1 a space and cp2strcpy(largeStr, cp1); // copies cp1 into largeStrstrcat(largeStr, " "); // adds a space at end of largeStrstrcat(largeStr, cp2); // concatenates cp2 to largeStr
// prints A string example A different stringcout << largeStr << endl;
複製程式碼

2.5 使用strn函式處理C風格字串

char largeStr[16+18+2] // to hold cp1 a space and cp2strncpy(largeStr, cp1, 17); // size to copy includes the nullstrncat(largeStr, " ", 2); // pedantic, but a good habitstrncat(largeStr, cp2, 19); // adds at most 18 characters, plus a null

2.6 儘可能使用標準庫型別string

string largeStr = cp1; // initialize largeStr as a copy of cp1largeStr += " "; // add space at end of largeStrlargeStr += cp2; // concatenate cp2 onto end of largeStr

此時,標準庫負責處理所有的內在管理問題。


三、C風格字串

字串字面值的型別實質是const char型別的陣列。C++從C語言繼承下來的一種通用結構是C風格字串,而字串字面值就是該型別的例項。C風格字串是以空字元null結束的字元陣列:

複製程式碼
char ca1[]={'C', '+', '+'}; // no null, not C-style stringchar ca2[]={'C', '+', '+', '\0'}; // explicit nullchar ca3[]="C++"; // null terminator added automaticallyconst char *cp="C++"; // null terminator added automaticallychar *cp1=ca1; // points to first element of a array, but not C-style stringchar *cp2=ca2; // points to first element of a null-terminated char array
複製程式碼

ca1和cp1都不是C風格字串:ca1是一個不帶結束符null的字元陣列,而指標cp1指向ca1,因此,它指向的並不是以null結束的陣列。


字串的連線:

1.c++中string可以替代c中的char陣列且前者用起來更方便。連線兩個string物件只需用'+';c字串是用char陣列實現的。以下都稱c字串為char陣列

例如:string s1="hello",s2="world";

          string s3=s1+s2;                  //也可以s3=s1+"world"

cout<<s3<<endl;//結果為helloworld

當然還可以用+=連線。

2.還可以這樣連線一個string物件和char陣列。

例如:string s1="hello";

          char s2[]="world";

cout<<s1+s2<<endl;//輸出結果為helloworld

但不能這樣連線兩個char陣列或字元字面值。

例如:string s1="hello";

           string s2="world";

           string s3=s1+"world";//正確,可以連線一個string物件和字串字面值

           string s4="hello"+"world";//錯誤,不能這樣連線連個字串字面值

           char s5[]="world";

           string s6=s1+s5;//正確,可以連線一個string物件和char陣列

           char s7[]="hello";

           stirng s8=s7+s5;//錯誤,不能這樣連線兩個char陣列。

總而言之只能用+或+=連線兩個string物件或一個string物件和字串字面值或一個string物件和char陣列。

連線一個string物件和字串字面值或char陣列或返回的都是string物件,所以可以連線一個string物件和字串字面值(或char陣列)後再連線一個字串字面值(或char陣列)。

例如:string s;//初始化為空
    char s1[]="hello";
    char s2[]="world";
    s=s+s1+s2;//正確