C++中常用的容器String、vector、list、map(学习笔记)

目录

一、String容器

        初始化

        string对象上的操作       

二、vector容器

        初始化

         区分是列表初始化还是值初始化:

        其他操作

三、list容器

四、map容器


        这里主要讲C++中经常用到的一些保存数据的容器,其中也会介绍string。

        在C++11中提到了很多容器,这里主要介绍:vector、list、map。还有一些其他的容器就不做介绍了。

一、String容器

        这是我们用得最多的用来表示字符串的类型了 ,下面介绍一下String的一些知识:

        初始化

                string s1;                                 //这里默认初始化,s1是一个空字符串

                string s2 = s1;                        //s2是s1的副本,此时s2和s1是里面保存的是一样的内容

                string s3 = "hiya";                //s3是该字符串字面值的副本

                string s3("hiya");                  //等价于上面的s3

                string s4(10, 'c');                    //s4的内容是cccccccccc。(10个c)

        string对象上的操作       

                os<<s;                   将s写到输出流os当中,返回os

                is>>s;                    从is中读取字符串赋给s,字符串以空白分隔,返回is

                getline(is, s)       从is中读取一行赋给s,返回is

                s.empty();           s为空返回true,否则返回false

                s.size();                返回s中字符的个数

                s[n];                      返回s中第n个字符的引用,位置从0计起

                s1 + s2;                返回s1和s2连接后的结果

                s1 = s2;                用s2的副本代替s1中原来的字符;

                s1 == s2;          如果s1和s2中所含字符完全一样,则它们相等;string对象的相等性判断对字母的大小写敏感

                s1 != s2;              

                <,<=,>,>=           利用字符在字典中的顺序进行比较,且对字母的大小写敏感

        这里对于string类型的数据,我们可以像访问数组元素一样访问string中的对应字符。

        注:还可以使用迭代器来对字符串类型做一些操作,如

   string s("some things");
   if (s.begin() != s.end())
   {
       uto it = s.begin;     //it表示s的第一个字符
       *it = touper(*it);    //将当前字符改为大写形式
   }

二、vector容器

        vector类型得到标准定义为:vector<T> v1;

        其中T为类型,这里可以是内置类型,如int等,也可以是结构体或者类类型。

        初始化

                vector<T> v1;                              //v1是一个空的vector,它潜在的元素是T类型,执行默认初始化

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

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

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

                vector<T> v4(n);                        //v4中包含了n个重复执行了值初始化的对象

                vector<T> v5{a,b,c,......};        //v5包含了初始值个数的元素,每个元素被赋予了相应的初始值

                vector<T> v5 = {a,b,c,.......};   //等价于上面的v5

         区分是列表初始化还是值初始化:

                vector<int> v1(10);          //v1有10个元素,每个元素的值都是0

                vector<int> v2{10};         //v2有1个元素,该元素的值为10

                vector<int> v3(10,1);      //v3有10个元素,每个元素的值都是1

                vector<int> v4{10,1};     //v4有2个元素,值分别为10和1

        其他操作

                v.empty()                 如果v不返回任何元素,返回真,否则返回假

                v.size()                     返回v中元素的个数

                v.push_back(t)         向v的尾端添加一个值为t的元素

                v[n]                          返回v中第n个位置上的元素的引用,从0开始计起

                v1 = v2;                    用v2中的元素的拷贝替换v1中的元素

                v1 = {a,b,c,......}       用列表中的元素来拷贝替换v1中的元素

                v1 == v2                   v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值都相同

                v1 != v2                    

                <,<=,>,>=                以字典的书序进行比较
 

         上述介绍的string和vector我们都可以使用基于范围的for语句来进行范文,如:

  string str("hello");
  for(auto c : str)
  cout << c << endl;

        这里将依次输出str中的每一个字符,且每一个字符占一行 

vector<string> vec{"hello", “world"};
for(auto c : vec)
    cout << c << endl;

        这里会输出hello和world,且每个单词占一行

        对于vector我们还可以通过基于范围的for语句来改变当中的每一个元素的值

vector<int> v{1,2,3,4,5,6,7,8,9};
for(auto &i : v) //对于v中的每一个元素(注意:i是一个引用)
    i *= i;        //求每个元素的平方值
for(auto i : v)
    cout << i << " ";
cout << endl;

        输出结果为:1 4 9 16 25 36 49 64 81

        注:不能使用下标的形式往vector对象中添加元素

三、list容器

        这里list和vector基本操作相同,这里就说说它们之间的区别,便于我们选择用哪一种容器更好,区别如下:

        (1)  vector是顺序表,表示的是一块连续的内存,元素被顺序存储;list是双向连接表,在内存中不一定连续。

        (2)当数值内存不够时,vector会重新申请一块足够大的连续内存,把原来的数据拷贝到新的内存里面;list因为不用考虑内存的连续,因此新增开销比vector小。

        (3)list只能通过指针访问元素,随机访问元素的效率特别低,在需要频繁随机存取元素时,使用vector更加合适。

        (4)当向vector插入或者删除一个元素时,需要复制移动待插入元素右边的所有元素;因此在有频繁插入删除操作时,使用list更加合适。

        下面介绍一个list和vector中的插入。

        vector中可以使用push_back()向容易的尾端插入指定的数据,但是不能使用push_front,该函数是向容器的首端插入指定的元素,这里我们就可以使用insert()函数来实现插入操作,insert包括两个参数,一个参数是迭代器,用于指出插入元素的位置,这里即使是尾端迭代器也可以,所以insert完成的是向该迭代器所指位置的前一个位置插入指定的元素,如:

 注:迭代器表示要拷贝的范围,不能指向与目的位置相同的容器,如:

   lst.insert(lst.begin(), lst.begin(), lst.end());// 这里要插入的迭代器容器是lst,但是要拷贝的范围也是lst,所以运行时会出现错误。

                vector<string> vec;

                list<string> lst;

                lst.insert(lst.begin(), "Hello");           //向list类型容器的lst的首端插入”Hello“

                vec.insert(vec.begin(), "Hello");       //同上


                insert除了上述接收两个参数的形式外,还可以接收三个参数,如:


                vec.insert(vec.begin(), 10, "Hello");                 //添加10个Hello字符串到vec的首端

                vector<string> v = {"quasi", "simba", "frollo", "scar"};

                vec.insert(vec.begin(), v.end()-2, v.end());      //将v的最后两个插入vec的首端

                lst.insert(lst.end(), {"shese", "words", "will", "go”, "at", "the", "end"});      //将后面的列表中的字符串插入lst的尾部

四、map容器

        map是属于关联容器这一类的,包括两个参数,第一个参数是关键字,第二个参数的该关键字对应的值。

        对map的一个经典例子是单词计数器程序:

map<string, size_t> word_count; //string 到size_t的空map
string word;
while(cin >> word)
    ++word_count[word];   //提取word的计数器并将其加1
for(const auto &w : word_count)   //使用基于范围的for语句依次访问map中的数据
    cout << w.first << "occurs" << w.second << ((w.second > 1) ? "times" : "time") << endl;

        一般很多时候,我们会将map和set连起来一起用,如下面的例子是改进的上面的单词计数器的例子,本例子中只统计不在exclude中的单词.

map<string, size_t> word_count;
set<string> exclude = {"the", "But", "And", "At", "A", "An"};
string word;
while(cin >> word)
    if (exclude.find(word) == exclude.end())
       ++word_count[word];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值