c++ string类详解

1,string定义:

Strings are objects that represent sequences of characters(string是表示字符序列的对象)string是一个类。string属于标准库,头文件<string>.

(注:string的有些方法比较冗杂,我这里会陈列所有方法,但只阐述常用的!!!)

2,npos:

string有一个静态成员变量:npos

3,string的构造函数:

string s1;
string s2("hello world");

string s3(s2, 6, 5);//从下标为6开始,取五个字符

string s4(s2, 6);//从下标为6开始,缺省值为size_t npos=-1;最大的整型,越界,到字符串完为止

string s5 (10, 'a');
cout << s5 << endl;//aaaaaaaaaa

string s6(s5.begin(), s5.end());
cout << s6 << endl;//aaaaaaaaaa

4,operator=

string s8 = s7;
s8 = "xxx";
s8 = 'x';

5,非成员函数

(1)operator<<

此函数非成员函数,原因:这个运算符是用来直接打印字符串的,(cout<<s1)运算符左右两边分别是ostream类型和string类型,所以这两个参量将作为这个运算符重载的第一第二参数,如果这个作为成员函数,那么第一个参数默认是*this(也就是string),那么与我们想要达到的参数顺组颠倒,所以它不能作为成员函数。

用法:cout << s1 << endl;

(2)operator>>

此函数非成员函数。

用法:string s1("wwwwww");
cin >> s1;
cout << s1 << endl;

(1)留提取后,原先的的内容会被覆盖。

(2)提取的时候以空格和换行符截止,如果想要得到一整行的内容,应该使用getline();

(3)getline (string)

此函数非成员函数。

(1)这个方法,字符串原先的的内容会被覆盖。

(2)第一个是遇到字符(delim)这个参数,才停止。第二个是遇到‘\0’截止

用法:

(1)string s1;
getline(cin, s1,'#');

(2)string s1;
getline(cin, s1);

(4)swap (string)

非成员函数:

成员函数:

两者原理大致相同,

用法:string s1("xxx");
string s2("yyy");
swap(s1, s2);

(5)operator+ (string)

非成员函数:

用法:

string s1("hello");
string s2("world");
cout << s1 + s2 << endl;
cout << s1 + '#' << endl;

(6)relational operators (string)

非成员函数:

这里有各种各样的字符串的比较方法,这里是根据首元素字母的ascll码值进行比较的

用法:

string s1("hello");
string s2("world");
cout << (s1 < s2) << endl;//1
cout << (s1 == s2) << endl;//0

6,Element access

(1)operator[]

(1)[ ]可以直接通过下标访问字符数组中的值。

(2)这里提供了两种,一种是既可以读又可以改变内容的,第二种是只可以读取,不可以更改的

const string s1("hello world");
for (size_t i = 0;i < s1.size();i++) {
    //读
    cout << s1[i] << " ";
}(这里调用的第二个用函数)

以上情况就是因为,这是一个用const就是的引用,不可以修改,但是这里修改了,所以报错。

string s1("hello world");
for (size_t i = 0;i < s1.size();i++) {
    cout << s1[i]++ << " ";
}(这里调用的第一个用函数)所以这里的值可以修改

(2)at()

at和[]相似,但失败后会抛异常

(3)back()

返回字符串最后一个字符的引用

(4)front()

返回字符串第一个字符的引用

7,迭代器相关的函数

(1)begin()

返回一个指向字符串第一个字符的迭代器。

(2)end()

返回一个指向字符串末尾后的字符的迭代器。

(3)rbegin()

返回指向字符串最后一个字符的反向迭代器

(4)rend()

返回一个反向迭代器,该迭代器指向字符串第一个字符前面的理论元素。

(5)cbegin()

返回一个指向字符串第一个字符的const_iterator迭代器,该迭代器是指向const内容的迭代器,这个迭代器本身可以改变指向的对象(除非它本身也是const修饰的),但是指向的的内容,即用const修饰的字符串,不能随意修改。

(6)cend()

返回一个指向字符串末尾后的字符的const_iterator迭代器。

(7)crbegin()

返回一个const_reverse_iterator,指向字符串的最后一个字符

(8)crend()

返回一个const_reverse_iterator,该迭代器指向字符串第一个字符前面的理论元素

(9)用法:

(1)string::iterator it = s1.begin();
while (it != s1.end()) {
    cout << *it << " ";
    ++it;
}
cout << endl;//用来读

(2) it = s1.begin();
while (it != s1.end()) {
    //写
    *it = 'a';
    ++it;
}
cout <<s1<< endl;//用来写

(3)auto rit= s1.rbegin();
while (rit!=s1.rend())
{
    cout << *rit << " ";
    rit++;
}
cout << endl;//倒着遍历

(4)void func(const string& s) {
    //引用传参
    string::const_iterator it = s.begin();
    while (it != s.end()) {
        //读
        cout << *it << " ";
        ++it;
    }
    cout << endl;

迭代器的优势:定义在类域,运用方式相似,屏蔽了底层细节

第三种遍历方式:

上述已经提供了两种遍历的方法了,第一种是【】遍历,第二种是迭代器。一下讲第三种范围for,它的底层也是迭代器。

for (auto ch : s1) {
    //读
    cout << ch << " ";
}
cout << endl;

for (auto& ch : s1) {
    //写
    cout << ch << " ";
}
cout << endl;

8,Capacity:

(1)size()和length()

string s1 = "hello world";
cout << s1.size() << endl;//从容器来看,具有通用性
cout << s1.length() << endl;


(2)clear()

s1.clear();//清除数据,但是没有释放空间

(3)max_size()

返回字符串可以达到的最大长度。这是字符串可以达到的最大潜在长度,但不能保证对象能够达到该长度,它无法分配内存在达到该长度之前。

(4)resize()

将字符串大小调整为n个字符的长度。如果n小于当前字符串长度,则将当前值缩短到前n个字符,删除第n个字符以外的字符。如果大于当前字符串长度,将字符串大小调整为n个字符的长度,并用'\0',或者字符char c补齐补齐。

用法:

string s1 = "hello world";
s1.resize(20,'$');
cout <<s1 << endl;

(5)capacity()

返回分配内存的大小。

string s;
size_t old = s.capacity();
cout << "初始" << s.capacity() << 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中:

(6)reserve()

该方法和resize相似,但是也有区别。reserve只是预留空间,不创建元素对象。resize既分配了空间,也创建了对象,可以通过下标访问。reserve会修改capacity大小,但不修改size大小;resize既修改capacity大小,也修改size大小。

价值:确定大概要多少空间,提前开好,减少扩容,提高效率

9,Modifiers:

(1)operator+=

用法:

string s;
string s1("world");

s += '#';
s += "hello";
s += s1;
cout << s << endl;

(2)push_back()

尾插法

用法:string s;
s.push_back('#');

(3)append()

在当前字符串的基础上进行拼接,

string s;
s.append("hello");
s.append("world",0,3);
string s2("ld");
s.append(s2);
string s3("xxxxxx");
s.append(s3,1);
s.append(4,'#');
cout << s << endl;

(4)assign()

为字符串赋一个新值,替换其当前内容

用法:

string ss;
string ss1("hello world");
ss.assign(ss1);
cout << ss << endl;//hello world

string ss2("xxxxx");
ss2.assign(ss1);
cout << ss2 << endl;//hello world,覆盖

string ss3("xxxxx");
ss3.assign(ss1,5,10);
cout << ss3 << endl;// world

(5)insert()

string s("hello world");
s.insert(0, 1, 'x');
s.insert(s.begin(), 'x');
s.insert(0, "aaa", 1, 2);在下标为0的位置插入,字符串“aaa”中的一部分,这一部分从下标1开始,长度为两个字符。
cout << s << endl;

(6)erase()

    s.erase(7, 2);//从小标7,开始删,删2个字符
    s.erase(7);//从小标7,开始删,删完

(8)replace()

s.replace(5, 1, "%%%%%%");//将下标为5的一个字符改为这个字符串

注:insert / erase / replace 尽量不要用,都涉及移动数据,效率不高

10,String operations

(1)c_str()

返回指向数组的指针

(2)find()

用法:

string s1("test.c.ter.zip");
size_t i = s1.find('.',5);//4
size_t i = s1.find('.');//6
string s2("est");
string& s3 = s2;
int i=s1.find(s3);//1
cout << i << endl;

(3)substr()

string s1("test.c.ter.zip");
size_t i = s1.find('.');
string s2 = s1.substr(i);
cout << s2 << endl;//.c.ter.zip

(4)rfind()

从后往前找

string s1("test.c.ter.zip");

size_t j = s1.rfind('.');
 s2 = s1.substr(j);//.zip

练习一:

分离协议,域名,资源名:

string s3("https://cplusplus.com/reference/string/string/swap-free/");
//协议
//域名
//资源名
size_t i1 = s3.find(':');
string sub1, sub2, sub3;
if (i1 != string::npos) {
     sub1 = s3.substr(0, i1);
}
else {
    cout << "没有找到i1的位置" << endl;
}

 size_t i2 = s3.find('/',i1+3);
    if (i1 != string::npos) {
sub2 = s3.substr(i1+3,i2-(i1+3));
    }
    else {
        cout << "没有找到i2的位置" << endl;
    }
    sub3 = s3.substr(i2 + 1);
    cout << sub1 << endl;
    cout << sub2 << endl;
    cout << sub3 << endl;


练习二:

大数相加:

string addstrings(string num1, string num2) {
    int end1 = num1.size() - 1,
        end2 = num2.size() - 1;
    int next = 0;
    string str;
    while (end1 >= 0 || end2 >= 0)
    {
        int x1 = end1 >= 0 ? num1[end1] - '0' : 0;
        int x2 = end2 >= 0 ? num2[end2] - '0' : 0;
        int ret = x1 + x2 + next;
        next = ret / 10;
        ret = ret % 10;
        str += ('0' + ret);
        --end1;
        --end2;
    }if (next == 1) {
        str +=' 1';
    }
    reverse(str.begin(), str.end());
    return str;
}

  • 28
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值