1、 C语言中的字符串
C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问
- 字符串是表示字符序列的类
- 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性。
- .string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信 息,请参阅basic_string)。
- string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits 和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
- 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个 类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
总结: - string是表示字符串的字符串类
- 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
- string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
- 不能操作多字节或者变长字符的序列。 在使用string类时,必须包含#include头文件以及using namespace std;
#include <assert.h>
namespace bite
{
class string
{
public:
typedef char* iterator;
public:
string(const char* str = "")// const char* 使因为 调用strcpy 第二个参数为 const
{
if (nullptr == str)
str = "";
// 当前对象开辟空间
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity+1];
// 拷贝元素
strcpy(_str, str);
}
string(size_t n, char ch)
: _size(n)
, _capacity(n) //string 类底层
, _str(new char[n+1])
{
memset(_str, ch, n);//
_str[n] = '\0'; // 将最后一个字符设置为'\0'
}
// [begin, end) 区间拷贝
// 如何体现出 左闭右开?
// _size = end - begin; 此时从 begin 往后 _size 个位置,就不包括 end
// 由于是左闭右开区间,因此 _str[_size]
string(char* begin, char* end)
{
_size = end - begin; //_size为从 begin ---end 的元素个数,不包括end,
_capacity = _size;
_str = new char[_size + 1];
strncpy(_str, begin, _size);
_str[_size] = '\0'; //第size+1个元素 ,从0 -- size-1 ,完成拷贝
}
string(const string& s) // 不能修改应用的内容
: _size(s._size)
, _capacity(s._size)
{
_str = new char[_capacity+1];
strcpy(_str, s._str);
}
//运算符重载
string& operator=(const string& s)
{
if (this != &s) //检测是否有对自己赋值,避免自己给自己赋值
{
int len = strlen(s._str);
//申请新空间
char* p = new char[len+1];
//拷贝旧空间
strcpy(p, s._str);
// 释放旧空间
delete[] _str;
// 指向新空间
_str = p;
_size = len; // 重置
_capacity = len;// 重置
}
return *this;
}
~string()
{
if (_str)
{
delete[] _str;
_str = nullptr;
_capacity = 0;
_size = 0;
}
}
/
// capacity
size_t size()const // 不需要修改 _size _capacity属性 所以用 const
{
return _size;
}
size_t capacity()const
{
return _capacity;
}
bool empty()const
{
return 0 == _size;
}
void resize(size_t newsize, char ch)
{
size_t oldsize = size();
if (newsize > oldsize)
{
// 有效元素个数增多
// 多出的元素在空余空间中能否放的下
if (newsize > _capacity)
{
reserve(newsize);
}
memset(_str + _size, ch, newsize - oldsize);
}
_size = newsize;
_str[_size] = '\0';
}
void reserve(size_t newcapacity)
{
size_t oldcapacity = capacity();
if (newcapacity > oldcapacity)
{
// 申请新空间
char* temp = new char[newcapacity + 1];
// 拷贝元素
strcpy(temp, _str); //也有将'\0'赋值
// 释放旧空间
delete[] _str;
_str = temp;
_capacity = newcapacity;
}
}
/
// access
char& operator[](size_t index)
{
assert(index < _size);
return _str[index];
}
const char& operator[](size_t index)const
{
assert(index < _size);
return _str[index];
}
/
// modify
void push_back(char ch) //尾插
{
if (_size == _capacity)
reserve(_capacity*2);
_str[_size++] = ch;
_str[_size] = '\0';
}
string& operator+=(char ch) //
{
push_back(ch);
return *this;
}
string& operator+=(const char* str);
string& operator+=(const string& s);
bool operator==(const string& s);
bool operator!=(const string& s);
bool operator>(const string& s);
bool operator>=(const string& s);
bool operator<(const string& s);
bool operator<=(const string& s);
friend ostream& operator<<(ostream& _cout, const bite::string& s)
{
_cout << s.c_str();
return _cout;
}
friend istream& operator<<(istream& _cout, string& s);
/
// 特殊操作
size_t find(char ch, size_t pos = 0)
{
for (size_t i = pos; i < _size; ++i)
{
if (ch == _str[i])
return i;
}
return npos; //未找到 ch
}
// size_t npos = -1 ----- 是一个非常大的数字
size_t rfind(char ch, size_t pos = npos)
{
if (pos == npos)
pos = _size - 1;// 默认情况从最后一个位置查找
for (int i = pos; i >= 0; i--)
{
if (ch == _str[i])
return i;
}
return npos;
}
string substr(size_t pos = 0, size_t n = npos)
{
if (n == npos)
n = _size;// 默认情况为最后位置
string temp(_str + pos, _str + pos + n);
return temp;
}
const char* c_str()const
{
return _str;
}
/
// iterator
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
private:
char* _str;
size_t _size;
size_t _capacity;
static size_t npos; // npos是一个无符号整数 值为-1
};
size_t string::npos = -1;
}
void TestString1()
{
bite::string s1;
bite::string s2(“hello”);
bite::string s3(s2);
bite::string s4(10, ‘$’);
bite::string s5(s2.begin(), s2.end());
for (auto e : s2)
cout << e;
cout << endl;
for (size_t i = 0; i < s3.size(); ++i)
cout << s3[i];
cout << endl;
//bite::string::iterator it = s4.begin();
auto it = s4.begin();
while (it != s4.end())
{
cout << *it;
++it;
}
cout << endl;
}
void TestString2()
{
bite::string s(“hello”);
cout << s.size() << endl;
cout << s.capacity() << endl;
s.push_back('!');
cout << s.size() << endl;
cout << s.capacity() << endl;
s.resize(15, '$');
cout << s.size() << endl;
cout << s.capacity() << endl;
s.resize(10, '&');
cout << s.size() << endl;
cout << s.capacity() << endl;
}
void TestString3()
{
bite::string s(“hello”);
size_t pos1 = s.find('l');
cout << pos1 << endl;
size_t pos2 = s.rfind('l');
cout << pos2 << endl;
cout<<s.substr(pos1, 2)<<endl;
}
int main()
{
//TestString1();
//TestString2();
TestString3();
return 0;
}