两种最重要的标准库---string和vector
string和vector是两种最重要的标准库类型,string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列。
一、标准库类型string
1.定义和初始化string对象:初始化string对象的方式有
string s1 默认初始化,s1是一个空串 string s2(s1) s2是s1的副本
string s2=s1 等价于s2(s1),s2是s1的副本
string s3("value") s3是字面值"value"的副本,除了字面值最后的那个空字符外
string s3="value" 等价于s3("value"),s3是字面值"value"的副本
string s4(n,‘c‘) 把s4初始化为由连续n个字符c组成的串
如果使用等号(=)初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到心创建的对象中去。与之相反,如果不使用等号,则执行的是直接初始化。
2.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个字符的引用,位置n从0计起
s1+s2 返回s1和s2连接后的结果 s1=s2 用s2的副本代替s1中原来的字符
s1==s2 s1!=s2 如果s1和s2中所含的字符完全一样,则他们相等;string对象的相等性判断对字母的大小写敏感
读取未知数量的string对象:
#include <iostream>
#include <string> using namespace std; int main() { string word; while(cin>>word) cout<<word<<endl; return 0; }
使用getline()读取一整行:
getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读的
内容存入到那个string对象中去(注意不存换行符)。
#include <iostream> #include <string> using namespace std; int main() { string line; //每次读入一整行,直到达文件末尾 while(getline(cin,line)) cout<<line<<endl; return 0; }
string的empty和size操作:
empty函数根据string对象是否为空返回一个对应的布尔值,empty也是string的一个成员函数。
#include <iostream> #include <string> using namespace std; int main() { string line; while(getline(cin,line)) //每次读入一整行,遇到空行直接跳过 if(!line.empty()) cout<<line<<endl; return 0; }
size函数返回string对象的长度(即string对象中字符的个数)
#include <iostream> #include <string> using namespace std; int main() { string line; //每次读入一整行,输出其中超过100个字符的行 while(getline(cin,line)) if(line.size()>100) cout<<line<<endl; return 0; }
处理string对象中的字符:使用基于范围的for语句
范围for语句:这种语句遍历给定序列中的每个元素并对序列中的每个值执行某种操作,
for (declaration : expression)
statement
其中,expression部分是一个对象,用于表示一个序列。declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。每次迭代,
declaration部分的变量会被初始化为expression的下一个元素值。
#include <iostream> #include <string> #include <ctype.h> using namespace std; int main() { string s("hello world!!!"); for (decltype(s.size()) index = 0;index != s.size() && !isspace(s[index]);++index) s[index] = toupper(s[index]); cout << s << endl; /*decltype(s.size()) punct_cnt = 0; for (auto c : s) if (ispunct(c)) ++punct_cnt; cout << punct_cnt << " punctuation characters in " << s << endl;*/ /*for (auto & c : s) c = toupper(c); cout << s << endl;*/ getchar(); return 0; }
二、标准库类型vector
1. 标准库类型vector表示对象的集合,其中所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象。因为vector容纳着其他对象,
所以它也被称作容器。
vector能容纳绝大多数类型的对象作为其元素,但是因为引用不是对象,所以不存在包含引用的vector。除此之外,其他大多数(非引用)内置类型和类类型都可
以构成vector对象,甚至组成vector的元素也可以是vector。
2. 定义和初始化vector对象
和任何一种类类型一样,vector模板控制着定义和初始化向量的方法。
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{a,b,c...}
3. vector支持的操作
v.empty() 如果v不含有任何元素,返回真;否则返回假 v.size() 返回v中元素的个数
v.push_back(t) 向v的尾端添加一个值为t的元素 v[n] 返回v中第n个位置上元素的引用
v1=v2 用v2中元素的拷贝替换v1中的元素 v1={a,b,c...} 用列表中元素的拷贝替换v1中的元素
v1==v2 v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值都相同 v1!=v2
4. 向vector对象中添加元素
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v; int a; while (cin >> a ,a!=-1) v.push_back(a); for(auto i : v) cout << i << endl; system("pause"); return 0; }
5. 使用迭代器
使用迭代器可以访问某个元素,迭代器也能从一个元素移动到另外一个元素。迭代器有有效和无效之分,这一点和指针差不多。有效的迭代器或者指向某个元素,或者
指向容器中尾元素的下一个位置;其他所有情况都属于无效。这些类型都拥有名为begin和end的成员,其中begin成员负责返回指向第一个元素(或第一个字符)的迭代器。
end成员则负责返回指向容器(或string对象)“尾元素的下一个位置”的迭代器,该迭代器指示的是容器的一个本不存在的“尾后”元素。end成员返回的迭代器常被称作尾后
迭代器或者简称为尾迭代器。特殊情况下如果容器为空,则begin和end返回的是同一个迭代器。
标准容器迭代器的运算符:
*iter 返回迭代器iter所指元素的引用 iter->mem 解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
++iter 令iter指示容器中的下一个元素 --iter 令iter指示容器中的上一个元素
iter1==iter2 iter1 != iter2 判断两个迭代器是否相等(不相等),如果两个迭代器指示的是同一个元素或者它们是同一个容器的尾后迭代器,则相等;反之,不相等
#include <iostream> #include <vector> #include <string> #include <ctype.h> using namespace std; int main() { string s("some string"); if (s.begin() != s.end()) { auto it = s.begin(); *it = toupper(*it); } cout << s << endl; system("pause"); return 0; }
#include <iostream> #include <vector> #include <string> #include <ctype.h> using namespace std; int main() { string s("some string"); if (s.begin() != s.end()) { for (auto it = s.begin();it != s.end() && !isspace(*it);++it) *it = toupper(*it); } cout << s << endl; system("pause"); return 0; }
迭代器类型:拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型。const_iterator和常量指针差不多,能读取但不能修改它所指的元素值。
相反,iterator的对象可读可写。如果vector对象或string对象是一个常量,只能使用const_iterator;如果vector对象或string对象不是常量,那么既能使用iterator也能
使用const_iterator。
begin和end运算符:begin和end返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator;如果对象不是常量,返回iterator。为了
便于得到const_iterator类型的返回值,引入了两个新函数,分别是cbegin和cend,类似于begin和end,两个新函数也分别返回指示容器第一个元素或最后元素下一个
位置的迭代器。不同的是,不论vector对象(或string对象)本身是否是常量,返回值都是const_iterator。
#include <iostream> #include <vector> #include <string> #include <ctype.h> using namespace std; int main() { string s("some string"); if (s.begin() != s.end()) for (auto it = s.cbegin();it != s.cend() && !s.empty();++it) cout << *it; cout << endl; system("pause"); return 0; }