string介绍:
- string是表示字符串的字符串类
- 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
- string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
- 不能操作多字节或者变长字符的序列
代码:
代码实现:
namespace ZYY
{
class string
{
public:
typedef char* iterator;
typedef const char* const_iterator;
string(const char* x = ""):_str(new char[strlen(x)+1])
{
strcpy(_str,x);
_size = strlen(_str);
_capacity = _size;
}
string(const string& s):_str(new char[strlen(s._str)+1])
{
strcpy(_str,s._str);
_size = strlen(_str);
_capacity = _size;
}
string& operator=(const string& s)
{
if(&s != this)
{
delete []_str;
_str = new char[strlen(s._str)+1];
strcpy(_str,s._str);
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
void insert(size_t pos, char ch)
{
assert(pos <= _size);
if(_size == _capacity)
{
if(_capacity == 0)
{
reserve(8);
}
else
{
reserve(_capacity * 2);
}
}
size_t end = _size + 1;
while (end >= pos + 1)
{
_str[end] = _str[end - 1];
--end;
}
_str[pos] = ch;
_size++;
}
void insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if(len + _size >= _capacity)
{
reserve(len+_size);
}
size_t end = _size + len;
while (pos + len <= end)
{
_str[end] = _str[end - len];
--end;
}
while (*str)
{
_str[pos] = *str;
++pos;
++str;
}
_size += len;
}
size_t find(const char ch)
{
for(size_t i = 0 ; i < _size ;i++)
{
if(_str[i] == ch)
{
return i;
}
}
return string::_npos;
}
size_t find(const char* str)
{
const char* pos = strstr(_str,str);
if(pos == nullptr)
{
return string::_npos;
}
else
{
return pos-_str;
}
}
void reserve(size_t n)
{
if(n > _capacity)
{
char* tmp = new char[n+1];
strcpy(tmp,_str);
delete []_str;
_str = tmp;
_capacity = n;
}
}
void push_back(const char ch)
{
if (_size == _capacity)
{
if (_capacity == 0)
{
reserve(8);
}
else
{
reserve(_capacity * 2);
}
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
void clear()
{
_size = 0;
_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;
}
void append(size_t n, char c)
{
for (size_t i = 0; i < n; ++i)
push_back(c);
}
const string& operator+=(char ch)
{
push_back(ch);
return *this;
}
const string& operator+=(const char* str)
{
append(str);
return *this;
}
const string& operator+=(const string& s)
{
append(s._str);
return *this;
}
bool operator>(const string& s)const
{
char* str1 = _str;
char* str2 = s._str;
while (*str1 && *str2)
{
if (*str1 > *str2)
{
return true;
}
else if (*str1 < *str2)
{
return false;
}
else
{
++str1;
++str2;
}
}
if (str1)
{
return true;
}
else return false;
}
bool operator==(const string& s)const
{
const char* str1 = _str;
const char* str2 = s._str;
while (*str1 && *str2)
{
if (*str1 == *str2)
{
++str1;
++str2;
}
else
{
return false;
}
}
if (str1 == nullptr && str2 == nullptr)
{
return true;
}
else
{
return false;
}
}
bool operator>=(const string& s)const
{
return operator>(s) || operator==(s);
}
friend ostream& operator<<(ostream &_cout,const string& s);
friend istream& operator>>(istream &_cin,string& s);
const_iterator begin() const
{
return _str;
}
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
const_iterator end() const
{
return _str + _size;
}
size_t size()const
{
return _size;
}
size_t capacity()
{
return _capacity;
}
const char* c_str()
{
return _str;
}
char& operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& operator[](size_t pos) const
{
assert(pos < _size);
return _str[pos];
}
~string()
{
delete []_str;
_str = nullptr;
_size = 0;
_capacity = 0;
}
private:
char* _str;
size_t _size;
size_t _capacity;
static size_t _npos;
};
size_t string:: _npos = -1;
}
ostream& ZYY::operator<<(ostream &_cout,const ZYY::string& s)
{
cout<<s._str;
return _cout;
}
istream& ZYY::operator>>(istream &_cin,string& s)
{
char ch = _cin.get();
while(ch != ' ' && ch != '\n')
{
s += ch;
ch = _cin.get();
}
return _cin;
}
代码测试:
int main()
{
cout<<"打印s1:"<<endl;
ZYY::string s1 = "nihao";
cout<<s1<<endl;
cout<<"打印s2:"<<endl;
ZYY::string s2 = "pengyou";
cout<<s2<<endl;
cout<<"比较s1与s2的大小:"<<endl;
if(s1 > s2)
{
cout<<"s1大于s2"<<endl;
}
else
{
cout<<"s1不大于s2"<<endl;
}
cout<<"将s1的值赋给s2:"<<endl;
s2 = s1;
cout<<s2<<endl;
cout<<"将s1末尾追加一个字符:"<<endl;
s1 += 'a';
cout<<s1<<endl;
cout<<"将s1末尾追加一个字符串:"<<endl;
s1 += " hao";
cout<<s1<<endl;
cout<<"将s1末尾追加一个s2:"<<endl;
s1 += s2;
cout<<s1<<endl;
cout<<"从s1中提取字符串:"<<endl;
const char* s = s1.c_str();
cout<<s<<endl;
cout<<"给s1的4位置插入y:"<<endl;
s1.insert(4,'y');
cout<<s1<<endl;
cout<<"给s1的末尾位置插入p:"<<endl;
s1.push_back('p');
cout<<s1<<endl;
cout<<"清空s2:"<<endl;
s2.clear();
cout<<s2.size()<<endl;
cout<<s2<<endl;
cout<<"输入s3:"<<endl;
ZYY::string s3;
cin>>s3;
cout<<s3<<endl;
}
测试结果:
注意事项:
- string可以通过c_str函数转换为const char类型,char类型也可以用to_string转换为string类型
- STL中的string是深拷贝!!
- STL中的string的底层在插入的时候也会给string串预留一些空间,避免频繁扩容
- 在cin输入string的时候,默认是遇到空格与回车就结束(在笔试题中尤为重要)
- string的末尾追加通常都是用+号的运算符重载,比较方便,当然也可以用append函数
- 深浅拷贝
①浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以 当继续对资源进项操作时,就会发生发生了访问违规
②深拷贝:如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出,一般情况都是按照深拷贝方式提供 - string的缺省参数是string s = “”,不能是string s = nullptr或者string s = ‘\0’