1. 程式人生 > >C++ 字串與字元陣列 詳解

C++ 字串與字元陣列 詳解

在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() – 返回某個子字串

4種字串型別

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

  • string

  • char*

  • const char*
  • char[]

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

string

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

char*

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

const char*

該宣告指出,指標指向的是一個const char型別,即不能通過當前的指標對字串的內容作出修改

注意這裡有兩個概念:

  • char * const [指向字元的靜態指標]
  • const char * [指向靜態字元的指標]

前者const修飾的是指標,代表不能改變指標
後者const修飾的是char,代表字元不能改變,但是指標可以變,也就是說該指標可以指標其他的const char。

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

結果可見:儘管都對應了相同的字串,但”Hellow 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編譯器就會得到警告。
所以,我們還是應當按照”型別相同賦值”的原則來寫程式碼:

const char * a="string1";

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

另外,關於char*和char[]在函式引數中還有一個特殊之處,執行下面的程式碼

void fun1 ( char *p1,  char p2[] ) {
 printf("%s %d %d\n",p1,p1,&p1);
 printf("%s %d %d\n",p2,p2,&p2);
p2="asdf"; //通過! 說明p2不是常量! 
printf("%s %d %d\n",p2,p2,&p2);
}
void main(){
char a[]="Hello";
fun1(a,a);
}

執行結果:

Hello 3471628 3471332
Hello 3471628 3471336
asdf 10704764 3471336

結果出乎意料!上面結果表明p2這時候根本就是一個指標變數!
結論是:作為函式的形式引數,兩種寫法完全等效的!都是指標變數!

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 *來處理的!兩種形參宣告寫法完全等效!

字串型別之間的轉換: string、const char*、 char* 、char[]相互轉換

一、轉換表格

源格式->目標格式 string char* const char* char[]
string NULL 直接賦值 直接賦值 直接賦值
char* strcpy NULL const_cast char*=char
const char* c_str() 直接賦值 NULL const char*=char;
char[] copy() strncpy_s() strncpy_s() NULL

二、總結方法:

  1. 變成string,直接賦值。
  2. char[]變成別的,直接賦值。
  3. char*變constchar*容易,const char*變char*麻煩。<const_cast><char*>(constchar*);
  4. string變char*要通過const char*中轉。
  5. 變成char[]。string逐個賦值,char* const char* strncpy_s()。

三,程式碼示例

1、string轉為其他型別

①、string轉const char*

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    std::string str = "HelloWorld!";     //初始化string型別,並具體賦值
    const char* constc = nullptr;         //初始化const char*型別,並賦值為空
    constc= str.c_str();                 //string型別轉const char*型別
    printf_s("%s\n", str.c_str());        //列印string型別資料 .c_str()
    printf_s("%s\n", constc);             //列印const char*型別資料
    return 0;
}

②、string轉char*

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    std::string str = "HelloWorld!";     //初始化string型別,並具體賦值
    char* c = nullptr;                    //初始化char*型別,並賦值為空
    const char* constc = nullptr;         //初始化const char*型別,並賦值為空
    constc= str.c_str();                 //string型別轉const char*型別
    c= const_cast<char*>(constc);        //const char*型別轉char*型別
    printf_s("%s\n", str.c_str());        //列印string型別資料 .c_str()
    printf_s("%s\n",c);                  //列印char*型別資料
    return 0;

}

③、string轉char[]

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    std::string str = "HelloWorld!";      //初始化string型別,並具體賦值
    char arrc[20] = {0};                   //初始化char[]型別,並賦值為空
    for (int i = 0; i < str.length(); i++) //string型別轉char[]型別
    {
        arrc[i]=str[i];
    }
    printf_s("%s\n", str.c_str());         //列印string型別資料 .c_str()
    printf_s("%s\n", arrc);                //列印char[]型別資料
    return 0;
}

2、const char*轉為其他型別

①const char*轉string

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    const char* constc = "Hello World!";     //初始化const char* 型別,並具體賦值
    std::string str;                        //初始化string型別
    str= constc;                            //const char*型別轉string型別
    printf_s("%s\n", constc);                //列印const char* 型別資料
    printf_s("%s\n", str.c_str());           //列印string型別資料
    return 0;
}

②const char*轉char*

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    const char* constc = "Hello World!";     //初始化const char* 型別,並具體賦值
    char* c = nullptr;                       //初始化char*型別
    c= const_cast<char*>(constc);           //const char*型別轉char*型別
    printf_s("%s\n", constc);                //列印const char* 型別資料
    printf_s("%s\n", c);                     //列印char*型別資料
    return 0;
}

③const char*轉char[]

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    const char* constc = "Hello World!";     //初始化const char* 型別,並具體賦值
    char arrc[20] = { 0 };                   //初始化char[]型別,並賦值為空
    strncpy_s(arrc,constc,20);              //const char*型別轉char[]型別
    printf_s("%s\n", constc);                //列印const char* 型別資料
    printf_s("%s\n", arrc);                  //列印char[]型別資料
    return 0;
}

3、char*轉為其他型別

①char*轉string

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    char* c = "HelloWorld!";           //初始化char* 型別,並具體賦值
    std::string str;                   //初始化string型別
    str= c;                            //char*型別轉string型別
    printf_s("%s\n", c);                //列印char* 型別資料
    printf_s("%s\n", str.c_str());      //列印string型別資料
    return 0;
}

②char*轉const char*

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    char* c = "HelloWorld!";         //初始化char* 型別,並具體賦值
    const char* constc = nullptr;     //初始化const char* 型別,並具體賦值
    constc= c;                       //char*型別轉const char* 型別
    printf_s("%s\n", c);              //列印char* 型別資料
    printf_s("%s\n", constc);         //列印const char* 型別資料
    return 0;
}

③char*轉char[]

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    char* c = "HelloWorld!";         //初始化char* 型別,並具體賦值
    char arrc[20] = { 0 };           //初始化char[] 型別,並具體賦值
    strncpy_s(arrc,c,20);             //char*型別轉char[] 型別
    printf_s("%s\n", c);              //列印char* 型別資料
    printf_s("%s\n", arrc);           //列印char[]型別資料
    return 0;
}

4、char[]轉為其他型別

#include "stdafx.h"
#include <iostream>
int _tmain(intargc, _TCHAR* argv[])
{
    char arrc[20] = "HelloWorld!";//初始化char[] 型別並具體賦值
    std::string str;                 //初始化string
    const char* constc = nullptr;   //初始化const char*
    char*c = nullptr;                //初始化char*
    str= arrc;                     //char[]型別轉string型別
    constc= arrc;             //char[]型別轉const char* 型別
    c= arrc;                        //char[]型別轉char*型別
    printf_s("%s\n", arrc);         //列印char[]型別資料
    printf_s("%s\n", str.c_str());  //列印string型別資料
    printf_s("%s\n", constc);       //列印const char* 型別資料
    printf_s("%s\n", c);            //列印char*型別資料
    return 0;
}

相關推薦

C++ 字串字元陣列

在C++中,有兩種型別的字串表示形式: C-風格字串 C++引入的string類 C-風格字串 C 風格的字串起源於 C 語言,並在 C++ 中繼續得到支援。字串實際上是使用 null 字元 ‘\0’ 終止的一維字元陣列。因此,一個以 null 結

C語言基礎知識筆記:day4字串字元陣列

注:本筆記為直接上傳,因各個markdown筆記語法的差異性,在顯示上略有區別。 如需原版請聯絡:[email protected]。(郵件主題為:學習筆記,正文需要的筆記名,可以直接複製該筆記的網址)。同時歡迎各位一起學習交流。 day4字串與字元陣

字串字元陣列

一 . 使用帶%s格式符的scanf函式讀入字串時,不需要再引數前加取地址符&。 原因:編譯器會自動將陣列名作為陣列首地址來處理。 如:scanf("%s", str); 二 . 字元陣列與字串 (這兩個概念其實現在我也不是很清楚),但看到的一句話可以幫助理解:在C語言中,將

java 字串字元陣列相互轉化,字串位元組陣列相互轉化

package com.liuxd; /** * Created by Liuxd on 2018-11-02. */ public class TestString { public static void main(String[] args) throws Exception

字元型別char、字串字元陣列字元陣列資料陣列區別

字元型別是以ASCII碼值運算的:小寫字母比相應的大寫字母大32,其中A=65,a=97 Esc鍵 27(十進位制)、'\x1B'(十六進位制)、'\33'(八進位制) 轉義字元:\0 空字元\n 換行\r 回車\t 水平製表符(Tab鍵)\' 單引號\" 雙引號\\ 反斜槓 char c='M';

我來學網路——C/SB/S

1.C/S結構,即Client/Server(客戶機/伺服器)結構,是大家熟知的軟體系統體系結構,通過將任務合理分配到Client端和Server端,降低了系統的通訊開銷,可以充分利用兩端硬體環境的優勢。 2.B/S結構,即Browser/Server(瀏覽器/伺服器)結構,是隨著Interne

字串字元陣列轉化

1:字元陣列換為字串 見程式碼 #include <iostream> #include <string> using namespace std;   int main

matlab裡cell和char,字串字元陣列(zz)

用importdata和textscan讀取內容為字串的txt,結果為cell型元胞組。 我想把cell變成char型,然後就自然地想到cell2str,遺憾的是matlab中沒有這個函式。 就像沒有str2cell一樣。 實現str2cell功能的函式是cel

C/C++字串字元陣列的總結

一、定義 字元陣列:儲存字元的陣列 字串 :是使用最頻繁的字元陣列,是一個特殊的字元陣列 C++中並沒有專門的字串的型別,一個字串實際上就是一個字元陣列,與普通字元陣列不同的是,字串的結尾有一個字元\0,表示字串的結束。 char 可以定義字元陣列,也可以定義字串

matlab裡cell和char,字串字元陣列

很多人分不開字元陣列和字串什麼區別。 >>str1='i love matlab' % 這是一個字元陣列,也是一個字串 str1 = i love matlab >>str2=['I ';'am ';'a ';'boy'];% 這是字元陣列,由於是陣列,所以每一行必須具有相同的列數(字

JavaScript陣列結構演算法——陣列(中)

迭代器方法在上篇中,我們探討了很多陣列方法,接下來總結一下最後一組方法——迭代器方法。這些方法對陣列的每個元素應用一個函式,可以返回一個值、一組值、或者一個新陣列。1、不生成新陣列的迭代器方法以下這組迭代器方法不產生任何新陣列,它們要麼對陣列中的每個元素執行某種操作,要麼返回

String類的常用方法,實現首字母大寫(重要),轉換大小寫,判斷字串是否由數字組成,字串字元陣列的轉換

(1)String類的常用方法:示例:觀察Public char charAt(int index)public class Test {public static void main(String[] args) {// TODO Auto-generated method

js字串字元陣列之間的轉換

strObj.match(reg)方法對字串物件進行檢索,返回包含所有匹配結果的陣列。而 正則表示式 /./g 匹配的是所有的字元, 所以str.match(/./g)返回的是由字串str中所有的字元組成的陣列,以此達到將字串轉換為陣列的目的。 2、array to string 陣列轉字串使用strOb

基本資料型別的介紹及轉換,基本資料型別字串之間轉換,字串字元陣列之間轉換以及字串位元組陣列之間轉換

目錄 一.Java的基本資料型別介紹 二.各類基本資料之間的轉換 三.基本資料型別和String之間轉換(附:物件包裝類及所對應的基本資料型別) 四.String與字元陣列轉換 五.Strin

字串字元陣列字串區別

C 語言中並不存在字串這個資料型別,而是使用字元陣列來儲存字串。那麼,字元陣列就一定是字串嗎? 對於這個問題,大多教科書中的回答是“是”。其實不然,字元陣列和字串是完全不相同的兩個概念,千萬不要混淆。分析如下所示的示例程式碼。 1 #include <stdio.h> 2 #incl

菜鳥學習-C語言函式引數傳遞-結構體陣列

C語言中結構體作為函式引數,有兩種方式:傳值和傳址。 1.傳值時結構體引數會被拷貝一份,在函式體內修改結構體引數成員的值實際上是修改呼叫引數的一個臨時拷貝的成員的值,這不會影響到呼叫引數。在這種情況下,涉及到結構體引數的拷貝,程式空間及時間效率都會受到影

C語言的字元陣列字串)的定義初始化

1、字元陣列的定義與初始化 字元陣列的初始化,最容易理解的方式就是逐個字元賦給陣列中各元素。 char str[10]={ 'I',' ','a','m',' ',‘h’,'a','p','p','y'}; 即把10個字元分別賦給str[0]到str[9]10個元素 如果花

C語言中字串常量字元陣列

字串常量與字元陣列的關係在C語言中沒有專門的字串變數,如果想將一個字串存放在變數中以便儲存,必須使用字元陣列,即用一個字元型陣列來存放一個字串,陣列中每一個元素存放一個字元。例如“char a[10]="love".”

C++之虛函數虛繼承

類繼承 file 文件 技術分享 函數表 命令行 .com G1 mes 準備工作 1、VS2012使用命令行選項查看對象的內存布局 微軟的Visual Studio提供給用戶顯示C++對象在內存中的布局的選項:/d1reportSingleClassLayout。使用方法

C語言字串字元陣列

如果是字元陣列,也可以用一個字串字面值來初始化: char str[10] = "Hello"; 相當於: char str[10] = { 'H', 'e', 'l', 'l', 'o', '\0' }; str的後四個元素沒有指定,自動初始化為0,即Null字元。