C++(13)STL实践与分析之再谈String类型
来源:互联网 发布:linux wexitstatus 编辑:程序博客网 时间:2024/05/22 10:36
STL实践与分析
--再谈string类型(上)
引:
复习3.2节介绍的string类型:
曾经介绍过的string操作
string s;
定义一个新的空string对象,命名为s
string s(cp);
定义一个新的string对象,用cp所指向的(以空字符null结束的)C风格字符串初始化该对象
string s(s2);
定义一个新的string对象,并将它初始化为s2的副本
is >> s;
从输入流is中读取一个以空白字符分隔的字符串,写入s
os << s;
将 s写到输出流os中
getline(is,s);
从输入流is中读取一行字符,写入s
s1 + s2
把 s1和 s2串接起来,产生一个新的string对象
s1 += s2
将 s2拼接在 s1后面
关系操作符
相等运算(==和!=)以及关系运算(<、<=、>和>=)都可用于string对象的比较,等效于(区分大小写的)字典次序的比较
在某些方面,可以将string类型视为字符容器,除了一些特殊的操作,string类型提供与vector类型相同的操作。
string容器支持的操作:
1)表9.5 列出的typedef,包括迭代器类型。
2)表9.2列出的容器构造函数,但是不包括只需要一个长度参数的构造函数。
3)表9.7列出的vector容器所提供的添加元素的操作。注意:无论vector容器还是string类型都不支持push_front操作。
4)表9.8 列出的长度操作。
5)表9.9列出的下标和at操作;但string类型不提供该表列出的back和front操作。
6)表9.6 列出的begin 和end 操作。
7)表9.10列出的erase和clear操作;但是string类型不入提供pop_back或pop_front操作。
8)表9.11 列出的赋值操作。
9)与vector容器的元素一样,string的字符也是连续存储的。因此,string类型支持capacity和reserve操作。
- string str("Hiyal");
- string::iterator iter = str.begin();
- while (iter != str.end())
- {
- cout << *iter ++ << endl;
- }
除了共享容器的操作外,string类型还支持其他本类型特有的操作。
- //P290 习题9.34
- int main()
- {
- // freopen("input","r",stdin);
- string lower;
- while (cin >> lower)
- {
- for (string::iterator iter = lower.begin(); iter != lower.end(); ++iter)
- {
- *iter = toupper(*iter);
- }
- cout << lower << endl;
- }
- }
- //习题 9.35
- int main()
- {
- //freopen("input","r",stdin);
- string str;
- while (cin >> str)
- {
- for (string::iterator iter = str.begin(); iter != str.end(); ++iter)
- {
- if (isupper(*iter))
- {
- str.erase(iter);
- --iter;
- }
- }
- cout << str << endl;
- }
- }
- //习题9.36
- int main()
- {
- vector<char> cVec;
- char c;
- while (cin >> c)
- {
- cVec.push_back(c);
- }
- string s(cVec.begin(),cVec.end());
- cout << s << endl;
- }
- //习题9.37
- int main()
- {
- string s;
- s.reserve(100); //为其先开辟一块内存
- char c;
- while (cin >> c)
- {
- s.push_back(c);
- }
- cout << s << endl;
- }
一、构造string对象的方法
1、构造string对象传统方法
- string s1;
- string s2(5,'a');
- string s3(s2);
- string s4(s3.begin(),s3.begin() + s3.size()/2);
- char *cp = "HiHa";
- char c_array[] = "Hello World";
- char no_null[] = {'H','i'};
- string str1(cp);
- string str2(c_array,5);
- string str3(c_array+5,4);
- string str4(no_null); //Error
- string str5(no_null,2);
- cout << str4 << endl;
将不包含null的数组传递给stringstr(cp)将导致编译器无法检测到的严重错误,此类错误在运行时会发生什么情况没有定义。
2、其他方法
构造string对象的其他方法
String s(cp,n);
创建一个string对象,它被初始化为cp所指向数组的前n个元素的副本
Strings(s2,pos2);
创建一个string对象,它被初始化为一个已存在的string对象s2中从下标pos2开始的字符的副本
Strings(s2,pos2,len2);
创建一个string对象,它被初始化为s2中从下标pos2开始的len2个字符的副本。如果pos2> s2.size(),则该操作未定义,无论len2的值是多少,最多只能复制s2.size()- pos2 个字符
注意:n、len2和 pos2都是unsigned值
用子串做初始化式:
- string str1("HiHa");
- string str2(str1,2);
- cout << str2 << endl;
- string str3(str1,0,2);
- cout << str3 << endl;
- string str4(str1,0,8);
- cout << str4 << endl;
无论要求复制多少个字符,标准库最多只能复制数目与string对象长度相等的字符。
二、修改string对象的其他方法
1、string容器的操作不仅支持迭代器,而且提供下标为基础的操作。
与容器共用的string操作
s.insert(p,t)
在迭代器p指向的元素之前插入一个值为t的新元素。返回指向新插入元素的迭代器
s.insert(p,n,t)
在迭代器p指向的元素之前插入n个值为t的新元素。返
回 void
s.insert(p,b,e)
在迭代器 p指向的元素之前插入迭代器b 和e 标记范围内
所有的元素。返回void
s.assign(b,e)
在迭代器b和e标记范围内的元素替换s。对于string类型,该操作返回s;对于容器类型,则返回void
s.assign(n,t)
用值为t的n个副本替换s。对于string类型,该操作返回s;对于容器类型,则返回void
s.erase(p)
删除迭代器 p指向的元素。返回一个迭代器,指向被删除元素后面的元素
s.erase(b,e)
删除迭代器b和e标记范围内所有的元素。返回一个迭代器,指向被删除元素段后面的第一个元素
string类型特有的操作
s.insert(pos,n,c)
在下标为pos的元素之前插入n个字符c
s.insert(pos,s2)
在下标为pos的元素之前插入string对象s2的副本
s.insert(pos,s2,pos2,len2)
在下标为pos的元素之前插入s2中从下标pos2开始的len2个字符
s.insert(pos,cp,len)
在下标为pos的元素之前插入cp所指向数组的前len个字符
s.insert(pos,cp)
在下标为pos的元素之前插入cp所指向的以空字符结束的字符串副本
s.assign(s2)
用 s2的副本替换s
s.assign(s2,pos2,len)
用s2中从下标pos2开始的len个字符副本替换s
a.assign(cp,len)
用cp所指向数组的前len个字符副本替换s
a.assign(cp)
用cp所指向的以空字符结束的字符串副本替换s
a.erase(pos,len)
删除从下标pos开始的 len个字符
除非特殊声明,上述所有操作都返回s的引用
基于位置的实参
对于string类型,还允许通过为erase函数传递一个起点位置和删除元素的数目,来指定删除的范围:
- str.erase(str.size()-5,5);
类似的,对于string类型,还可以使用下标而不是迭代器来指定插入位置:
- str.insert(str.size(),5,'!');
指定新的内容
在string对象中,insert或assign的字符可来自字符数组或者另一个string对象。
- char *cp = "Stately plump Buck";
- string s;
- s.assign(cp,7);
- s.insert(s.size(),cp+7);
- cout << s << endl;
类似的,可以将一个string对象的副本插入到另一个string对象中去:
- //可以支持三种插入方式
- string str1("some string");
- string str2("some other string");
- str1.insert(str1.begin(),str2.begin(),str2.end());
- str1.insert(0,str2);
- str1.insert(0,str2,0,str2.size());
- cout << str1 << endl;
三、只适用于string类型的操作
string类型提供了容器类型不支持的其他几种操作,如下标所示:
substr函数,返回当前string对象的子串。
append和replace函数,用于修改string对象
一系列的find函数,用于查找string对象
substr操作
子串操作
S.substr(pos,n)
返回一个string类型的字符串,他包含s中从下标pos开始的n个字符
S.substr(pos)
返回一个string类型的字符串,他包含s中从下标pos开始到s末尾的所有字符
S.substr()
返回s的副本
我们可以给substr函数传递一个查找的起点和一个计数器。该函数将生成一个新的string对象,而字符数目由计数器决定,但最多只能到原string对象的最后一个字符!
- string s("Hello World");
- string str = s.substr(6,5);
- cout << str << endl;
另一种方式:
- string str = s.substr(6);
append和replace函数
string类型提供了6个append重载函数和10个replace版本O(∩_∩)O~。append和replace函数使用了相同的参数集合实现重载(如下表所示)。
对于append操作,字符将添加在string对象的末尾,而replace函数则将这些字符插入到指定位置,从而替换string对象中一段已经存在的字符。
修改string对象的操作(args在下表定义)
S.append(args)
将args串接在s后面,返回s的引用
S.replace(pos,len,args)
删除s中从下标开始的len个字符,用args指定的字符串替换之,返回s的引用。
在这个版本中,args不能为b2,e2
S.replace(b,e,args)
删除迭代器b 和e标记范围内所有的字符,用args替换之。返回s的引用
在这个版本中,args不能为s2,pos2,len2
append和replace操作的参数args
s2
string类型的字符串 s2
s1,pos2,len2
字符串s2 中从下标pos2 开始的len2 个字符
cp
指针cp指向的以空字符结束的数组
cp,len2
cp指向的以空字符结束的数组中前len2 个字符
n,c
字符c 的n 个副本
b2,e2
迭代器b2 和e2标记的范围内所有字符
append操作提供了在字符串尾部插入的捷径:
- string str("C++ Primer");
- str.append(" 3rd Ed.");
- //与下列操作作用相同
- str.insert(str.size()," 3rd Ed.");
replace操作用于删除一段指定范围内的字符,然后在删除的位置插入一组新的字符,等效于调用erase和insert函数:
- str.replace(11,3,"4th");
- cout << str << endl;
- //与下列操作作用相同
- str.erase(11,3);
- str.insert(11,"4th");
【注释:】
并不要求删除的文本长度与插入的长度一定相同。
- //只删除了3个字符,但是在同一个位置却插入了6个字符。
- str.replace(11,3,"Fourth");
STL实践与分析
--再谈string类型(下)
四、string类型的查找操作
string类型提供了6种查找函数,每种函数以不同形式的find命名。这些操作全部返回string::size_type类型的值,以下标的方式标记查找匹配所发生的位置;或者返回一个string::npos的特殊值,说明查找没有匹配。string类将npos定义为保证大于任何有效下标的值。
string类型的查找操作(参数在下表定义)
s.find(args)
在s中查找args的第一次出现
s.rfind(args)
在s中查找args的最后一次出现
s.find_first_of(args)
在s中查找args的任意字符的第一次出现
s.find_last_of(args)
在s中查找args的任意字符的最后一次出现
s.find_first_not_of(args)
在s中查找第一个不属于args的字符
s.find_last_not_of(args)
在s中查找最后一个不属于args的字符
每种查找都有4个重载版本,每个版本使用不同的参数集合。这些操作的不同之处在于查找的到底是单个字符、另一个string字符串、C风格的以空字符结束的字符串,还是用字符数组给出的特定数据的字符集合。
string类型提供的find操作的参数
c,pos
在s中,从下标pos标记的位置开始,查找字符c。pos的默认值为0
s2,pos
在s中,从下标pos标记的位置开始,查找string对象s2。pos的默认值为0
cp,pos
在s中,从下标pos标记的位置形参,查找指针cp所指向的C风格的以空字符结束的字符串。pos的默认值为0
cp,pos,n
在s中,从下标pos标记的位置开始,查找指针cp所指向数组的前 n个字符。pos和n都没有默认值
1、精确匹配查找
find函数,如果找到的话,则返回第一次匹配的下标值;如果找不到,则返回npos:
- string name("AnnaBelle");
- string::size_type pos = name.find("Anna");
默认情况下,find操作以及其他处理字符的string操作使用内置操作符比较string字符串中的字符。因此,这些操作(以及其他string操作)都区分字母的大小写;
- string lowerCase("annabelle");
- string::size_type pos = lowerCase.find("Anna");
- if (pos != string::npos)
- {
- cout << lowerCase[pos] << endl;
- }
find操作的返回类型是string::size_type类型,请使用该类型的对象存储find的返回值。
2、查找任意字符
- //在name中寻找并定位第一个数字
- string numeric("1234567890");
- string name("r2d2");
- string::size_type pos = name.find_first_of(numeric);
- cout << pos << endl
- << name[pos] << endl;
【谨记:】
string对象的元素下标从0开始计数;
3、指定查找的起点
程序员可以给find操作传递一个可选的起点位置实参,用于指定开始查找的下标位置,该位置实参的默认值为0。通常的编程模式是使用这个可选的实参循环查找string对象中所有的匹配。
- //重写查找“r2d2”的程序,以便找出 name 字符串中出现的所有数字:
- string numeric("0123456789");
- string name("r2d25");
- string::size_type pos = 0;
- while ((pos = name.find_first_of(numeric,pos)) != string::npos)
- {
- cout << name[pos] << endl;
- ++ pos;
- }
pos必须+1,以确保下一次循环从刚找到的数字后面开始查找下一个数字。
4、寻找不匹配点
调用find_first_not_of函数查找第一与实参不匹配的位置:
- //在 string 对象中寻找第一个非数字字符
- string numeric("1234567890");
- string dept("03714p3");
- string::size_type pos = dept.find_first_not_of(numeric);
- if (pos != string::npos)
- {
- cout << dept[pos] << endl;
- }
5、反向查找
迄今为止,我们使用的所有find操作都是从左向右查找的。除此之外,标准库还提供了一组类似的从右向左查找string对象的操作。Rfind成员函数用于寻找最后一个– 也就是最右边 – 制定子串出现的位置:
- string river("Miississippi");
- string::size_type first_pos = river.find("is");
- if (first_pos != string::npos)
- {
- cout << "first_pos: " << first_pos << endl;
- }
- string::size_type last_pos = river.rfind("is");
- if (last_pos != string::npos)
- {
- cout << "last_pos: " << last_pos << endl;
- }
6、find_last函数
find_last函数类似对应的find_first函数,唯一的差别在于find_last函数返回最后一个匹配的位置,而不是第一个
1)find_last_of函数查找与目标字符串的任意字符匹配的最后一个字符。
2)find_last_not_of函数查找最后一个不能跟目标字符串的任何字符匹配的字符。
这两个操作都提供第二个参数,这个参数是可选的,用于指定在string对象中开始查找的位置。
- //P297 习题9.38
- //(1)
- string str("ab2c3d7R4E6");
- string numeric("0123456789");
- string::size_type pos = 0;
- while ((pos = str.find_first_of(numeric,pos)) != string::npos)
- {
- cout << str[pos] << endl;
- ++ pos;
- }
- //(2)
- string str("ab2c3d7R4E6");
- string numeric("0123456789");
- string::size_type pos = 0;
- while ((pos = str.find_first_not_of(numeric,pos)) != string::npos)
- {
- cout << str[pos] << endl;
- ++ pos;
- }
- //习题9.39
- #include <iostream>
- #include <sstream>
- #include <stack>
- using namespace std;
- int main()
- {
- string line1 = "We were her pride of 10 she named us:";
- string line2 = "Benjamin, Phoenix, the Prodigal";
- string line3 = "and perspicacious pacific Suzanne";
- string sentence = line1 + ' ' + line2 + ' ' + line3;
- istringstream item(sentence);
- unsigned int shoest = 1000;
- unsigned int lonest = 0;
- stack<string> shoSta;
- stack<string> lonSta;
- string word;
- int wordCnt = 0;
- while (item >> word)
- {
- ++ wordCnt;
- if (word.size() > lonest)
- {
- lonest = word.size();
- while (!lonSta.empty())
- {
- lonSta.pop();
- }
- lonSta.push(word);
- }
- else if (word.size() == lonest)
- {
- lonSta.push(word);
- }
- if (word.size() < shoest)
- {
- shoest = word.size();
- while (!shoSta.empty())
- {
- shoSta.pop();
- }
- shoSta.push(word);
- }
- else if(word.size() == shoest)
- {
- shoSta.push(word);
- }
- }
- cout << wordCnt << endl;
- cout << endl << "Longest Word:" << endl;
- while (!lonSta.empty())
- {
- cout << lonSta.top() << endl;
- lonSta.pop();
- }
- cout << endl << "Shortest Word:" << endl;
- while (!shoSta.empty())
- {
- cout << shoSta.top() << endl;
- shoSta.pop();
- }
- }
五、string对象的比较
1、传统的操作符比较
string类型定义了所有关系操作符,使程序员可以比较两个string对象是否相等(==)、不等(!=),以及实现小于或大于(<、<=、>、>=)运算。string对象采用字典顺序比较,也就是说,string对象的比较与大小写敏感的字典顺序比较相同
2、compare函数
操作的结果类似于C语言中的strcmp函数:
string类型的compare操作
s.compare(s2)
比较s和s2
s.compare(pos1,n1,s2)
让s中从pos下标位置开始的n1个字符与s2做比较
s.compare(pos1,n1,s2,pos2,n2)
让s中从pos1下标位置开始的n1个字符与s2中从pos2下标位置开始的n2个字符做比较
s.compare(cp)
比较s和cp所指向的以空字符结束的字符串
s.compare(pos1,n1,cp)
让s中从pos1下标位置开始的n1个字符与cp所指向的字符串做比较
c.compare(pos1,n1,cp,n2)
让s中从pos1下标位置开始的n1个字符与cp所指向的字符丰的前n2个字符做比较
compare函数返回下面列出的三种可能值之一:
1)正数,此时s1大于 args所代表的string对象。
2)负数,此时s1小于 args所代表的string对象。
3)0,此时 s1恰好等于 args所代表的string对象。
- string cobol_program_crash("abend");
- string cplus_program_crash("abort");
- cout << cobol_program_crash.compare(cplus_program_crash) << endl;
- cout << cplus_program_crash.compare(cobol_program_crash) << endl;
compare函数提供了6个重载版本,方便程序员实现一个或两个string对象的子串的比较,以及string对象与字符数组或其中一部分的比较:
- char second_ed[] = "C++ Primer, 2nd Edition";
- string third_ed("C++ Primer, 3rd Edition");
- string fourth_ed("C++ Primer, 4th Edition");
- cout << fourth_ed.compare(second_ed) << endl;
- cout << fourth_ed.compare(fourth_ed.find("4th"),3,
- third_ed,third_ed.find("3rd"),3)
- << endl;
- //P299 习题9.40
- int main()
- {
- string q1("When lilacs last in the dooryard bloom`d");
- string q2("The child is father of the man");
- string sentence;
- sentence.assign(q2,0,12);
- sentence.append(q1,16,16);
- cout << sentence << endl;
- }
- //习题9.41
- string greet(string form,string lastname,string title,
- string::size_type pos,int length)
- {
- string::iterator beg,end;
- beg = form.begin() + form.find("Daisy");
- end = beg + 5;
- form.replace(beg,end,lastname);
- beg = form.begin() + form.find("Ms");
- end = beg + 2;
- form.replace(beg,end,title.substr(pos,length));
- return form;
- }
- /*
- string greet(string form,string lastname,string title,
- string::size_type pos,int length)
- {
- form.replace(form.find("Daisy"),5,lastname);
- form.replace(form.find("Ms"),2,title,pos,length);
- return form;
- }
- */
- int main()
- {
- string generic1("Dear Ms Daisy:");
- string generic2("MrsMsMisssPeople");
- string lastName("AnnaP");
- string salute = greet(generic1,lastName,generic2,5,4);
- cout << salute << endl;
- }
本文借鉴:http://blog.csdn.net/column/details/zjf666.html?&page=4
- C++(13)STL实践与分析之再谈String类型
- C++(15)STL实践与分析之Map类型
- C++(12)STL实践与分析之顺序容器
- C++(14)STL分析与实践之容器适配器
- C++(16)STL实践与分析之初探算法
- C++(17)STL实践与分析之再谈迭代器
- C++ STL string类型
- STL之string类型
- C++STL之string
- C++STL之string
- C++STL之string
- C++STL之string
- c++STL之string
- C++STL之string
- C++STL之string
- C++STL之string
- C++STL之string
- C++STL之string
- Java IO流--IO包中的其他类
- 杭电acm 2139 Calculate the formula
- Python简单爬虫
- POJ-2196 Specialized Four-Digit Numbers-10,12,16进制的各个位数相加彼此相等的数
- hdu 5363 Key Set(水)
- C++(13)STL实践与分析之再谈String类型
- Arduino入门知识
- IO流
- JavaScript——实现时间的动态显示
- maven使用私服(其他我没测试)无法导入jar文件问题
- A. GukiZ and Contest-Codeforces Round #307 (Div. 2)-简单水题
- 【CF245H】【Queries for Number of Palindromes】
- android 设置全屏,窗口透明度,待机设置,主题设置总结
- Objective-C文章中的生词