從零開始學C++(2 字元串、向量和數組)

来源:https://www.cnblogs.com/dreamerweee/archive/2020/02/03/12255946.html
-Advertisement-
Play Games

可以說string和vector是C++標準庫中最重要的兩種類型,string支持可變長字元串,而vector表示可變長的集合。 string 頭文件:<string> 定義在命名空間 std 中,using std::string; string s1; // 預設初始化,s1是一個空串 stri ...


  可以說string和vector是C++標準庫中最重要的兩種類型,string支持可變長字元串,而vector表示可變長的集合。

 

  string

  頭文件:<string>

  定義在命名空間 std 中,using std::string;

string s1;                        // 預設初始化,s1是一個空串
string s2(s1);                  // s2是s1的副本
string s3 = s1;                // s3是s1的副本
string s4("value");           // s4是字面值"value"的副本,除了字面值最後的那個空字元外
string s5 = "value";         // 等價於上面的括弧初始化
string s6(n, 'c');              // 把s6初始化為由連續n個字元c組成的串
View Code

   這裡需要區分直接初始化和拷貝初始化(後面學了類相關的知識就會知道,這兩種初始化調用分別調用的是構造函數和拷貝控制的某種構造函數)。

  使用等號(=)初始化一個變數,實際上執行的就是拷貝初始化(copy initialization),編譯器把等號右側的初始值拷貝到新創建的對象中去。反之,不使用等號,則執行的就是直接初始化(direct initialization)

  

  string的操作

    os << s        將s寫到輸出流os中,返回os

    is >> s        從is中讀取字元串賦給s,字元串以空白分隔,返回is

    getline(is, s)  從is中讀取一行賦給s,返回is

    s[n]        返回s中第n個字元的引用,位置n從0計起

    s1 + s2      返回s1和s2連接後的結果

// 讀取未知數量的string對象

int main()
{
    string word;
    while (cin >> word)
        cout << word << endl;
    return 0;
}
View Code

   

  string的size()函數返回類型為string::size_type,它是一個無符號類型的值,而且能足夠存放下任何string對象的大小。

  string對象與字元字面值或者字元串字面值相加時,必須確保每個加法運算符(+)的兩側的運算對象至少有一個是string對象:

int main()
{
    string str1("hell");
    string str2 = str1 + 'o' + " world";
    cout << str2 << endl;
    return 0;
}
View Code

 

  如何處理string對象中的字元呢?

    頭文件cctype中定義了一組標準庫函數

    isalnum(c)  當c是字母或數字時為真

    isalpha(c)  當c是字母時為真

    iscntrl(c)  當c是控制字元時為真

    isdigit(c)  當c是數字時為真

    isgraph(c)  當c不是空格但可列印時為真

    islower(c)  當c是小寫字母時為真

    isprint(c)  當c是可列印字元時為真

    ispunct(c)  當c是標點符號時為真

    isspace(c)  當c時空白時為真(即c是空格、橫向製表符、縱向製表符、回車、換行、進紙符)

    isupper(c)  當c是大寫字母時為真

    isxdigit(c)  當c是十六進位數字時為真

    tolower(c)  如果c是大寫字母,輸出對應的小寫字母;否則原樣輸出c

    toupper(c)  如果c是小寫字母,輸出對應的大寫字母;否則原樣輸出c

    string str3("abcdefgh0123");
    for (auto c : str3) {
        if (isxdigit(c)) {
            cout << "0x" << c << endl;
        } else {
            cout << c << endl;
        }
    }
View Code

 

  

  vector

  也被稱為容器(container),頭文件<vector>,using std::vector;

  vector是一個類模板(class template)。模板本身不是類或函數,可以將模板看作為編譯器生成類或函數編寫的一份說明。編譯器根據模板創建類或函數的過程稱為實例化(instantiation),當使用模板時,需要指出編譯器應該把類或函數實例化成何種類型。

   vector的使用

    vector<int> ivec;  // ivec保存int類型的對象

    vector<ClassObj> co_vec;  // co_vec保存ClassObj類類型的對象

    vector<vector<string>> files;  // files保存的元素是vector對象

  定義和初始化

    vector<T> v1;  // v1是一個空vector,它潛在的元素是T類型的,執行預設初始化

    vector<T> v2(v1); // v2中包含有v1所有元素的副本

    vector<T> v2 = v1; // 等價於v2(v1)

    vector<T> v3(n, val); // v3包含了n個重覆的元素,每個元素的值都是val

    vector<T> v4(n);  // v4包含了n個重覆地執行了值初始化的對象

    vector<T> v5{a,b,c...}; // 列表初始化,包含了{}中的元素

    vector<T> v6={a,b,c...}; // 同上

  使用列表初始化時,註意:

    vector<int> v1{10};  // v1只有一個元素

    vector<int> v2(10);  // v2有10個元素

    vector<int> v3{10, 1};  // 2個元素,10、1

    vector<int> v4(10, 1);  // 10個元素,值都是1

  用圓括弧:提供的值用來構造(construct)vector對象

  用花括弧:列表初始化該vector對象,也就是說,初始化過程會儘可能地把花括弧內的值當成是元素初始值的列表來處理,只有在無法執行列表初始化時才會考慮其他初始化方式。

    vector<string> v5{10};  // v5有10個預設初始化的元素

    vector<string> v6{10, "hi"}; // v6有10個值為"hi"的元素

  上面兩條語句儘管使用了花括弧,但是花括弧中的值(10)與元素類型(string)不匹配,不能作為元素的初始值,編譯器會嘗試使用構造函數去初始化對象。

    vector<string> v7{10, "hi", "hello"};  // 錯誤

 

  使用push_back向vector對象中添加元素

    vector<int> ivec;

    for (int i = 0; i != 10; ++i) {

      ivec.push_back(i);

    }

  

  迭代器(iterator)

  提供迭代器的類型,擁有begin和end成員函數,begin返回指向第一個元素(或第一個字元)的迭代器;end返回容器(或string對象)“尾元素的下一位置”的迭代器。

    auto b = ivec.begin(), e = ivec.end();

  如果容器為空,則begin和end返回的是同一個迭代器,都是尾後迭代器。

  擁有迭代器的標準庫類型使用iterator和const_iterator來表示迭代器的類型:

    vector<int>::iterator iter1;  // iter1能讀寫vector<int>的元素

    string::iterator iter2;

    vector<int>::const_iterator iter3;  // iter3 只能讀元素,不能寫元素

  

  vector和string迭代器支持的運算

    iter + n   iter - n   iter += n   iter -= n

    iter1 - iter2  兩個迭代器相減的結果是它們之間的距離,參與元素的兩個迭代器必須指向的是同一個容器中的元素或尾元素的下一位置

    >、>=、<、<=

  註意:兩個迭代器不能相加!!!(沒有意義)

  

  數組

  在C++代碼中,儘可能地使用vector,而不使用數組。

  數組的聲明:a[d],其中a是數組的名字,d是數組的維度。維度說明瞭數組中元素的個數,因此必須大於0。數組中元素的個數也屬於數組類型的一部分,編譯的時候維度必須是已知的,因此,維度必須是一個常量表達式:

    unsigned cnt = 10;

    constexpr unsigned sz = 10;

    int arr[10];  // 正確

    int *parr[sz]; // 含有10個整型指針的數組

    string err[cnt];  // 錯誤:cnt不是常量表達式

    string strs[GetSize()];  // 當GetSize()是constexpr時正確,否則錯誤

  數組下標的類型為size_t,size_t是一種機器相關的無符號類型,被設計得足夠大以便能表示記憶體中任意對象的大小,在頭文件<cstddef>中。

 

  在很多用到數組名字的地方,編譯器都會自動地將其替換為一個指向數組首元素的指針:

    string nums[] = {"a", "b", "c"};

    string *p = &nums[0];  // 指向nums的第一個元素

    string *ps = nums;   // 等價

  在一些情況下,數組的操作實際上是指針的操作,所以當使用數組作為一個auto變數的初始值時,推斷得到的類型是指針而非數組:

    int ia[] = {0,1,2,3,4,5};

    auto ia2(ia);  // ia2是一個整型指針,指向ia的第一個元素

  當使用decltype關鍵字時上述轉換不會發生:

    decltype(ia) ia3 = {0,1,2,3,4,5};

    ia3[4] = 10;

  標準庫函數begin和end,與容器中的兩個同名成員功能類似,作用於數組。

 

  C風格字元串

  它不是一種類型,而是為了表達和使用字元串而形成的一種約定俗成的寫法。按此習慣書寫的字元串存放在字元數組中並以空字元結束。

  strlen(p)    返回p的長度,空字元不計算在內

  strcmp(p1, p2)  比較p1和p2,如果p1==p2,返回0,如果p1>p2,返回正值,否則返回一個負值

  strcat(p1, p2)  將p2附加到p1之後,返回p1

  strcpy(p1, p2)  將p2拷貝給p1,返回p1

 

  string對象轉換為C風格字元串:str.c_str();

 

  本來想把《STL源碼剖析》中的vector實現寫出來,但是內容就太多了,所以現階段就只寫C++的基礎知識,後面再單獨寫其他深入的內容。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 組件(Component)是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。 註冊一個全局組件語法格式如下: Vue.component(tagName, options) tagName 為組件名,options 為配置選項。註冊後,我們可以使用以下方式來調用組件 ...
  • 1 f=open("yesterday","r",encoding="utf-8") #文件句柄 2 data=f.read() 3 data2=f.read() 4 print (data) 5 print (" data2 ") 6 #讀文件時指針會在文件內移動,讀一次後,指針將所有的文本讀完後 ...
  • 二叉堆(也可作為簡單的優先隊列)的建立、增、刪、自調整。 main.cpp: #include <iostream> #include "BinaryHeap.h" using namespace std; int main() { BinaryHeap<int> bh(BinaryHeap<int ...
  • 原理 項目的資料庫字典表是一個很重要的文檔。通過此文檔可以清晰的瞭解數據表結構及開發者的設計意圖。 通常為了方便我都是直接在資料庫中建表,然後通過工具導出數據字典。 在Mysql資料庫中有一個information_schema庫,它提供了訪問資料庫元數據的方式。 什麼是元數據呢?就是關於數據的數據 ...
  • Redis詳解(八)——企業級解決方案 緩存預熱 緩存預熱就是系統上線後,提前將相關的緩存數據直接載入到緩存系統。避免在用戶請求的時候,先查詢資料庫,然後再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據! 緩存預熱解決方案: 緩存雪崩 緩存雪崩就是在一個較短的時間內,緩存中較多的key集中過期 ...
  • python和其他語言一樣,也有大量的第三方庫 在安裝python時預設都會安裝pip,安裝了pip後 在cmd.exe下可以運行pip 安裝庫 pip install 庫的名字 換源 因為PyPi地址在國外,國內訪問速度慢有些地方甚至訪問不了,把鏡像源換為國內地址速度簡直飛起 國內一些常用的軟體源 ...
  • Standard Template Library(STL)主要由兩種組件構成1:一是容器(container),包括vector、list、set、map等;另一種組件是用以操作這些容器的所謂泛型演算法(generic algorithm),包括find()、sort()、replace()、mer... ...
  • Redis詳解(七)——集群 ​Redis3.0版本之前,可以通過Redis Sentinel(哨兵)來實現高可用 ( HA ),從3.0版本之後,官方推出了Redis Cluster,它的主要用途是實現數據分片(Data Sharding),不過同樣可以實現HA,是官方當前推薦的方案。 在Redi ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...