【C++】第三章:字串、向量和陣列

2020-08-12 23:05:16

3.1 名稱空間的using宣告

  • 我們用到的庫函數基本上都屬於名稱空間std
  • 如果我們想使用std中的一某個名字,需要每次都要std::name
  • 因此,我們這檔案開頭這樣宣告:using namespace::name
  • 在接下來的程式裡就直接使用name就可以了,無需新增std
  • 話說回來,直接using namespace std;它不香嗎?
  • 另外注意,標頭檔案不應包含using宣告

3.2 標準庫型別string

3.2.1定義和初始化string物件

#include <string>
string s1;
string s2 = s1;
string s3 = "Queue";  //拷貝初始化
string s4("ueueQ");   //直接初始化
string s5(n, 'c')  //將s5初始化爲由連續個n個字元c組成的字串

3.2.2string物件上的操作

  • 對string字串的操作
    在这里插入图片描述
  • 注意cin>>s 與 getline(cin, s)的區別
  • cin的輸入,會以空格爲分隔符。但是getline不會,它也會接受空格
  • 在說一下s.size()這個返回值型別的問題,這個函數是庫裡的,可以結合上一章學過的auto函數,我們要用一個len去接收這個函數的返回值,但是型別我們不知道,這時auto的作用就出來了。即:auto len = s.size(); 當然,我們也可以用decltype(s.size()) len;來實現

3.2.3處理string物件中的字元

  • 有時候,我們需要單獨處理string中的單個字元,那麼如何提取呢?
  1. 如何提取string中的單個字元
string str = "ueueQx_ac";
for(auto c : str)    //這裏爲什麼寫auto,不用多說
{
	cout<<c<<endl;
}
  1. 如何修改字串中的字元
string str = "ueueQx_ac";
for(auto &c : str)  //這裏爲什麼要用參照,因爲我們要去修改這單個字元
{
	c = toupper(c);
}
cout<<str<<endl;

在这里插入图片描述

  • 但是,有時候我們只需要存取其中的某一個特定的字元,而不是對整個字串進行遍歷,這時有兩種方法,一是使用下標,二是使用迭代器
  1. 下標方法
string str = "UEUEQ_AC";
decltype(str.size()) count;    //這裏爲什麼用decltype去定義count,也就不多說了
cin>>count;
cout<<srt[count]<<endl;
  1. 迭代方法

3.3標準庫型別vector

  • vector是模板而非型別,由vector生成的型別必須包含vector中元素的型別
  • vector用法總結

3.3.1定義和初始化vector物件

  • 關於用圓括號還是花括號,還有列表初始化等等問題,這裏沒有講解,記了也白記,過後就忘了
#include<vector>
vector<int> v1;  //空元素
vector<int> v2(v1);  //用v1初始化v2
vector<int> v2 = v1;   //將v1的元素賦給v2
vector<int> v3(10,1);   //v3中定義了10個爲1的數
vector<int> v4(10);     //v4中由10個數,爲預設的初始值0
vector<int> v5{325,67,8,7,98,4,3,4,76};  //v5被賦予初值
vector<int> v5 = {325,67,8,7,98,4,3,4,76};  //同上

vector<string> s1
vector<string> s2{10}   //s2中有10個string型別的值,爲空的
vector<string> s3{10,"Q"}   //s3中有10個內容爲"Q"的值

3.3.2向vector物件中新增元素

  • 這一塊無非就是vector它的內建函數們,上邊有傳送門

3.3.3其他的vector問題

  1. 不允許用下標的形式新增元素!
  2. 而且,只能對確知已存在的元素執行下標操作!
vector<int> ivec;
cout<<ivec[5]<<endl;    //不允許
vector<int> ivec(10);
cout<<ivec[5]<<endl;  //允許

3.4迭代器

3.4.1使用迭代器

vector<int> v(10);
auto b = v.begin();   //負責返回指向的第一個元素
auto e = v.end();    //負責返回指向容器的「尾元素的下一個位置」,即「尾後」,沒有實際意義
  • 如果容器爲空,則begin和end返回的是同一個迭代器,都是尾後迭代器

5

  • 例子:當要用迭代器裏面代表的值的時候,一定要解除參照!!!!!!
    string str{"ueueQ"};
    for(auto b = str.begin(); b != str.end(); ++b)
    {
        *b = toupper(*b);   //注意解除參照
    }
    cout<<str<<endl;
  • 迭代器的型別
  1. 對於該型別,知不知道已經無關緊要了,因爲可以用auto去自動的分析
  2. 每一種容器類都定義了一個iterator的型別
  3. 但是,我們仍要知道,哈哈,例如
vector<int>::iterator it;   //it\str可以讀寫物件中的元素或字元
string::iterator str;

vector<int>::const_iterator it;   //通過it\srt只能讀取元素或字元,不能寫
string::const_iterator str;
//C++11引入了兩個新函數,做下說明
auto b = str.cbegin();  //這時,b的型別是string::const_iterator
auto c = str.cend();  //無論vector、string的物件是否是常數,用這個兩新函數,但返回值都是const_iterator
  • 迭代器失效:
  • 這裏有一點先記住,但凡是在使用了迭代器的回圈體裡,都不要在向迭代器所屬的容器新增元素

3.4.2迭代器運算

2

#include<iostream>
#include<vector>
using namespace std;

//迭代器:遞增做二分法查詢

int main()
{
    vector<int> text{4, 9, 11, 16, 20, 34, 45, 49, 61};
    int temp;
    cin>>temp;
    auto min = text.begin();
    auto max = text.end();
    auto mid = text.begin() + text.size() / 2;
    while(min <= max)
    {
        if(temp == *mid)
        {
            cout<<"已經找到"<<endl;
            break;
        }
        else if(temp < *mid)
        {
            max = mid - 1;
            cout<<"小找"<<endl;
        }
        else
        {
            min = mid + 1;
            cout<<"大找"<<endl;
        }
        mid = min + (max - min) / 2;
    }
    return 0;
}