天天看點

《C++Primer》讀書筆記——第3章 字元串、向量和數組

  1. using聲明文法:using namespace::name;如,using std:cin;
  2. 頭檔案不應該包括using聲明
  3. 初始化string對象的方式:
    1. string s1;//預設初始化,s1是個空串
    2. string s2(s1);//s2是s1的副本
    3. string s2 = s1;//等價于s2(s1),s2是s1的副本
    4. string s4(n,’c’)//把s4初始化為由連續n個字元c組成的串

      ps:2、4為直接初始化(沒用=),3為拷貝初始化(用了=),4可轉換為拷貝初始化:string s4 = string(n,’c’);

  4. string的基本操作
    1. os << s;
    2. is >> s;
    3. getline(is, s);//從is中讀一行賦給s,傳回is
    4. s.empty();s為空,傳回true
    5. s.size();傳回s中字元的個數
    6. s1+s2;傳回s1 s2的連接配接
    7. s1==s2;
    8. s1!=s2;
    9. s1>=s2;(> <= <)//字典序比較
  5. size()函數傳回值類型為string::size_type類型,size_type是無符号的,Tips:如果一條表達式中已經有size()函數了,就不要再用int了,這樣可以避免混用int和unsigned可能帶來的問題
  6. 字元串+操作:不能将字面值與字面值直接相加

    tips:C++語言中的字元串字面值并不是标準庫類型string的對象。切記:字元串字面值與string是不同的類型

  7. cctype頭檔案中的函數
    1. isalnum(c);當c是字母或數字時為真
    2. isdight(c);當c是數字時為真
    3. isxdight(c);當c是16進制數字時為真
    4. isalpha(c);當c是字母時為真
    5. islower(c);當c是小寫字母時為真
    6. isupper(c);當c是大寫字母時為真
    7. iscntrl(c);當c是控制字元時為真
    8. isgraph(c);當c 可列印但不是空格時為真
    9. isprint(c);當c是可列印字元時為真(c具有可視形式或c是空格)
    10. isspace(c);當c是空白時為真(即c是空格、橫向制表符、數字、字母、可列印空白中的一種)
    11. ispunct(c);當c是标點符号時為真(即c不是控制字元、數字、字母、可列印空白中的一種)
    12. tolower;轉換為小寫字母
    13. toupper;轉換為大寫字母
  8. Tips:建議使用C++版本的C标準庫頭檔案。

    C++标準庫中除了定義C++語言特有功能外,也相容了C語言的标準庫,隻不過将名字由name.h轉變為cname。一般使用cname形式的頭檔案

  9. string中單個字元類型為char
  10. 要想通路string對象中的單個字元有兩種方式,一種是使用下标,一種是使用疊代器。

    下标運算符[],下标的值成為下标或索引

  11. C++語言既有類模闆,又有函數模闆,其中vector是一個類模闆。模闆本身不是類和函數。編譯器根據模闆建立類或函數的過程稱為執行個體化。
  12. 對于類模闆,我們提供一些額外資訊來制定模闆到底執行個體化乘什麼樣的類,需要提供哪些資訊由模闆決定。

    提供資訊的方式總是這樣:即在模闆名字後面加一個尖括号,在括号内放上資訊。

    以vector為例,提供的額外資訊是vector内所存放對象的類型,如:vector< int> ivec;

  13. 初始化vector對象的方法
    1. vector< T> v1//v1是一個空vector,執行預設初始化
    2. vector< T> v2(v1)//v2中包含是以v1元素的副本
    3. vector< T> v2 = v1//等價于v2(v1)
    4. vector< T> v3(n, val)//v3包含了n個值val的元素
    5. vector< T> v4(n)//v4包含了n個預設初始化的元素
    6. vector< T> v5{a,b,c,d…}//v5包含的每個元素被賦予特定值。PS:一定注意是花括号!!!
    7. vector< T> v5 = {a,b,c,d…}//等價于v5{a,b,c,d…}
    8. 特例:vector< string> v7{10};vector< string> v7{10,”hi”}都是正确的
  14. vector支援的操作
    1. v.empty()如果v為空,傳回true
    2. v.size傳回v中元素的個數
    3. v.push_back(t)向v的尾端添加一個值為t的元素
    4. v[n]下标通路
    5. v1 == v2 v1 != v2
    6. < <= > >=
  15. 不能以下表的形式添加元素。隻能對已存在的元素執行下表操作,試圖用下标通路一個不存在的元素将引發錯誤,會導緻錯誤,如buffer overflow(緩沖區溢出)
  16. 疊代器——通路string vector的另一種途徑。

    标準庫容器都支援疊代器,隻有其中的幾種支援下标通路。

    類似于指針,疊代器也實作了元素的間接通路

    嚴格來說,string類型不屬于容器類型,但是string支援很多與容器類似的操作。

  17. v.begin() 傳回指向第一個元素的疊代器

    v.end() 傳回指向容器“尾元素的下一位置”的疊代器,被稱作尾後疊代器,尾疊代器。沒有實際含義,隻作為一個标記

    如果容器為空,則begin() end()傳回的是同一個疊代器,都是尾後疊代器

  18. 标準容器疊代器的運算符
    1. *iter 傳回疊代器iter所指元素的引用
    2. iter->men 解引用iter并擷取鈣元素的名為men的成員,等價于(*iter).men
    3. ++iter 令iter訓示容器中的下一個元素
    4. –iter 上一個元素
    5. iter1 == iter2(iter1 != iter2) 判斷是否相等
  19. 概念:泛型程式設計

    所有标準庫容器都定義了==和!=,但它們中的大多數都沒有定義<運算符。養成用疊代器和!=的習慣,就不用太在意用的到底是哪種容器了。

  20. 疊代器類型:iterator和const_iterator(隻讀不能寫)
  21. vector對象可以動态增長,但也帶來了副作用。
    1. 不能在範圍for循環中向vector對象添加元素。
    2. 任何一種可能改變vector對象容量的操作,比如push_back,都會使該對象的疊代器失效

      Tips:凡是使用了疊代器的循環體,都不要向疊代器所屬的容器添加元素。

  22. vector 和 string支援的疊代器運算
    1. iter+n(iter-n)
    2. iter1-iter2 傳回它們之間的距離,類型為difference_type的帶符号整形數
    3. > >= < <= 疊代器的關系運算器,若在前面則小于
  23. 數組。和vector相比,相同點:也是存放類型相同的對象的容器,這些對象本身沒有名字,需要通過其所在位置通路。不同點:數組大小固定不變,不能随意向數組中增加元素。某些場合運作時效率較好,但失去了靈活性。
  24. 定義和初始化内置數組
    1. 定義:數組的次元必須是一個常量表達式。如下面是正确的:

      constexpr int sz = 42;

      string strs[sz];

    2. 顯示初始化數組元素

      int a2[] = {0, 1, 2};//次元是3

      int a3[5] = {0, 1, 2};//初始化了前3個元素

      int a5[2] = {0, 1, 2};//錯誤!初始值錯誤

    3. 字元數組的特殊性

      字元數組有一種額外的初始化形式,即可以用字元串字面值對此類數組初始化。但注意!字元串字面值的結尾處還有一個空字元,這個空字元也會像其他字元一樣,被拷貝到字元數組裡。

      char a1[] = {‘C’, ‘+’, ‘+’};//無空字元,次元為3

      char a2[] = {‘C’, ‘+’, ‘+’, ‘\0’};//有空字元,次元為4

      char a3[] = “C++”;//自動添加空字元,等同于上一句

      char a4[6] = “Daniel”;//錯誤:沒有空間可存放空字元

    4. 不允許拷貝和指派:不允許用一個數組初始化另一個數組,不能把一個數組直接指派給另一個數組
    5. 了解複雜的數組聲明:

      int *ptrs[10];

      int &refs[10] = ;//錯誤,不存在引用的數組

      int (*Parray)[10] = &arr;//Parray指向一個含有10個整數的數組

      int (&arrRef)[10] = arr;//arrRef引用一個含有10個整數的數組

  25. 數組下标通常定義為size_t類型。它在cstddef頭檔案中定義
  26. 指針和數組
    1. 使用數組類型的對象其實是使用該數組首元素的指針,

      string nums[] = {“one”, “two”, “three”};

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

      string *p2 = nums;//等價于p2 = &nums[]0; 即 nums == &nums[0]

      auto nums2(nums);//nums2是一個指針,等同于p p2

    2. 指針的運算 p1-p2 p1==p2 (!= > >= < <=)
    3. 指針的下标運算

      int *p = &ia[2];

      int j = p[1];//p[1] == *(p+1)

      int k = p[-2];//p[-2] == *(p-2)

  27. C風格字元串:字元串字面值:最後一個字元後面跟着一個空字元(’\0’)

    C标準庫String函數(定義在cstring頭檔案中,注意差別于string頭檔案)

    1. strlen(p) 傳回p的長度
    2. strcmp(p1, p2) p1==p2傳回0 p1>p2傳回正值 p1< p2傳回負值
    3. strcat(p1, p2) 将p2附加到p1之後,傳回p1
    4. strcpy(p1, p2) 将p2拷貝給p1,傳回p1

      注意:傳入此類函數的指針必須指向以空字元作為結束符的數組:如:

      char ca[] = {“C”, “+”, “+”};

      cout << strlen(ca) << endl;//嚴重錯誤:ca沒有以’\0’結束

  28. 多元數組:嚴格來說,C++沒有多元數組,通常多元數組其實是數組的數組。謹記!!
  29. 多元數組的初始化

    int ia[3][4] = { {0,1,2,3}, {4,5,6,7}, {8,9,10,11} };

    int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};//等同于上句

    int ia[3][4] = { {0}, {4}, {8} };//初始化首列,其餘元素執行預設值初始化

    int ia[3][4] = {0,3,6,9};//初始化首行,其餘元素執行預設值初始化