zoukankan      html  css  js  c++  java
  • 《C++ Primer》读书笔记—第三章 字符串、向量和数组

    声明:

    • 文中内容收集整理自《C++ Primer 中文版 (第5版)》,版权归原书所有。
    • 学习一门程序设计语言最好的方法就是练习编程

    这一部分内容比较简单。

    string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列。

    一、命名空间的using声明

    1、using namespace std;

    2、头文件不应该包含using声明,因为头文件会被多个源文件引用,有的程序不经意间包含了一些名字,可能与头文件中的内容冲突。

    3、理论上每用一个名字using一次比较好,因为不清楚整个命名空间都有哪些关键字,可能造成命名冲突。

    二、标准库类型string

    1、定义一个名为s的空string,然后执行输入,输出时会自动忽略开头空白,并从第一个字符开始,直到遇到第下一处空白。如“Hello Word”,只会输出“Hello”。

    1 int main(){
    2     string s;
    3     cin>>s;
    4     cout<<s<<endl;
    5 
    6 return 0;
    7 }

    2、使用getline读取一整行  使用getline代替>>,保留输入中的空白符。

      getline的参数是一个输入流和一个string对象,函数从给定的输入流中读取内容,直到换行符为止(换行符也读取进来了)。

    1 int main(){
    2 
    3 string line;
    4 while(getline(cin,line)){
    5     cout<<line<<endl;
    6     }
    7     return 0;
    8 }

    3、empty函数根据string对象是否为空返回一个对应的布尔值。

      size函数返回string对象的长度。size函数的返回值类型是string::size_type,size_type是在类string中定义的,它是一个无符号类型的值。

    4、0-15之间的十进制数转换为十六进制。初始化一个字符串令其存放16个十六进制的“数字”

     1 int main(){
     2 
     3     const string hexdigits = "0123456789ABCDEF";//可能的十六进制数字
     4     cout<<"Enter a series of numbers between 0 and 15"<<" separated by spaces. Hit ENTER when finished: "<<endl;
     5     string result;      //保存十六进制的字符串
     6     string::size_type n;    //用于保存从输入流读取的数
     7     while(cin>>n)
     8         if(n<hexdigits.size())  //忽略无效输入
     9             result+=hexdigits[n];  //得到对应的十六进制
    10     cout<<"Your hex number is :"<<result<<endl;
    11 
    12     return 0;
    13 }

    三、标准库类型vector

    1、vector生成的类型必须包含vector中元素的类型,如vector<int>。

    2、vector初始化:

    1 vector<int> v1( 10 );  //v1有10个元素,每个值为0
    2 vector<int> v2{ 10 };  //v2有1个元素,每个值为10
    3 vector<int> v3( 10, 1 );  //v3有10个元素,每个值为1
    4 vector<int> v4{ 10, 1 };//v1有2个元素,一个为10,一个为1

    3、基本操作

      (1)头文件#include<vector>.

      (2)创建vector对象,vector<int> vec;

      (3)尾部插入数字:vec.push_back(a);

      (4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的。

      (5)使用迭代器访问元素.

      vector<int>::iterator it;
        for(it=vec.begin();it!=vec.end();it++)
          cout<<*it<<endl;

      (6)插入元素:vec.insert(vec.begin()+i,a);在第i+1个元素前面插入a;

      (7)删除元素:vec.erase(vec.begin()+2);删除第3个元素

        vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始

      (8)向量大小:vec.size();

      (9)清空:vec.clear();

    4、vector直接初始化适用于三种情况:初始值已知且数量较少、初始值是另一个vector对象的副本、所有元素的初始值都一样。

    5、vector能在运行时高效快速的添加元素。因此使用vector比较高效的一种方法就是先定义一个空的vector,再在运行时向其中添加具体值。

    6、push_back函数:创建一个空的vector,在运行时向其中添加元素。push_back负责把一个值当成vector的尾元素push到vector对象的尾端。

      vector<int>v2;

      for(int i = 0;i!=100;++i)

      v2.push_back(i);

    6、vector对象及string对象下标运算符可用于访问已存在的元素而不能用于添加元素。只能用push_back。

    7、来自知乎“诸葛不亮”:现在各大编译器实现的string都有短字符串优化,实现方式是在内部同时持有一个定长char数组和一个char*指针。在字符串数据短时,使用数组存储,这样就可以利用栈内存效率比堆内存高的优势了。内置数组长度各编译器不同,vs好像是24字节?
    所以未初始化长度的string,其实至少头几个字节还是有效可用的。
    至于何时切换么存储——string内部一般会持有一个uint32之类的数据,用struct+位域拆分为两个变量,最高位0/1标识用数组还是用指针保存内容,后面的位数用来存储数据长度。

    四、迭代器介绍

    1、迭代器可以用来访问string和vector对象的元素。

      尾后迭代器(off-the-end iterator)end函数返回的迭代器,指向一个并不存在的元素,该元素位于容器尾元素的下一位置。

    2、迭代器运算:迭代器与整数相加或相减得到一个新的迭代器,与原来的迭代器相比,新的迭代器向前或者向后移动了若干个位置。

    3、

    auto itrBeg = v.begin();  
    auto itrEnd = v.end();
    
    • begin函数负责返回指向第一个元素的迭代器
    • end函数返回指向尾后元素的迭代器,尾后元素是“尾元素的下一位置”

    4、如果对象只需读操作而无需写操作的话最好使用常量类型(如const_iterator)。

    5、迭代器相减可以得到两个迭代器指针的距离,即右边的迭代器移动多少个距离可以追上左侧的迭代器。得到的距离类型为difference_type,是带符号整型,这个距离可正可负。

    6、使用迭代器实现二分搜索。从有序序列中找出某个给定的值。

     1 //test必须是有序的
     2 //beg和end表示我们的搜索范围
     3 auto beg = text.begin(), end = text.end();  
     4 auto mid = beg + ( end - beg ) / 2;  
     5 while( mid != end && *mid != target)  
     6 {  
     7     if( target < *mid )  
     8     {  
     9         end = mid;  //如果要找的元素在前半部分,则搜索范围忽略后部分
    10     }  
    11     else  
    12     {  
    13         beg = mid + 1;  //mid之后寻找
    14     }  
    15 
    16     mid = beg + ( end - beg ) / 2;//新的中间点  
    17 }

    五、数组

    1、和vector一样,数组可以存放大多数的对象。例如,可以定义一个存放指针的数组。数组本身也是对象,允许定义数组的指针及数组的引用。

    2、理解数组声明的含义,最好的方法是从数组名字开始由内向外的顺序阅读。

      如:

      int  *ptrs[10]  //ptrs是一个含有10个整形指针的数组 

      int(*parray)[10]=&arr;//parray指向一个含有10个整数的数组。*parray意味着parray是个指针,指向大小为10的数组,数组中的元素时int。

      int  *(&arry)[10]=ptrs;//arry是数组的应用,该数组含有10个指针。  由内向外,首先arry是个引用,然后引用对象是个大小为10的数组,然后数组的元素类型是指向int的指针。

    3、使用数组类型的对象其实就是使用一个指向该数组首元素的指针。

    4、c标准库的string函数:(传入以下函数的指针必须指向以空字符为结束的数组:‘’)

      strlen(p):返回p的长度,空字符不算在内

      strcmp(p1,p2):比较p1p2的相等性,如果p1==p2返回0,p1>p2返回正值,p1<p2返回负值。

      strcat(p1,p2):将p2附加到p1后面,返回p1

      strcpy(p1,p2):将p1拷贝给p2,返回p1

     1 int main(){
     2     char ca[]={'c','+','+',''};
     3     char da[]={'c','-','-',''};
     4     cout<<strlen(ca)<<endl;     //3
     5     cout<<strcmp(ca,da)<<endl;    //-1
     6     cout<<strcat(ca,da)<<endl;    //c++c--
     7     cout<<strcpy(ca,da)<<endl;   //c++
     8     return 0;
     9 }

    六、多维数组

    1、多维数组其实是数组的数组,多维数组名转换得来的指针其实是指向第一个内层数组的指针。

    2、使用类型别名简化多维数组的指针://将类型“四个整数组成的数组”命名为int_array

    using int_array = int[4];  //新标准下类型别名的声明
    typedef int int_array[4]; //等价的typedef声明

     

    第三章结束。进度不是很快,上手能力并没有太大的提升,得加入编程训练了。且随疾风前行。

  • 相关阅读:
    MVC总结
    HTML+CSS总结
    常用正则表达式
    从你的全世界切过(胡说八道支持向量机SVM小故事)
    Beta分布
    贝叶斯决策理论
    Linux(Ubuntu)下载安装破解Matlab2016
    贝叶斯规则
    多元分布
    条件分布
  • 原文地址:https://www.cnblogs.com/zlz099/p/6437755.html
Copyright © 2011-2022 走看看