从C语言到C++_11(string类的常用函数)力扣58和415(上):https://developer.aliyun.com/article/1513666
4. string类对象的访问及遍历操作
这里 operator[] 是使用引用返回,是为了能够支持修改返回的变量。
我们就可以像数组一样操作string了。
迭代器是 STL 六大组件之一,是用来访问和修改容器的。
如果你是第一次接触 "迭代器的概念",不妨可以先把迭代器想象成 "像指针一样的类型"。
对于 string,无论是正着遍历,倒着遍历,下标 + [] 都足够好用,为什么还要迭代器呢?
当然,对于 string,下标和 [] 确实足够好用,我们在学习C语言的时候就先入为主地使用了,
确实可以不用迭代器。但是如果是其他容器(数据结构)呢?
比如 list、map / set 不支持 下标 + [] 遍历,迭代器就排上用场了,
这就是迭代器存在的意义。迭代器是通用的遍历方式。
对于 string,你得会用迭代器,但是一般我们还是喜欢用 下标 + [] 遍历。
迭代器有很多,此外还有反向迭代器、const 迭代器……
这些都可以通过看文档去了解和学习。对于迭代器后面还会详细讲解,
范围 for。
这个我们在讲 auto 关键字的时候讲过了,它是一个用起来是很甜的语法糖。
这个范围 for 虽然看起来和听上去都很强,又是自动迭代又是自动判断结束的,
但其实它底层也就是编译器在编译后把这段代码替换成了迭代器而已。
void test_string3() { string s1("hello world"); s1[0] = 'x'; //s1[20]; 内部会检查越界 cout << s1 << endl; for (size_t i = 0; i < s1.size(); ++i)// 普通遍历string,每个字符+1 { s1[i]++; } cout << s1 << endl; string::iterator it = s1.begin();// 迭代器遍历string,每个字符+1 while (it != s1.end()) { (*it)++; it++; } cout << s1 << endl; for (auto& e : s1)// 范围for遍历string,每个字符-1 { e--; } cout << s1 << endl; string::reverse_iterator rit = s1.rbegin();// 迭代器逆置遍历string,每个字符-1 while (rit != s1.rend()) { cout << *rit; (*rit)--; ++rit;// 注意这里也是++ } cout << endl; *(s1.begin()) = 'h';// 把第一个字母改成h -> s1[0] = 'h'; cout << s1 << endl; }
5. string类对象的修改操作
这个 c_str 有什么意义呢?
比如这里需要打开文件,fopen 第一个参数要求是 const char*,
所以这里怎么能直接放 string 是不行的,这时候可以用 .c_str() 就可以把字符串的地址返回出来。
简单接口演示:
void test_string4() { string s("hello"); s.push_back('-'); s.push_back('-'); s.append("world"); cout << s << endl; string str("abcdefg"); s += '@'; s += str; s += "!!!"; cout << s << endl; s.append(++str.begin(), --str.end()); cout << s << endl; string copy(s.begin() + 3, s.end() - 3); cout << copy << endl; int ival = 2023; double dval = 3.14; cout << to_string(ival) << endl; cout << to_string(dval) << endl; string istr = "9999"; string dstr = "9999.99"; cout << stoi(istr) << endl; cout << stod(dstr) << endl; }
上面 += 是最好用且最常用的,看看 rfind 和 find 的使用场景:
void DealUrl(const string& url) { // 取出协议 size_t pos1 = url.find("://"); if (pos1 == string::npos) { cout << "非法url" << endl; return; } string protocol = url.substr(0, pos1); cout << protocol << endl; // 取出域名 size_t pos2 = url.find('/', pos1 + 3);// 冒号位置+3开始往后找 if (pos2 == string::npos) { cout << "非法url" << endl; return; } string domain = url.substr(pos1 + 3, pos2 - pos1 - 3); cout << domain << endl; // 取出路径 string uri = url.substr(pos2 + 1); cout << uri << endl << endl; } void test_string5() { string filename("test.cpp.tar.zip");// 取后缀 size_t pos = filename.rfind('.');// 反向找 if (pos != string::npos) { //string suff = filename.substr(pos, filename.size() - pos); string suff = filename.substr(pos);//不用像上一行算长度,直接让默认值取到最后 cout << suff << endl; } string url1 = "https://cplusplus.com/reference/string/string/";// 对一个网址进行操作,可以多放几个试试 DealUrl(url1); }
6. string类非成员函数
上面的几个接口大家了解一下,后面的 OJ 题目中会有一些体现他们的使用。
string类中还有一些其他的操作,这里不一一列举,大家在不明白时查文档即可。
7. string的相关笔试题
1. 关于代码输出正确的结果是( )(vs2013 环境下编译运行)
int main() { string a = "hello world"; string b = a; if (a.c_str() == b.c_str()) { cout << "true" << endl; } else cout << "false" << endl; string c = b; c = ""; if (a.c_str() == b.c_str()) { cout << "true" << endl; } else cout << "false" << endl; a = ""; if (a.c_str() == b.c_str()) { cout << "true" << endl; } else cout << "false" << endl; return 0; }
A.false false false
B.true false false
C.true true true
D.true true false
2. 下面程序的输出结果正确的是( )
int main() { string str("hello world"); str.reserve(111); str.resize(5); str.reserve(50); cout << str.size() << " " << str.capacity() << endl; return 0; }
A.10 50
B.5 50
C.5 111
D.10 111
3. 下面程序的输出结果正确的是( )
int main() { string strText = "How are you?"; string strSeparator = " "; string strResult; int size_pos = 0; int size_prev_pos = 0; while ((size_pos = strText.find_first_of(strSeparator, size_pos)) != string::npos) { strResult = strText.substr(size_prev_pos, size_pos - size_prev_pos); cout << strResult << " "; size_prev_pos = ++size_pos; } if (size_prev_pos != strText.size()) { strResult = strText.substr(size_prev_pos, size_pos - size_prev_pos); cout << strResult << " "; } cout << endl; return 0; }
A.Howareyou?
B.How Are You?
C.How are
D.How are you?
答案:
1. A
分析:a 和 b的值虽然相同,但是a.c_str()==b.c_str()比较的是存储字符串位置的地址,a和b是两个不同的对象,内部数据存储的位置也不相同,因此不相等,后面c="",a=""与b对象都没有任何的影响,所以都不相等
2. C
分析:
str.reserve(111); //调整容量为 111
str.resize(5); //调整元素个数为 5
str.reserve(50); //调整容量为 50,由于调整的容量小于已有空间容量,故容量不会减小
所以size=5 capacity=111
3. D
分析:程序的目的是以字符串strSeparator = " "作为分隔符,对字符串string strText = "How are you?";进行分割,每分割出一个单词就进行一次打印
从C语言到C++_11(string类的常用函数)力扣58和415(下):https://developer.aliyun.com/article/1513668?spm=a2c6h.13148508.setting.18.5e0d4f0eB41884