C++ 字符串與字符數組 詳解


寫在前面:字符是單個的,字符串一般有多個,但也可以是單個,甚至可以是空的

char c; c = 'a';  //字符a,注意使用單引號
c = "a'; //出錯!“a”使用的是雙引號,代表是字符串,而c是字符類型

string c="abcd"; string c1="a";單個字符,但是雙引號

在C++中,有兩種類型的字符串表示形式:

  • C-風格字符串
  • C++引入的string類

C-風格字符串

C 風格的字符串起源於 C 語言,並在 C++ 中繼續得到支持。字符串實際上是使用 null 字符 ‘\0’ 終止的一維字符數組。因此,一個以 null 結尾的字符串,包含了組成字符串的字符。
下面的聲明和初始化創建了一個 “Hello” 字符串。由於在數組的末尾存儲了空字符,所以字符數組的大小比單詞 “Hello” 的字符數多一個。

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

其實不需要把 null 字符放在字符串常量的末尾。C++ 編譯器會在初始化數組時,自動把 ‘\0’ 放在字符串的末尾。所以也可以利用下面的形式進行初始化

char greeting[] = "Hello";

以下是 C/C++ 中定義的字符串的內存表示:

 

C++ 中有大量的函數用來操作以 null 結尾的字符串:

序號 函數 功能
1 strcpy(s1,s2) 復制字符串 s2 到字符串 s1
2 strcat(s1,s2) 連接字符串 s2 到字符串 s1 的末尾
3 strlen(s1) 返回字符串 s1 的長度
4 strcmp(s1,s2) 返回s1與s2的比較結果
5 strchr(s1,ch) 返回一個指針,指向字符串s1中字符ch的第一次出現的位置
6 strstr(s1,s2) 返回一個指針,指向字符串s1中s2的第一次出現的位置

 

 

 

 

 

 

 

 

 

C++ 中的 String 類

C++ 標准庫提供了 string 類類型,支持上述所有的操作,另外還增加了其他更多的功能。比如:

  • append() – 在字符串的末尾添加字符
  • find() – 在字符串中查找字符串
  • insert() – 插入字符
  • length() – 返回字符串的長度
  • replace() – 替換字符串
  • substr() – 返回某個子字符串

C++中的字符串一般有以下四種類型,

  • string

  • char*

  • const char*
  • char[]

下面分別做簡單介紹,並說明其中的一些區別

1)string

string是一個C++類庫中的一個類,它位於名稱空間std中,因此必須使用using編譯指令或者std::string來引用它。它包含了對字符串的各種常用操作,它較char*的優勢是內容可以動態拓展,以及對字符串操作的方便快捷,用+號進行字符串的連接是最常用的操作;

2)char*

char* 是指向字符串的指針(其實嚴格來說,它是指向字符串的首個字母),你可以讓它指向一串常量字符串;

3)const char*

該聲明指出,指針指向的是一個const char類型,即不能通過當前的指針對字符串的內容作出修改

注意這里有兩個概念:

  • char * const [指向字符的靜態指針]
  • const char * [指向靜態字符的指針]

前者const修飾的是指針,代表不能改變指針
后者const修飾的是char,代表字符不能改變,但是指針可以變,也就是說該指針可以指針其他的const char;

4)char[]

與char*與許多相同點,代表字符數組,可以對應一個字符串,如

char * a="string1"; char b[]="string2";

這里a是一個指向char變量的指針,b則是一個char數組(字符數組)

二者的不同點

一,char*是變量,值可以改變, char[]是常量,值不能改變!
a是一個char型指針變量,其值(指向)可以改變;
b是一個char型數組的名字,也是該數組首元素的地址,是常量,其值不可以改變

二,char[]對應的內存區域總是可寫,char*指向的區域有時可寫,有時只讀
比如:

char * a="string1"; char b[]="string2"; gets(a); //試圖將讀入的字符串保存到a指向的區域,運行崩潰! 
gets(b) //OK

解釋: a指向的是一個字符串常量,即指向的內存區域只讀;
b始終指向他所代表的數組在內存中的位置,始終可寫!

注意,若改成這樣gets(a)就合法了

char * a="string1"; char b[]="string2"; a=b; //a,b指向同一個區域
gets(a) //OK
printf("%s",b) //會出現gets(a)時輸入的結果

解釋: a的值變成了是字符數組首地址,即&b[0],該地址指向的區域是char *或者說 char[8],習慣上稱該類型為字符數組,其實也可以稱之為“字符串變量”,區域可讀可寫。

總結:char *本身是一個字符指針變量,但是它既可以指向字符串常量,又可以指向字符串變量,指向的類型決定了對應的字符串能不能改變!

三,char * 和char[]的初始化操作有着根本區別:

char *a="Hello World"; char b[]="Hello World"; printf("%s, %d\n","Hello World", "Hello World"); printf("%s, %d %d\n", a, a,  &a); printf("%s, %d %d\n", b,     b,  &b);

結果:

Hello World,13457308 Hello World,13457308    2030316 Hello World,2030316 2030316

結果可見:盡管都對應了相同的字符串,但”Hello World”的地址 和 a對應的地址相同,與b指向的地址有較大差異;&a 、&b都是在同一內存區域,且&b==b
根據c內存區域划分知識,我們知道,局部變量都創建在棧區,而常量都創建在文字常量區,顯然,a、b都是棧區的變量,但是a指向了常量(字符串常量),b則指向了變量(字符數組),指向了自己(&b==b==&b[0])。

 

char * a=”string1”;是實現了3個操作:

  1. 聲明一個char*變量(也就是聲明了一個指向char的指針變量);
  2. 在內存中的文字常量區中開辟了一個空間存儲字符串常量”string1”
  3. 返回這個區域的地址,作為值,賦給這個字符指針變量a

最終的結果:指針變量a指向了這一個字符串常量“string1”
(注意,如果這時候我們再執行:char * c=”string1”;則,c==a,實際上,只會執行上述步驟的1和3,因為這個常量已經在內存中創建)

char b[]=”string2”;則是實現了2個操作:

  1. 聲明一個char 的數組,
  2. 為該數組“賦值”,即將”string2”的每一個字符分別賦值給數組的每一個元素

最終的結果:“數組的值”(注意不是b的值)等於”string2”,而不是b指向一個字符串常量

實際上, char * a=”string1”; 的寫法是不規范的!
因為a指向了即字符常量,一旦strcpy(a,”string2”)就糟糕了,試圖向只讀的內存區域寫入,程序會崩潰的!盡管VS下的編譯器不會警告,但如果你使用了語法嚴謹的Linux下的C編譯器GCC,或者在windows下使用MinGW編譯器就會得到警告。
所以,我們還是應當按照”類型相同賦值”的原則來寫代碼:

onst char * a="string1";

保證意外賦值語句不會通過編譯。

 

const char*與char[]的區別:
const char * a=”string1”
char b[]=”string2”;

二者的區別在於:

    1. a是const char 類型, b是char const類型
      ( 或者理解為 (const char)xx 和 char (const xx) )

    2. a是一個指針變量,a的值(指向)是可以改變的,但a只能指向(字符串)常量,指向的區域的內容不可改變;

    3. b是一個指針常量,b的值(指向)不能變;但b指向的目標(數組b在內存中的區域)的內容是可變的

    4. 作為函數的聲明的參數的時候,char []是被當做char *來處理的!兩種形參聲明寫法完全等效!

 

參考:https://blog.csdn.net/ksws0292756/article/details/79432329


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM