目录
1.上节内容补充
1.string是可以进行比较的
#include<iostream>
using namespace std;
int main()
{
string s1("hello world");
string s2("iostream");
//两个string比较
cout << (s1 > s2) << endl;//第一个字符h<i所以 输出0
//string和字符串比较(很少这样用,一般都是使用两个对象(两个string))
cout << (s1 < "iii") << endl;
cout << ("ccc" < s1) << endl;
return 0;
}
2.字符串转整形,长整型等类型
stoi
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1("1234567");
int val = stoi(s1);
cout << val << endl;
//int base=10代表转成10进制的形式
size_t sz = 0;//sz会返回一共成功转换了几个字符
int val1 = stoi("223",&sz);
cout << val1 << endl;
cout << sz << endl;
return 0;
}
3.整形,浮点型等转字符串
to_string
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str=to_string(3.14);//默认保留6位小数
cout << str << endl;
return 0;
}
4.练习题
1.回文字符串
力扣https://leetcode-cn.com/problems/valid-palindrome/
class Solution {
public:
bool IsLetterOrNumber(char s)
{
if ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z'))
return true;
if (s >= '0' && s <= '9')
return true;
return false;
}
char my_tolower(char str)
{
if (str >= 'A' && str <= 'Z')
{
str += 32;
}
return str;
}
bool isPalindrome(string s) {
int begin = 0;
int end = s.size() - 1;
while (begin<end)
{
while (begin<end && !IsLetterOrNumber(s[begin]))
{
begin++;
}
while (begin<end && !IsLetterOrNumber(s[end]))
{
end--;
}
if (my_tolower(s[begin])!=my_tolower(s[end]))
//等价于if(tolower(s[begin])!=tolower(s[end])),tolower 是C语言库函数
//还有一个toupper 正好两个为一对
return false;
begin++;
end--;
}
return true;
}
};
也可以 在bool isPalindrome(string s) 函数一开始,把stirng类的字符串转成统一的大写或小写。
// 先小写字母转换成大写,再进行判断
for(auto& ch : s)
{
if(ch >= 'a' && ch <= 'z')
ch -= 32;
}
2.字符串相加
力扣https://leetcode-cn.com/problems/add-strings/submissions/
class Solution {
public:
string addStrings(string num1, string num2) {
int end1=num1.size()-1;
int end2=num2.size()-1;
int next=0;//进位
string temp;
while(end1>=0 || end2>=0)
{
int x1=0,x2=0;
if(end1>=0)
{
x1=num1[end1]-'0';
end1--;
}
if(end2>=0)
{
x2=num2[end2]-'0';
end2--;
}
int ret=x1+x2+next;
if(ret>9)
{
next=1;
ret-=10;
}
else
{
next=0;
}
temp+=(ret+'0');//尾插
}
if(next==1)
{
temp+='1';
}
reverse(temp.begin(),temp.end());//逆置
return temp;
}
};
2.string的模拟实现
2.1传统的写法
1.string的基本框架:
namespace str //命名空间,为了防止和string库的命名冲突
{
class string
{
public:
//成员函数
private:
char* _str;
size_t _size;
size_t _capacity;
};
}
2.成员函数
2.1构造函数
string库里的构造函数,我不传参数进行初始化,也就是调用默认构造函数:
#include<iostream>
using namespace std;
int main()
{
string s1;//不给参数
cout << s1 << endl;
return 0;
}
发现打印的是空字符串:
所以默认构造函数的实现:
string()
:_str(new char[1])
, _size(0)
,_capacity(0)
{
_str[0] = '\0';
}
需要注意的是:
这里不能写_str(nullptr) 有个函数c_str是返回字符串的起始想打印字符串,会发现会报错。这里必须是new char[ ]为了与析构函数相对应 。
改进构造函数:
//构造函数
string(const char* s = "") //空字符串 有'\0'
:_size(strlen(s))//有效字符的个数
, _capacity(_size) //能够存储有效字符的空间大小。不包括'\0'
{
_str = new char[_capacity+1];//开空间的时候,要给'\0'开辟一个空间
strcpy(_str,s);
}
2.2析构函数
//析构函数
~string()
{
delete[] _str;
_str =nullptr;
}
2.3拷贝构造函数
//拷贝构造,必须深拷贝
string(const string& s)
:_size(s._size)
, _capacity (s._capacity)
{
_str = new char[_capacity + 1];
strcpy(_str,s._str);
}
2.4赋值重载
需要注意赋值重载是需要深拷贝的。
//赋值重载
string& operator=(const string&s)
{
if (this != &s) //注意:自己给自己赋值时
{
//先申请,不要一上来就销毁,要是申请失败了,原数据也给销毁了。
char*temp = new char[strlen(s._str) + 1];
strcpy(temp, s._str);
delete[] _str; //释放构造时的空间
_str = temp;
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
2.5[ ]重载
需要注意:[ ]是断言
char& operator[](size_t pos)
{
assert(pos<_size);//[]是断言,at是抛异常
return _str[pos];
}
const char& operator[](size_t pos)const
{
assert(pos<_size);//断言
return _str[pos];
}
2.6 size() 和 c_str()
const char* c_str()const
{
return _str;
}
size_t size()const
{
return _size;
}
2.7迭代器
typedef char* iterator;//迭代器
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
typedef const char* const_iterator;//const 迭代器
const_iterator begin()const
{
return _str;
}
const_iterator end()const
{
return _str + _size;
}
2.8 String.h 整体的代码
#include<iostream>
#include<cassert>
using namespace std;
namespace str
{
class string
{
public:
//构造函数
string(const char * s="")
:_size(strlen(s))
,_capacity(_size)
{
_str = new char[_capacity+1];
strcpy(_str,s);
}
//拷贝构造函数
//s2(s1)
string(const string&s)
:_size(s._size)
, _capacity(s._capacity)
{
_str = new char[_capacity + 1];//开辟时是需要开辟capacity+1 为'\0'开辟空间
strcpy(_str,s._str);
}
//析构函数
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
//c_str函数
const char* c_str()const
{
return _str;
}
//size()函数
size_t size()const
{
return _size;
}
//赋值运算符重载
string& operator=(const string& s)
{
if (this != &s)
{
char*tmp = new char[strlen(s._str)+1];
strcpy(tmp,s._str);
delete[]_str;
_size = s._size;
_capacity = s._capacity;
_str = tmp;
}
return *this;
}
//[ ]重载
char& operator[](size_t pos)
{
assert(pos<_size);//断言
return _str[pos];
}
//迭代器
typedef char* iterator;
typedef const char* const_iterator;
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
const_iterator begin()const
{
return _str;
}
const_iterator end()const
{
return _str + _size;
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
void test1()
{
//构造函数测试
string s;
cout << s.c_str() << endl;
string s1("hello world");
cout << s1.c_str() << endl;
//拷贝构造测试
string s2(s1);
cout << s2.c_str() << endl;
//赋值重载测试
string s3;
s3 = s2;
cout << s3.c_str() << endl;
//[ ]重载测试
for (size_t i = 0; i < s3.size(); i++)
{
s3[i] += 1;//修改
}
cout << s3.c_str()<<endl;
//迭代器测试
string::iterator it = s3.begin();
while (it != s3.end())
{
*it -= 1;
cout << *it;
it++;
}
cout << endl;
//const 迭代器只读
string::const_iterator it1 = s3.begin();
while (it1!=s3.end())
{
cout << *it1;
it1++;
}
cout << endl;
//范围for底层是调用迭代器的
for (auto e : s3)
{
cout << e;
}
cout << endl;
}
}
代码测试:
#include "String.h"
int main()
{
str::test1();
return 0;
}
小插曲:
其实范围for的底层是调用迭代器,编译器会直接把范围for变成迭代器:
我把迭代器begin函数改成大写的。再使用范围发现标红报错,所以范围for的底层调用的是迭代器。
2.2现代写法模拟实现
swap函数:下面会用到先铺垫一下
C++中提供了一个string成员swap:
实现的方式是去调用std里的全局swap。
void swap(string&s)
{
//swap最好应用于内置类型的交换
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
为什么会有2个swap,这两个直接的区别是什么?
int main()
{
string s1("hello world");
string s2;
s1.swap(s2);//string
swap(s1, s2);//全局
return 0;
}
首先string中底层是去调用的全局swap,但是交换时仅仅是交换了成员变量,而全局的swap在进行两个对象的交换时会发生一次深度拷贝构造,和2次的深度赋值重载的调用,其代价是非常大的,会影响执行效率,所以推荐全局的swap用来交换内置类型。
现代写法讲解:
其实现代写法是复用的一个过程:
1.构造函数还是不变的,因为下面需要复用,所以列出来方便看
//构造函数
string(const char * s="")
:_size(strlen(s))
,_capacity(_size)
{
_str = new char[_capacity+1];
strcpy(_str,s);
}
2.拷贝构造函数的现代写法
string(const string& s)
:_str(nullptr)//这里需要置空,析构函数delete对nullptr做了处理的,也可以自己加上判断
//如果不置空会析构随机地址,会报错
, _size(0) //最好都初始化一下,避免不必要的麻烦
, _capacity(0)
{
string tmp(s._str);//调用构造函数
swap(tmp);
}
拷贝构造讲解:
string s1("hello world");
string s2(s1);
使用s1拷贝构造s2, s2.string(s1) ,先把s2的_str 置为空,_size和_capacity置为0。使用s1的中的_str 也就是字符串,来构造一个新的对象tmp,此时的tmp已经和s1的内容一样,利用swap函数,分别交换s2和tmp 中的_str,_size,_capacity。对于_str 交换的是地址。执行完swap该函数马上就结束了,此时的临时对象tmp会去调用析构函数,清理资源正好把s2原始空间或数据清理完成。
3.析构函数
析构函数也是可以不变的,析构函数本身对nullptr做了处理的,也可以自己处理。比如:
//析构函数
~string()
{
//这个if语句可以不加,delete内部已经这么处理过了,或者更全面
if (_str != nullptr)
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
}
4.赋值重载
赋值重载直接复用的拷贝构造。思路和拷贝构造差不多。
//赋值运算符重载现代写法
string& operator=(const string &s)
{
if (this != &s)
{
string tmp(s);//调用拷贝构造函数
swap(tmp);
}
return *this;
}
改进:
string& operator=(string s)
{
swap(s);
return *this;
}
讲解:
string s1("hello world");
string s2;
s2=s1;
s2=s1 实际上:s2.operator(s1) ,先是拷贝构造了一个s对象,然后利用swap函数进行s2和s指针和值的交换,s对象是一个局部对象,在赋值重载函数结束时会去调用析构函数,正好swap已经完成了,此时s的内容都是s1之前的内容,整好帮助s清理之前的空间。这个赋值重载也不用检查自己给自己赋值,因为指向的空间都不一样。
2.3 string 数据插入等实现
1.reserve扩容函数:
需要注意开辟空间时是需要多开辟一个,为了存储'\0'。_capacity是能够存储有效字符的容量
void reserve(size_t n)
{
//加这个判断是为了和string中的reserve对应
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp,_str);
delete[]_str;
_str = tmp;
_capacity = n;
}
}
2.push_back函数实现
void push_back(char ch)
{
if (_size == _capacity)
{
reserve(_capacity==0? 4 : _capacity*2);
//为了防止上来_capacity是0 string s2; s2.push_back('c');这样会报错
}
_str[_size] = ch;
_size++;
_str[_size] = '\0';
}
3.append函数实现
void append(const char* str)
{
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
strcpy(_str+_size, str);
_size += len;
}
4.+=重载
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
string& operator+=(const char* str)
{
append(str);
return *this;
}
5.resize函数
了解一下resize的脾气:
int main()
{
string s1("hello world");
s1.resize(2);//当申请的空间小于_size
cout << s1.c_str() << endl;
string s2("hello world");
s2.resize(20);//申请空间大于_size,没有初始化
cout << s2.c_str() << endl;
string s3("hello world");
s3.resize(20,'c');申请空间大于_size,并初始化
cout << s3.c_str() << endl;
return 0;
}
resize分为3中情况:
1.申请的空间小于_size 只保留了申请空间的有效字符
2.申请的空间大于_size 没有初始化,会在后面多出来的空间填'\0',_size也变化了。 在这里的'\0'也是有效数据。但是打印不出来而已。
s2原始的数据:
resize后:
3. 申请的空间大于_size 并且初始化了。
resize的模拟实现:
主要注意3种情况:
void resize(size_t n, char ch = '\0')
{
if (n <= _size)
{
_size = n;
_str[_size] = '\0';
}
else
{
if (n>_capacity)//当大于_capacity时进行扩容
{
reserve(n);
}
memset(_str+_size,ch,n-_size);
_size = n;
_str[_size] = '\0';
}
}
6.find查找字符和字符串
1.查找字符
size_t find(char ch)
{
for (size_t i = 0; i < _size; i++)
{
if (_str[i] == ch)
{
return i;
}
}
return npos; //在类中定义了一个static const 变量 并赋值给了-1
}
在成员变量中增加了一个无符号静态变量npos:
2.查找字符串
size_t find(const char* str, size_t pos)
{
const char* tmp=strstr(_str+pos,str);
if (tmp == nullptr)
{
return npos;
}
return tmp - _str; //指针-指针
}
7.insert 函数
string& insert(size_t pos, char ch)
{
assert(pos<=_size);
if (_size == _capacity)
{
reserve(_capacity==0 ? 4: _capacity*2);
}
for (size_t i = _size+1; i > pos; i--)
{
_str[i] = _str[i-1];
}
_str[pos] = ch;
++_size;
return *this;
}
string& insert(size_t pos, const char*str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(len+_size);
}
size_t end = _size + len;
while (end>=pos+len)
{
_str[end] = _str[end-len];
end--;
}
strncpy(_str + pos, str, len);//不能使用strcpy会自己加\0
_size += len;
return *this;
}
8.erase函数
需要注意3种情况:
1.默认情况下npos,是删除pos位置向后的所有数据
2.pos位置后面的字符个数不够len,也是一样是删除pos位置向后的所有数据
3.比如我有7个数据,我删除5位置处向后的1个字符。pos+len<_size。
string& erase(size_t pos, size_t len=npos)
{
//erase只清理数据,不清理容量
assert(pos<_size);
if (len == npos || pos+len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str+pos ,_str+pos+len);
_size -= len;
}
return *this;
}
2.4运算符的重载
运算符的重载不是友元函数,也不是成员函数,而是定义在自己命名空间str中的全局函数。它们主要是通过我们自己定义的string类里的成员函数进行访问私有成员变量的。
1. <运算符重载
while结束时需要注意3种情况
//"abcd" "abcd" //false 同时结束
//"abcd" "abcde" //true s1结束,s2没结束
//"abcd" "abc" //false s1没结束 ,s2结束
bool operator<(const string& s1, const string&s2)
{
size_t i1 = 0;
size_t i2 = 0;
while (i1<s1.size() && i2<s2.size())
{
if (s1[i1] < s2[i2])
{
return true;
}
else if (s1[i1]>s1[i2])
{
return false;
}
i1++;
i2++;
}
分为3种情况
//"abcd" "abcd" //false 同时结束
//"abcd" "abcde" //true s1结束,s2没结束
//"abcd" "abc" //false s1没结束 ,s2结束
return i2 < s2.size() ? true : false;
//等价于:return strcmp(s1.c_str(),s2.c_str()) < 0;
}
2.==重载
bool operator==(const string& s1,const string& s2)
{
return strcmp(s1.c_str(), s2.c_str()) == 0;
}
3.其他运算符都是复用
bool operator<=(const string& s1, const string& s2)
{
return (s1 == s2 || s1 < s2);
}
bool operator>(const string& s1, const string& s2)
{
return !(s1 <= s2);
}
bool operator>=(const string& s1, const string& s2)
{
return !(s1<s2);
}
bool operator!=(const string& s1, const string& s2)
{
return !(s1 == s2);
}
4.流提取和流插入
//流提取和流插入
//流提取
istream& operator>>(istream& in, string& s)
{
char ch=in.get();
while (ch!=' ' && ch!= '\n')
{
s += ch;
ch = in.get();
}
return in;
}
//流插入
ostream& operator<<(ostream& out, const string& s)
{
for (auto e: s)
{
out << e;
}
/*for (size_t i = 0; i < s.size(); i++)
{
out << s[i];
}*/
//不要写成 我数据第一个就是\0 就打印不出后面的数据。
// out << s.c_str();
return out;
}
3.所有代码(留存)
String.h:
#include<iostream>
#include<cassert>
using namespace std;
namespace str
{
class string
{
public:
//构造函数
string(const char * s="")
:_size(strlen(s))
,_capacity(_size)
{
_str = new char[_capacity+1];
strcpy(_str,s);
}
//拷贝构造函数传统写法
//s2(s1)
//string(const string&s)
// :_size(s._size)
// , _capacity(s._capacity)
//{
// _str = new char[_capacity + 1];//开辟时是需要开辟capacity+1 为'\0'开辟空间
// strcpy(_str,s._str);
//}
void swap(string&s)
{
//swap最好应用于内置类型的交换
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
//拷贝构造函数现代写法
string(const string& s)
:_str(nullptr)//这里需要置空,析构函数对nullptr做了处理的,也可以自己加上判断
//如果不置空会析构随机地址,会报错
, _size(0) //最好都初始化一下,避免不必要的麻烦
, _capacity(0)
{
string tmp(s._str);//调用构造函数
swap(tmp);
}
//析构函数
~string()
{
if (_str != nullptr)
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
}
//c_str函数
const char* c_str()const
{
return _str;
}
//size()函数
size_t size()const
{
return _size;
}
//赋值运算符重载
/* string& operator=(const string& s)
{
if (this != &s)
{
char*tmp = new char[strlen(s._str)+1];
strcpy(tmp,s._str);
delete[]_str;
_size = s._size;
_capacity = s._capacity;
_str = tmp;
}
return *this;
}*/
//赋值运算符重载现代写法
string& operator=(const string &s)
{
if (this != &s)
{
string tmp(s);//调用拷贝构造函数
swap(tmp);
}
return *this;
}
/*string& operator=(string s)
{
swap(s);
return *this;
}*/
//[ ]重载
char& operator[](size_t pos)
{
assert(pos<_size);//断言
return _str[pos];
}
const char& operator[](size_t pos)const
{
assert(pos<_size);//断言
return _str[pos];
}
//迭代器
typedef char* iterator;
typedef const char* const_iterator;
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
const_iterator begin()const
{
return _str;
}
const_iterator end()const
{
return _str + _size;
}
void reserve(size_t n)
{
//加这个判断是为了和string中的reserve对应
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp,_str);
delete[]_str;
_str = tmp;
_capacity = n;
}
}
void push_back(char ch)
{
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
//为了防止上来_capacity是0 string s2; s2+='c';这样会报错
}
_str[_size] = ch;
_size++;
_str[_size] = '\0';
}
void append(const char* str)
{
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
strcpy(_str+_size, str);
_size += len;
}
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
string& operator+=(const char* str)
{
append(str);
return *this;
}
void resize(size_t n, char ch = '\0')
{
if (n <= _size)
{
_size = n;
_str[_size] = '\0';
}
else
{
if (n>_capacity)//当大于_capacity时进行扩容
{
reserve(n);
}
memset(_str+_size,ch,n-_size);
_size = n;
_str[_size] = '\0';
}
}
size_t find(char ch)
{
for (size_t i = 0; i < _size; i++)
{
if (_str[i] == ch)
{
return i;
}
}
return npos;
}
size_t find(const char* str, size_t pos)
{
const char* tmp=strstr(_str+pos,str);
if (tmp == nullptr)
{
return npos;
}
return tmp - _str;
}
string& insert(size_t pos, char ch)
{
assert(pos<=_size);
if (_size == _capacity)
{
reserve(_capacity==0 ? 4: _capacity*2);
}
for (size_t i = _size+1; i > pos; i--)
{
_str[i] = _str[i-1];
}
_str[pos] = ch;
++_size;
return *this;
}
string& insert(size_t pos, const char*str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(len+_size);
}
size_t end = _size + len;
while (end>=pos+len)
{
_str[end] = _str[end-len];
end--;
}
strncpy(_str + pos, str, len);//不能使用strcpy会自己加\0
_size += len;
return *this;
}
string& erase(size_t pos, size_t len=npos)
{
//erase只清理数据,不清理容量
assert(pos<_size);
if (len == npos || pos+len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str+pos ,_str+pos+len);
_size -= len;
}
return *this;
}
private:
char* _str;
size_t _size;
size_t _capacity;
static const size_t npos;
};
const size_t string::npos = -1;
//运算符重载
//两个对象比较大小
bool operator<(const string& s1, const string&s2)
{
size_t i1 = 0;
size_t i2 = 0;
while (i1<s1.size() && i2<s2.size())
{
if (s1[i1] < s2[i2])
{
return true;
}
else if (s1[i1]>s1[i2])
{
return false;
}
i1++;
i2++;
}
分为3种情况
//"abcd" "abcd" //false 同时结束
//"abcd" "abcde" //true s1结束,s2没结束
//"abcd" "abc" //false s1没结束 ,s2结束
return i2 < s2.size() ? true : false;
//等价于:return strcmp(s1.c_str(),s2.c_str()) < 0;
}
bool operator==(const string& s1,const string& s2)
{
return strcmp(s1.c_str(), s2.c_str()) == 0;
}
bool operator<=(const string& s1, const string& s2)
{
return (s1 == s2 || s1 < s2);
}
bool operator>(const string& s1, const string& s2)
{
return !(s1 <= s2);
}
bool operator>=(const string& s1, const string& s2)
{
return !(s1<s2);
}
bool operator!=(const string& s1, const string& s2)
{
return !(s1 == s2);
}
//流提取和流插入
//流提取
istream& operator>>(istream& in, string& s)
{
char ch=in.get();
while (ch!=' ' && ch!= '\n')
{
s += ch;
ch = in.get();
}
return in;
}
//流插入
ostream& operator<<(ostream& out, const string& s)
{
for (auto e: s)
{
out << e;
}
/*for (size_t i = 0; i < s.size(); i++)
{
out << s[i];
}*/
//不要写成 我数据第一个就是\0 就打印不出后面的数据。
// out << s.c_str();
return out;
}
void test1()
{
//构造函数测试
string s;
cout << s.c_str() << endl;
string s1("hello world");
cout << s1.c_str() << endl;
//拷贝构造测试
string s2(s1);
cout << s2.c_str() << endl;
//赋值重载测试
string s3;
s3 = s2;
cout << s3.c_str() << endl;
//[ ]重载测试
for (size_t i = 0; i < s3.size(); i++)
{
s3[i] += 1;//修改
}
cout << s3.c_str()<<endl;
//迭代器测试
string::iterator it = s3.begin();
while (it != s3.end())
{
*it -= 1;
cout << *it;
it++;
}
cout << endl;
//const 迭代器只读
string::const_iterator it1 = s3.begin();
while (it1!=s3.end())
{
cout << *it1;
it1++;
}
cout << endl;
//范围for底层是调用迭代器的
for (auto e : s3)
{
cout << e;
}
cout << endl;
}
void test2()
{
string s1("hello world");
string s2(s1);
cout << s2.c_str() << endl;
string s3;
s2 = s2;
cout << s3.c_str() << endl;
}
void test3()
{
/*string s1("hello world");
s1.push_back('c');
cout << s1.c_str() << endl;
s1.append("abcdefg");
cout << s1.c_str() << endl;
string s2;
s2 += "hello world";
s2.insert(11, 'a');
cout << s2.c_str() << endl;*/
string s3("aaaa");
s3.insert(4,"hello world");
cout << s3.c_str() << endl;
s3.erase(5,2);
cout << s3.c_str() << endl;
}
void test4()
{
string s2("hello");
s2.insert(0, "ab");
cout << s2.c_str() << endl;
}
void test5()
{
string s2;
string s1;
cin>>s2>>s1;
cout << s2 << endl;
cout << s1 << endl;
}
}
main.c:
#include "String.h"
int main()
{
str::test5();
return 0;
}