欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > C++(初阶)(八)——string

C++(初阶)(八)——string

2025/3/25 18:22:59 来源:https://blog.csdn.net/2401_88328558/article/details/146483292  浏览:    关键词:C++(初阶)(八)——string

string

  • string
    • 遍历
      • 下标+[]
      • 迭代器
        • iterator
        • 反向迭代器
      • 范围for
        • 修改
    • Capacity
      • size和length
      • max_size
      • capacity
      • clear
      • capacity的扩容
      • reserve
      • resize
    • Element access
      • operator[]和at
    • **Modifiers**:
      • append
      • insert
      • erase
      • replace
    • String operations
      • c_str
      • substr和find
      • find_first_of
      • getline
    • 题目
      • [387. 字符串中的第一个唯一字符](https://leetcode.cn/problems/first-unique-character-in-a-string/)
      • [415. 字符串相加](https://leetcode.cn/problems/add-strings/)

string是一个模板,管理char的顺序表

typedef basic_string<char> string;

string存在于c++标准模板库std中,如果std没有展开需要加上std::

底层是顺序表

class string
{
public://本质是返回引用,这样可以修改返回值char& operator[](size_t i){return _str[i];}
private:char* _str;size_t _size;size_t _capacity;
};
(constructor)函数名称功能说明
string() (重点)构造空的string类对象,即空字符串
string(const char* s) (重点)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s) (重点)拷贝构造函数
clsss Stack()
{...
};int main()
{string s1;string s2("hello world");string s3 = "hello world";//如果使用&(引用),必须加const,因为s4引用的不是常量串,而是中间产生的临时对象(具有常性)const string& s4 = "hello world";//可以实例化为int,当然也可以实例化为string(串)Stack<string> st;//第一种//string s5("你好");//st.Push(s5);//第二种st.Push("你好");string s6(s5);//开11个空间,末尾是'\0',前面是10个#string s7(10,"#");return 0;
}

string (const string& str, size_t pos, size_t len = npos);

npos在32位系统下,最大为42亿多,-1是unsinged int类型的最大值(42亿多),作为npos缺省值

int main()
{string s1("hello world");//从下标为3处开始的10个字符,如果取的字符多于原字符串,直到取完原字符结束string s2(s1,3,10);、cout << s2 <<endl;return 0;
}

遍历

string重载了operator[](一个是普通的(可修改)一个是const的(仅读))

下标+[]

int main()
{string s1("hello world");s1[0]++;cout << s1 << endl;s1[0] = 'x';cout << s1 << endl;//size不包含'\0'for(size_t i = 0; i < s1.size(); i++){s1[i]++;}cout << s1 << endl;for(size_t i = 0; i < s1.size(); i++){cout << s1[i] << " ";}cout << endl;//存在越界检查//s1[13];	//编译会报错
}//iello world
//xello world
//yfmmp!xpsme
//y f m m p ! x p s m e

迭代器

iterator

iterator是string类域中的一个类型,迭代器是类似指针的东西,begin是开始的位置,end是结束的下一个位置,即左闭右开区间[begin(),end())

int main()
{string s1("hello world");//容器通用访问方式string::iterator it = s1.begin();while (it != s1.end()){cout << *it << " ";++it;}cout << endl;//修改it = s1.begin();while (it != s1.end()){(*it)--;++it;}cout << endl;return 0;
}
//y f m m p ! x p s m e
//h e l l o   w o r l d
#include<iostream>
#include<vector>
//包含各种算法
#include<algorithm>
using namespace std;
int main()
{vector<int> a;for (int i = 0; i < 5; i++){a.push_back(i);}//auto vt = a.begin();	//auto自动推断类型,注意:作为返回值时慎用vector<int>::iterator vt = a.begin();while (vt != a.end()){cout << *vt << " ";++vt;}cout << endl;//逆置(反转)//为函数模板,传迭代器,左闭右开区间,针对所有容器reverse(a.begin(), a.end());vt = a.begin();while (vt != a.end()){cout << *vt << " ";++vt;}cout << endl;return 0;
}
//0 1 2 3 4
反向迭代器

反向迭代器,与正向的是相反的,++是向左走

注意是:reverse_iterator

int main()
{string s("hello world");//注意是rbegin()和rend()string::reverse_iterator rit = s.rbegin();while (rit != s.rend()){cout << *rit << " ";++rit;}cout << endl;return 0;
}
//d l r o w   o l l e h

普通迭代器可以读也可以修改,const迭代器可以读不可以修改

当然也有const反向迭代器

范围for

自动取容器数据依次赋值给对象,自动判断结束

#include<iostream>
using namespace std;
int main()
{//遍历字符串string str("hello world");//依次取str的拷贝给x,所以如果要对内容修改,要使用引用for (auto x : str){cout << x << " ";}cout << endl;//遍历数组int arr[6] = { 1,2,3,4,5,6 };for (auto x : arr){cout << x << " ";x++;}cout << endl;return 0;
}
修改
#include<iostream>
using namespace std;
int main()
{string str("hello world");//依次取str的拷贝给x,所以如果要对内容修改,要使用引用//for (auto x : str)//{//	x--;//}for (auto& x : str){x--;}for (auto x : str){cout << x << " ";}cout << endl;return 0;
}
//g d k k n  v n q k c

Capacity

size和length

size是不包含’\0’的

string s1("hello world");
cout << s1.size() << endl;
cout << s1.length() << endl;
//11
//11

length也是求字符串长度,还是推荐使用size

max_size

字符串最大长度

string s2;
cout << s2.max_size() <<endl;
//此处是32位系统
//2147483647

capacity

容量大小

string s2;
cout << s2.capacity() << endl;
//15(其实大小是16,因为还存储着'\0')

clear

清除数据,但是不会清除空间,相当于将size置为0

capacity的扩容

string s;
size_t old = s.capacity();
cout << old << endl;
for(size_t i = 0;i < 100;i++)
{s.push_back('x');if(s.capacity() != old){//扩容cout << s.capacity() << endl;old = s.capacity();}
}//vs下的扩容是第一次2倍,之后为1.5倍。不同的环境下扩容情况有所不同,例如在linux下是标准的2倍扩容。//15
//31
//47
//70
//105

reserve

reverse逆置翻转

reserve保留储藏储备

//扩容string s;
//提前知道使用多少空间,直接开辟完成
s.reserve(200);
size_t old = s.capacity();
cout << old << endl;
for(size_t i = 0;i < 100;i++)
{s.push_back('x');if(s.capacity() != old){//扩容cout << s.capacity() << endl;old = s.capacity();}
}
//在vs下开辟了207
//207

缩容,不同平台下不一样,可能不缩,建议不使用,与编译平台实现有关。

如果需要缩容,使用Shrink to fit

建议只使用reserve的扩容

resize

void resize (size_t n);
void resize (size_t n, char c);

在这里插入图片描述

string s1("xxxxxxxxxxxxxxxxxx");
cout << s1.size() << endl;
cout << s1.capacity() << endl;//插入数据,扩容插入数据
s1.resize(20);
s1.resize(25, 'y');
s1.resize(40, 'z');
cout << s1.size() << endl;
cout << s1.capacity() << endl;//删除数据
s1.resize(5);
cout << s1.size() << endl;
cout << s1.capacity() << endl;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

Element access

operator[]和at

区别在于对越界的检查方式

operator[]是断言,at是抛异常,可以捕获

	string s1("aaaaa");s1[0] = 'x';cout << s1 << endl;s1.at(1) = 'v';cout << s1 << endl;//xaaaa//xvaaa

Modifiers:

append

追加,附加

string s1("xxxxx");
cout << s1 <<endl;s1.push_back('y');
cout << s1 <<endl;s1.append("zzzz");
cout << s1 <<endl;string s2("haha");
s1.append(s2);
cout << s1 <<endl;//xxxxx
//xxxxxy
//xxxxxyzzzz
//xxxxxyzzzzhaha//追加迭代区间,可以只取一部分
s1.append(++s2.begin(),--s2.end());
cout << s1 <<endl;//xxxxxyzzzzhahaah//经常使用的是+=的运算符重载
s1 += 'n';
cout << s1 <<endl;
s1 += "llllll";
cout << s1 <<endl;//xxxxxyzzzzhahaahn
//xxxxxyzzzzhahaahnllllll

insert

插入字符,是将全部字符向后移动插入,时间复杂度是O(n),谨慎使用

string s1("aaaaa");
cout << s1 << endl;s1.insert(0, 1, 'c');
cout << s1 << endl;//多个插入
s1.insert(0, 3, 'k');
cout << s1 << endl;s1.insert(0,"pppp");
cout << s1 << endl;//支持迭代器
s1.insert(s1.begin(),3,'m');
cout << s1 << endl;//aaaaa
//caaaaa
//kkkcaaaaa
//ppppkkkcaaaaa
//mmmppppkkkcaaaaa

erase

删除字符,覆盖删除,底层要挪动数据,谨慎使用

string s2("hello world");
cout << s2 << endl;s2.erase(5,2);
cout << s2 << endl;//有多少删多少
s2.erase();
cout << s2 << endl;//hello world
//helloorld
//(全删除)

replace

底层要挪动数据,谨慎使用

string s1("hello world");
cout << s1 << endl;s1.replace(5,1,"%%%");
cout << s1 << endl;//hello world
//hello%%%world

将字符串中的空格替换为%%

string s1("hello world hello c");
cout << s1 << endl;
for(size_t i = 0; i < s1.size();i++)
{if(s1[i] == ' '){s1.replace(i,1,"%%");}
}
cout << s1 << endl; 

但是这种方式的效率是非常低的

string s2("hello world hello c");
string s3;
s3.reserve(s2.size());
for(auto ch : s2)
{if(ch != ' '){s3 += ch;}else{s3 += "%%";}
}
s2 = s3;
cout << s2 << endl;

String operations

c_str

为了兼容c语言的接口,返回的字符串需要在末尾有’\0’

substr和find

#include<iostream>
#include<string>using namespace std;
int main()
{string ur1("https://cplusplus.com/reference/string/string/?kw=string");size_t pos1 = ur1.find(':');if (pos1 != string::npos){string sub1 = ur1.substr(0, pos1);cout << sub1 << endl;}size_t pos2 = ur1.find('/',pos1+3);if (pos1 != string::npos){string sub2 = ur1.substr(pos1 + 3, pos2-(pos1 + 3));cout << sub2 << endl;string sub3 = ur1.substr(pos2 + 1);cout << sub3 << endl;}return 0;
}

find_first_of

使用较少

find是找第一个,rfind是找最后一个

find是找字符或者子串

find_first_of在字符串中找给定的字符或者子串

int main ()
{std::string str ("Please, replace the vowels in this sentence by asterisks.");//在str中找aeioustd::size_t found = str.find_first_of("aeiou");while (found!=std::string::npos){//找到aeiou换成*,从找到位置的+1继续找str[found]='*';found=str.find_first_of("aeiou",found+1);}std::cout << str << '\n';return 0;
}

getline

string s1,s2;
cin >> s1;
cout << s1 << endl;//hello world
//hello
string s1,s2;
cin >> s1;getline(cin,s1);
cout << s1 << endl;
//hello world
//hello world

题目

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

给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1

示例 1:

输入: s = "leetcode"
输出: 0

示例 2:

输入: s = "loveleetcode"
输出: 2

示例 3:

输入: s = "aabb"
输出: -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;}
};

415. 字符串相加

给定两个字符串形式的非负整数 num1num2 ,计算它们的和并同样以字符串形式返回。

你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。

示例 1:

输入:num1 = "11", num2 = "123"
输出:"134"

示例 2:

输入:num1 = "456", num2 = "77"
输出:"533"

示例 3:

输入:num1 = "0", num2 = "0"
输出:"0"

提示:

  • 1 <= num1.length, num2.length <= 104
  • num1num2 都只包含数字 0-9
  • num1num2 都不包含任何前导零
class Solution {
public:string addStrings(string num1, string num2) {string str;//提前开辟空间,降低异地扩容损耗,此处有可能进位所以多开辟一个str.reserve(max(num1.size(),num2.size()) + 1);int end1 = num1.size()-1,end2 = num2.size()-1;//进位int next = 0;while(end1 >= 0 || end2 >= 0){int val1 = end1 >= 0 ? num1[end1--]-'0' : 0;int val2 = end2 >= 0 ? num2[end2--]-'0' : 0;int ret = val1 + val2 + next;//大于10进位next = ret / 10;ret = ret % 10;//尾插,最后反转str += ('0'+ret);}if(next == 1)str += ('1');reverse(str.begin(),str.end());return str;}
};

热搜词