string类及相关函数的实现
Posted 在下赵某人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了string类及相关函数的实现相关的知识,希望对你有一定的参考价值。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
#include<string>
using namespace std;
namespace zzd
{
class string
{
public:
//默认构造一、 string();
string()
:_str(new char[1])
,_size(0)
,_capacity(0)
{
_str[0] = '\\0';//就算没数据,_str也要指向一个new出来的空间并且以 '\\0' 结束
}
//默认构造二、 将构造函数 string(const char* s); 给个缺省值实现 string(const char* s = "");
//string(const char* s = "")//若未传参数,则s是一个空串,-->strlen(s) == 0
// :_str(new char[strlen(s) + 1])
// , _size(strlen(s))
// , _capacity(strlen(s))
//{
// strcpy(_str, s);
//}
//构造函数string s1("hallo");
string(const char* s)
:_str(new char[strlen(s) + 1])
,_size(strlen(s))
,_capacity(strlen(s))
{
strcpy(_str, s);
//_str[strlen(s)] = '\\n';--->用不着:strcpy把从src地址开始且含有’\\0’结束符的字符串复制到以dest开始的地址空间,返回值的类型为char*
}
//resize的函数实现
void resize(size_t n, char c = '\\0')
{
int sz = strlen(_str);
if (_capacity < n)
{
reserve(2 * n);
}
if (n < _size)
{
_size = n;
_str[_size] = '\\0';
return;
}
_size = n;
for (int i = sz; i < _size; i++)
{
_str[i] = c;
}
_str[_size] = '\\0';
}
//swap的函数实现(不能叫重载,因为不在同一个命名空间)
void swap(string& s)
{
::swap(_str, s._str);// ::是用来指定这里的swap是全局域的swap
::swap(_size, s._size);
::swap(_capacity, s._capacity);
}
//拷贝构造现代写法string s2(s1);
string(const string& s)
:_str(nullptr)
{
string tmp(s._str);//s._str 是字符串类型,这里调用了构造函数 string(const char* s);
swap(tmp);//要用第一种构造函数构造一个临时变量,用 临时变量的_str 和 this->_str 交换,
//该函数结束后tmp调析构函数会将里面的资源释放,故刚开始需将_str初始化为nullptr,防止delete一个随机值。
}
//赋值操作符传统写法
//string& operator=(string& s)
//{
// if (this != &s)
// {
// char* tmp = new char[strlen(s._str) + 1];
// delete[] _str;
// _str = tmp;
// strcpy(_str, s._str);
// _size = strlen(s._str);
// _capacity = strlen(s._str);
// }
// return *this;
//}
//赋值操作符现代写法
string& operator=(string s)//用了传值传参(实际相当于调用拷贝构造 实现了 深拷贝)
{
swap(s);//交换 s与*this 的数据
return *this;
}
//实现size()接口
int size() const //函数内部不进行修改,所以最好把const带上,这样const对象与非const对象都可以调用
{
return _size;
}
//实现capacity()接口
int capacity() const
{
return _capacity;
}
//[]操作符重载 可读可写
char& operator[](int i)
{
assert(i < _size );//下标合法性的检查(检查是否越界访问)
return _str[i];
}
//[]操作符重载 只可读
const char& operator[](int i) const
{
assert(i < _size);
return _str[i];
}
//尾插字符函数
void PushBack(char c)
{
if (_size == _capacity)
{
int new_capacity = _capacity == 0 ? 4 : 2 * _capacity;
reserve(new_capacity);
}
_str[_size] = c;
_size++;
_str[_size] = '\\0';
}
//尾插字符串函数
void append(const char* s)
{
if (_size + strlen(s) >= _capacity)
{
reserve(2 * _size + strlen(s));
}
strcpy(_str + _size, s);
_size += strlen(s);
}
//扩容函数
void reserve(int capacity)
{
if (capacity > _capacity)
{
char* tmp = new char[capacity + 1];
strcpy(tmp, _str);
delete[] _str;
_str = nullptr;
::swap(_str, tmp);
_capacity = capacity;
}
}
//+=操作符重载(插字符)
string& operator+=(const char c)
{
PushBack(c);
return *this;
}
//+=操作符重载(插字符串)
string& operator+=(const char* s)
{
append(s);
return *this;
}
// + 操作符重载(char)
string operator+(char c)
{
string tmp(*this);
tmp += c;
return tmp;
}
// + 操作符重载(char*)
string operator+(const char* s)
{
string tmp(*this);
tmp += s;
return tmp;
}
//c_str()接口的实现
char* c_str()
{
return _str;
}
//定义迭代器
typedef char* iterator;
iterator begin()
{
return _str;
}
iterator end()
{
char* tmp = _str + _size;
return tmp; //指向最后一个有效数据的后面位置
}
//定义迭代器(const 版本)
typedef const char* const_iterator;
const_iterator begin() const
{
return _str;
}
const_iterator end() const
{
char* tmp = _str + _size;
return tmp; //指向最后一个有效数据的后面位置
}
//遍历打印一、
void print()
{
cout << "法一、:"; //按_size来打印('\\0'也会打印,只不过不显示)
for (int i = 0; i < _size; i++)
{
cout << _str[i];
}
cout << endl;
cout << "法二、:"; //有缺陷,遇到 '\\0' 会停止打印,不会按_size来打印
cout << c_str() << endl;
cout << "法三、:"; //迭代器打印法
iterator it = begin();
while (it != end())
{
cout << *it << ' ';
it++;
}
cout << endl;
}
//insert(size_t pos, char c)函数实现
void insert(size_t pos, char c)
{
assert(pos <= _size);
//判断是否扩容
if (_size == _capacity)
{
int new_capacity = _capacity == 0 ? 4 : 2 * _capacity;
reserve(new_capacity);
}
//从后往前移
for (int i = _size; i > pos; i--)
{
_str[i] = _str[i - 1];
}
_size++;
//最后要插入'\\0'
_str[_size] = '\\0';
_str[pos] = 'c';
}
//insert(size_t pos, char* s)函数实现
void insert(size_t pos,const char* s)
{
//assert(pos <= _size);
//int sz = strlen(s);
//if (sz == 0)
//{
// return;
//}
判断是否扩容
//if (_size + sz > _capacity)
//{
// int new_capacity = _capacity == 0 ? 4 : 2 * (_size + sz);
// reserve(new_capacity);
//}
从后往前移
//for (int i = _size + sz - 1; i >= pos + sz; i--)
//{
// _str[i] = _str[i - sz];
//}
//char c = _str[pos + sz];
//strcpy(_str + pos , s);//strcpy会将'\\0'也拷贝过去
//_str[pos + sz] = c;
//_size += sz;
最后要插入'\\0'
//_str[_size] = '\\0';
//----------------------实现方式二----------------------//
assert(pos <= _size);
size_t len = strlen(s);
//处理空串情况
if (len == 0)
{
return;
}
//判断增容
if (_size + len > _capacity)
{
reserve((_size + len) * 2);
}
//从后往前拷贝,空出插入的位置
size_t end = _size + len;
while (end >= pos + len)
{
_str[end] = _str[end - len];
end--;
}
//将数据插入
for (int i = 0; i < len; i++)
{
_str[pos + i] = s[i];
}
}
//erase()函数的实现
void erase(int pos, size_t n = npos)
{
//判断下标合法性
assert(pos < _size);
if (n == npos || n >= _size - 1)
{
_size = pos;
_str[pos] = '\\0';
return;
}
strcpy(_str + pos, _str + n + 1);
}
//clear()函数的实现
void clear()
{
_str[0] = '\\0';
_size = 0;
}
//析构函数
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
private:
char* _str;
int _size;
int _capacity;
static size_t npos; //声明了静态成员变量但未定义
};
//定义、初始化静态成员变量
size_t string::npos = -1;//定义了静态成员变量,同时初始化(不初始化也可以通过编译)
//非成员函数的print()实现
void print(const string& str)
{
for (int i = 0; i < str.size(); i++)
{
cout << str[i]; //这里调用的是 只可读的[]操作符重载
// str[i]++; ---> 该表达式不合法因为调用的是只可读[]重载
}
cout << endl;
迭代器
//for (auto a : str)
//{
// cout << a;
//}
//cout << endl;
}
//">>"和"<<"的重载并不一定要设置成友元,
//因为调用公有函数来访问私有成员就可以不设友元
// <<操作符重载
ostream& operator<<(ostream& _cout, const string& s)
{
print(s);
return _cout;
}
// >>操作符重载
istream& operator>>(istream& _cin, string& s)
{
s.clear();
char ch;
ch = _cin.get();//cin是拿不到' '和'\\n'的,会自动忽略,会认为是输入两个值之间的间隔。要用cin这个类里的get(); (std::istream::get)
while (ch != ' ' && ch != '\\n')
{
s += ch;
ch = _cin.get();//--->可以看做get()是cin的成员函数
}
return _cin;
}
//getline()函数的实现
istream& getline(istream& _cin, string& s)
{
s.clear();
char ch;
ch = _cin.get();//输入的数据未取完的暂时存在缓存区
while (ch != '\\n')
{
s += ch;
ch = _cin.get();
}
return _cin;
}
// == 操作符重载
bool operator==(string& s1, string& s2)
{
//s1和s2的size()都不同则直接返回false
if (s1.size() != s2.size())
{
return false;
}
//s1和s2的size()相同的情况
int i = 0;
while (i < s1.size())
{
if (s1[i] != s2[i])
{
return false;
}
i++;
}
return true;
}
// > 操作符重载
bool operator>(string& s1, string& s2)
{
int i1 = 0, i2 = 0;
while ((i1 < s1.size()) && (i2 < s2.size()))
{
if (s1[i1] > s2[i2])
{
return true;
}
else if (s1[i1] == s2[i2])
{
return false;
}
else
{
i1++;
i2++;
}
}
if (i1 == s1.size())
{
return false;
}
else
{
return true;
}
}
// != 操作符重载
bool operator!=(string& s1, string& s2)
{
return !(s1 == s2);
}
// < 操作符重载
bool operator<(string& s1, string& s2)
{
return !((s1 == s2) || (s1 > s2));
}
// >= 操作符重载
bool operator>=(string& s1, string& s2)
{
return (s1 > s2) || (s1 == s2);
}
// <= 操作符重载
bool operator<=(string& s1, string& s2)
{
return (s1 < s2) || (s1 == s2);
}
//测试函数
void test1()
{
string s1("hello");
string s2(s1);
string s3("world!");
s3 = s1;
s3.PushBack(' ');
s3.append("world!");
s1 += ' ';
s1 += "world!";
s1.print();
}
void test2()
{
string s1;
string s2("hello");
s2.resize(2);
s2.resize(5, 'a');
s2.resize(20);
s2[17] = 'x';
cout << "print()函数打印" << endl;
s2.print();
cout << "while迭代器遍历" << endl;
string::iterator it = s2.begin();// (string::)作用是指定类域
// (iterator)是变量it的类型,这里实际是char*.
// ( s1.begin(); )这个是调用对象s1的成员函数
while (it != s2.end())
{
cout << *it << ' ';
it++;
}
cout << endl;
cout << "范围for遍历" << endl;
for (auto c : s2)
{
cout << c << ' '; //一个容器只要按规范支持迭代器,就支持范围for
}
cout << endl;
}
void test3()
{
string s1("15678");
print(s1);
s1.insert(1, "234");
print(s1);
}
void test4()
{
string s1("hello");
//s1.erase(0, 1);
cin >> s1;
print(s1);
}
void test5()
{
string s1("hello");
//getline(cin, s1);
print(s1);
string s2("hello");
string s3(s2);
s3 += 'c';
s1 == s2;
s1 > s3;
}
void test6()
{
string s1("hello");
string s2(s1);
string s3 = s1 + 'a';
string s4 = s2 + " world!";
}
}
int main()
{
//zzd::test1();
//zzd::test2();
//zzd::test3();
//zzd::test4();
//zzd::test5();
zzd::test6();
return 0;
}
以上是关于string类及相关函数的实现的主要内容,如果未能解决你的问题,请参考以下文章