问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C++中string类的构造函数和遍历方法详解

创作时间:
作者:
@小白创作中心

C++中string类的构造函数和遍历方法详解

引用
CSDN
1.
https://blog.csdn.net/qq_63074244/article/details/142416059

常用的string构造相关类的接口

string类是一个管理字符串的字符数组,string类的出现方便管理我们日常所遇见的,字符名,字符串等等。下面们介绍一下常见的string类接口。

string();

默认构造,构造空的string类

int main()  
{  
    string s1;  
    cout << s1 << endl;  
    return 0;  
}  

string (const string& str);

拷贝构造,构造一个和已存在的string对象一模一样的对象。

int main()  
{  
    string s1("abcd");  
    cout << s1 << endl;  
    return 0;  
}  

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

从字符串的pos位置拷贝n个字符到字符串str上,pos是所拷贝的位置,len是所拷贝的长度。这里涉及到一个特殊的玩法,拷贝的长度如果大于字符串剩余的,这种情况并不会报错,会拷贝所以剩下的所有。还有一种情况,传入时若长度并未传入,也是会直接拷贝到字符串'\0'的位置。

int main()  
{  
    string s1("abcd",1,5);  
    cout << s1 << endl;  
    return 0;  
}  

string (const char* s);

用字符串来构造类对象

int main()  
{  
    char s1[] = "abcdfg";  
    string s2(s1);  
    cout << s2 << endl;  
    return 0;  
}  

string (const char* s, size_t n);

用s所指向字符串(或字符数组)的前n个来初始化创建一个string类对象。

int main()  
{  
    char s1[] = "abcdfg";  
    string s2(s1,3);  
    cout << s2 << endl;  
    return 0;  
}  

string (size_t n, char c);

n个字符进行初始化

int main()  
{  
    string s1(5,'a');  
    cout << s1 << endl;  
    return 0;  
}  

常用的string遍历相关类的接口

1.[]+下标

[ ]+下标本质是调用函数string::operator[],operator[]的返回值是一个引用,所以可以通过[]加下标的方式去访问和修改string类对象。string::operator[]即可以针对普通对象也可针对const对象。 [ ]+下标的方法适用于底层是连续的字符串这种情况。

补充[ ]与at的区别:在越界时[]会触发底层的断言,而at要通过捕获后显示。

int main()  
{  
    //遍历方式  
    string s1("hello");  
    for (size_t i=0; i < s1.size(); i++)  
    {  
        s1[i]++;  
        cout << s1[i] << " ";  
    }  
    cout << endl;  
    return 0;  
}  

2.迭代器

迭代器可以理解一种像指针的东西,它本身并不一定是指针,是不是指针取决与底层。

int main()
{
    //迭代器的用法
    string s1("hello");
    string::iterator s = s1.begin();//起始位置
    while (s!=s1.end())//字符串最后一个字符的下一个位置
    {
        cout << *s << " ";
        cout << ++(*s) << " ";//字符串++的情况
        s++;
    }
    cout << endl;
    return 0;
}  

上述案例中是否可以把s!=s1.end()改为s<s1.end

这里我们要明白是迭代器的底层并不是指针,在数组中这中情况是可以的,因为数组是空间是连续的,但是在链表中就不可以了。下面使用list进行验证一下底层到底是不是指针,这里我们通过对比可以看出,底层不是指针,如果是指针解引用不就是节点了吗?

“语法糖”

auto

auto的用法是可以自动识别右侧的类型,简化代码,代替写起来长的类型。

int i=10;  
auto a=1;//int  
auto b=1.0;//double  
auto &c=i;//int &  
auto f=c//int  
auto &d=c;//int &  
auto e=&i;//int *  

范围for

//自动进行遍历,自动取出容器的值给左边的值
//自动++,自动判读结束
//适用于容器和数组,范围for底层是迭代器

for(auto 变量名:容器名);  

如何实现修改

遍历for是自动取出容器的值给左边的对象,拷贝的值进行自增并不会影响容器的值,所以这里采用引用。

添加引用的两种情况

  1. 拷贝的数的较大时这种情况拷贝太难处理
  2. 要进行修改

反向迭代器

reverse_iterator rbegin();

int main()
{
    string s("abcde");
    std::string::reverse_iterator rit = s.rbegin();
    //auto rit=s.rbegin();
    while (rit != s.rend())
    {
        cout << *rit << " ";
        rit++;//注意这里是++而不是--
    }
    cout << endl;
    return 0;
}  

rebegin()底层实现的图像解析,这里只是逻辑这样实现的,底层不一定是这样实现的。

const_ reverse_iterator rbegin();

const_ reverse_iterator rbegin();与reverse_iterator rbegin();功能一样,前者实现的不能进行修改。

插入用法

插入单个字符

s.push_back('x');

插入字符串

operator+=

insert插入

上述的几种对数组的插入都是尾插,insert可以对不同位置进行插入。

int main()
{
    string s1("abcde");
    string s2("efg");
    //在指定位置插入字符串
    s1.insert(1, s2);
    cout << s1 << endl;
    //在指定位置插入指定长度,指定位置一段字符串
    s1.insert(1, s2, 1, 2);
    cout << s1 << endl;
    //指定位置插入一段字符串
    s1.insert(1, "xxx");
    cout << s1 << endl;
    //指定位置插入长度为n的一段字符串
    s1.insert(1, "xxx", 1);
    cout << s1 << endl;
    //指定位置插入n个字符
    s1.insert(s1.begin(), 3, '1');
    cout << s1 << endl;
    return 0;
}  

实战演练

1.用C++实现仅仅反转字母
字符串相加

代码优化:
通过insert进行的插入是头插入,头插对于字符的处理时后面的字符要向后移动,因此头插入的时间复杂度在本题是0(
),但是通过尾插是0(n),虽然尾插不是我们预期的,但是可以调用reverse模板进行反转。

总结

以上就是本期的主要内容主要介绍了string常用的基础用法,以及迭代的实现介绍。由于string具有较多的接口,这里不进行一一介绍,可以通过此处传送门进入Cplusplus官网进行查阅。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号