欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > string

string

2025/5/11 0:19:58 来源:https://blog.csdn.net/m0_73284013/article/details/144067503  浏览:    关键词:string

string类对象的常见构造:

void test_string1()
{string s0;string s1("hello world");string s2(s1);string s3(s1, 5, 3);string s4(s1, 5, 10);string s5(s1, 5);cout << s0 << endl;//输出空cout << s1 << endl;//输出hello worldcout << s2 << endl;//输出hello worldcout << s3 << endl;//输出 wocout << s4 << endl;//输出 worldcout << s5 << endl;//输出 worldstring s6(10, '#');cout << s6 << endl;//输出##########s0 = s6;cout << s0 << endl;//输出##########
}

模仿数组的访问:

有两个版本,第一个可读可写,第二个可读

构成运算符重载和函数重载,但是如果参数相同,只有返回值不同不能构成重载

这里不同,隐含的ths指针不同,一个是string*,一个是const string*,const修饰的是this指针指向的内容

void test_string2()
{string s1("hello world");// 下标+[]:char& operator[](size_t pos)for (size_t i = 0; i < s1.size(); i++){cout << s1[i] << " ";//本质是函数调用:cout << s1.operator[](i) << " ";}cout << endl;//可以修改for (size_t i = 0; i < s1.size(); i++){s1[i]++;}cout << endl;//普通对象可以修改string s3("hello world");s3[0]++;cout << s3 << endl;//const对象不能修改const string s2("hello world");//s2[0]++;cout << s2 << endl;cout << s3.size() << endl;cout << s3.capacity() << endl;
}

对象.at() 访问:

二者实现出来一样,显示o,但是判错不一样,这个用的少

	string s1("xhello world");cout << s1[5] << endl;cout << s1.at(5) << endl;//异常捕获try{//s1[15];//这个不起作用//s1.at(15);//这个可以检查出来}catch (const exception& e){cout << e.what() << endl;}

迭代器:

行为像指针一样的类型对象

begin返回第一个位置的迭代器

end是最后一个字符的下一个位置

定义在string这个类里面的,所以使用时要指定类域

void test_string3() {string s4("hello world");//迭代器string::iterator it = s4.begin();while (it != s4.end()){cout << *it << " ";++it;}cout << endl;
}int main()
{//test_string1();//test_string2();test_string3();return 0;
}

可修改:

string::iterator it3 = s3.begin();while (it3 != s3.end()){*it3 -= 3;//修改,对每个字符减三++it3;}cout << endl;it3 = s3.begin();while (it3 != s3.end()){cout << *it3 << " ";++it3;}cout << endl;

下标+[ ]和迭代器作用一样,但是迭代器才是主流,才是容器访问的核心方式

string和顺序表适合下标+[ ],但是链表、树都不行

	//顺序表vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;//链表list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator itt = lt.begin();while (itt != lt.end()){cout << *itt << " ";++itt;}cout << endl;

 

	// 底层就是迭代器//范围for可以遍历容器for (auto e : s3){cout << e << " ";}cout << endl;for (auto e : v){cout << e << " ";}cout << endl;for (auto e : lt){cout << e << " ";}cout << endl;

反向迭代器:reverse_iterator

    string s1("hello world");string::reverse_iterator rit = s1.rbegin();while (rit != s1.rend()){cout << *rit << " ";++rit;//还是++}cout << endl;

const迭代器: const_iterator

	// const迭代器 只读const string s3("hello world");string::const_iterator it3 = s3.begin();while (it3 != s3.end()){// *it3 += 3;cout << *it3 << " ";++it3;}cout << endl;

Capacity:

size和length一样

capacity:

	// 查看扩容机制string s;size_t sz = s.capacity();cout << "capacity changed: " << sz << '\n';cout << "making s grow:\n";for (int i = 0; i < 100; ++i){s.push_back('c');//自动扩容if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}cout << s1 << endl;cout << s1.capacity() << endl;cout << s1.size() << endl;

clear :

shrink_to_fit:

    string s1("hello worldxxxxxxxxxxxxxxx")cout << s1 << endl;cout << s1.capacity() << endl;cout << s1.size() << endl;//只清理数据,不清理空间s1.clear();cout << s1 << endl;cout << s1.capacity() << endl;cout << s1.size() << endl;// 缩容,默认缩容到15s1.shrink_to_fit();cout << s1.capacity() << endl;cout << s1.size() << endl;

reserve:

使用reserve手动扩容,请求提前开好一个空间,就不用反复扩容了,提高效率

reserve比capacity大才起作用,不会缩容

// reverse // 反转 翻转
// reserve // 保留,请求提前开好一个空间string s;s.reserve(100);//真实会比100大

resize:

比size小:删除

比size大:插入,默认插入\0

比capacity大:扩容+插入

    string s2("hello worldxxxxxx");cout << s2.size() << endl;cout << s2.capacity() << endl << endl;s2.resize(10);cout << s2.size() << endl;cout << s2.capacity() << endl << endl;s2.resize(20);cout << s2.size() << endl;cout << s2.capacity() << endl << endl;s2.resize(100, 'x');cout << s2.size() << endl;cout << s2.capacity() << endl << endl;

元素访问:

前两种在上文

后两种是取头尾的字符,用[ ]也可以代替,实践中没什么用

修改:

operator+=:

+=,相当于拼接

	string s3("hello world");s3 += ' ';s3 += "apple";cout << s3 << endl;

附加:append

+=用的多,这个用的少

	string s1("xhello world");//只能插入一个字符 chars1.push_back('!');cout << s1 << endl;//插入字符串s1.append("hello bit");cout << s1 << endl;//插入n个字符s1.append(10, 'x');cout << s1 << endl;//迭代区间string s2("  apple ");s1.append(s2);cout << s1 << endl;//这样就少插入s2空格s1.append(++s2.begin(), --s2.end());cout << s1 << endl;

覆盖:assign 

	string s1("xhello world");cout << s1 << endl;s1.assign(" xxxxx");cout << s1 << endl;//xxxxx

插入:insert

少用,要挪动数据,效率不高

在pos位置之前插入

	s1.insert(0, "yyyy");cout << s1 << endl;//yyyyxxxxx

删除:erase

尽量少用,要挪动数据,效率不高,和clear功能重叠

如果太短,删到结束

	s1.erase(5, 3);cout << s1 << endl;s1.erase();//删空了cout << s1 << endl;

替换:replace

少用,要挪动数据,效率不高

	string s2("hello world hello bit");//第五个那一个字符替换成20%s2.replace(5, 1, "20%");cout << s2 << endl;

查找:find

	size_t pos = s2.find(' ');//如果找到了就继续,没找到就返回nposwhile (pos != string::npos){s2.replace(pos, 1, "20%");pos = s2.find(' ');}cout << s2 << endl;

将空格替换成20%——效率高的做法(空间换时间) 

	//避免在后续向 s3 中添加字符时频繁地进行内存重新分配操作s3.reserve(s2.size());for (auto ch : s2)//依次遍历字符串 s2 中的每个字符//在每次循环中,将当前字符赋值给变量 ch	{if (ch != ' '){s3 += ch;}else{s3 += "20%";}}cout << s3 << endl;s2.swap(s3);

字符串操作:

 查找:find

find返回的pos位置是下标,从0开始计数

	size_t pos = s2.find(' ');//如果找到了就继续,没找到就返回nposwhile (pos != string::npos){s2.replace(pos, 1, "20%");pos = s2.find(' ');}cout << s2 << endl;
	// 拿到文件的后缀size_t pos1 = s1.rfind('.');//rfind:从后往前找if (pos1 != string::npos){string suffix = s1.substr(pos1);//默认直接取到npos//string suffix = s1.substr(pos1, s1.size()-pos1);cout << suffix << endl;}else{cout << "没有后缀" << endl;}

生成新字符串:substr 

从pos位置开始,长度为len,pos为下标

	string url1("https://legacy.cplusplus.com/reference/string/string/substr/");string protocol, domain, uri;size_t i1 = url1.find(':');if (i1 != string::npos){protocol = url1.substr(0, i1 - 0);cout << protocol << endl;}// 类比strcharsize_t i2 = url1.find('/', i1 + 3);if (i2 != string::npos){domain = url1.substr(i1 + 3, i2 - (i1 + 3));cout << domain << endl;uri = url1.substr(i2 + 1);cout << uri << endl;}// 类比strstr  size_t i3 = url1.find("baidu");cout << i3 << endl;

find-first-of:

std::string str("Please, replace the vowels in this sentence by asterisks.");cout << str << endl;// 类比strtokstd::size_t found = str.find_first_not_of("aeiou");while (found != std::string::npos){str[found] = '*';found = str.find_first_not_of("aeiou", found + 1);}cout << str << endl;

运算符重载:

	//比大小按照ASCII码比cout << (url1 < url2) << endl;string ss1 = "xxx";//单参数构造函数支持隐式类型转换,char srtingstring ss2 = "yyy";string ret = ss1 + ss2;cout << ret << endl;string ret1 = ss1 + "yyyy";string ret2 = "yyyy" + ss2;

转换:

	int i = 1234;double d = 11.22;string s1 = to_string(i);string s2 = to_string(d);string s3("45.55");double d3 = stod(s3);

练习:

仅反转字母

class Solution {
public:bool isLetter(char ch){if(ch>='a' && ch<='z'){return true;}if(ch>='A' && ch<='Z'){return true;}return false;}string reverseOnlyLetters(string s) {if(s.empty()){return s; }size_t begin = 0, end = s.size()-1;while(begin < end){while((begin < end) && !isLetter(s[begin])){++begin;}while((begin < end) && !isLetter(s[end])){--end;}swap(s[begin], s[end]);++begin;--end;}return s;}};

字符串中的第一个唯一字符

class Solution {
public:int firstUniqChar(string s) {int count[256] = {0};for(int i = 0; i < s.size(); i++){count[s[i]] += 1;}for(int i = 0;i < s.size(); i++){if(count[s[i]] == 1){return i;}}return -1;}
};
class Solution {
public:int firstUniqChar(string s) {int count[26] = {0};for(auto ch : s){count[ch - 'a'] ++;}for(int i = 0;i < s.size(); i++){if(count[s[i] - 'a'] == 1){return i;}}return -1;}
};

字符串相加

class Solution {
public:string addStrings(string num1, string num2) {//存当前位数的下标int endnum1 = num1.size()-1;int endnum2 = num2.size()-1;string str;//进位int next = 0;while(endnum1 >= 0 || endnum2 >= 0){int val1 = endnum1 >= 0? num1[endnum1--]-'0' :0;int val2 = endnum2 >= 0? num2[endnum2--]-'0' :0;int ret = val1 + val2 + next;next = ret / 10;//只要十位ret = ret % 10;//只要个位str += (ret + '0');}if(next == 1){str += '1';}reverse(str.begin(), str.end());return str;}
};

字符串最后一个单词的长度

使用cin和scanf输入时,遇到空格和换行就默认是两个字符之间的分割,所以这里要是使用cin输入了hello nowcoder,第一次只读取hello,再cin一下才能从缓冲区读到nowcoder

使用getchar可以解决遇到空格就结束的问题,只遇到换行结束

或者使用getline

delim:边界,定界,可以自己设置结束符号

#include <iostream>
using namespace std;int main() {string str;//第一种// char ch;// ch = getchar();// while(ch != '\n'){//     str += ch;//     ch = getchar();// }//第二种getline(cin,str);size_t pos = str.rfind(' ');pos += 1;cout<<str.size() - pos<<endl;return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词