1.簡介
string類是表示字符串的字符類,是一塊連續的空間存儲字符串,並且可以通過統一接口,實現插入,刪除,尾插,查找,迭代器遍歷等一系列操作。
2.代碼展示
#define _CRT_SECURE_NO_WARNINGS 1;
#include<iostream>
#include<assert.h>
using namespace std;
namespace xff {
class string {
public:
typedef char* iterator;
//迭代器
iterator begin() {
return _str;
}
iterator rbegin() { //最後一個字符
return _str+_size-1;
}
iterator end() {
return _str + _size;
}
iterator rend() { //第一個字符的前一個
return --_str;
}
//構造函數
string(const char* str=""){
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
//拷貝構造
string(const string& s)
:_str(nullptr)
,_size(0)
,_capacity(0)
{
string tmp(s._str);
this->swap(tmp);
}
//析構函數
~string(){
if (_str) {
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
}
//=
string operator=(string s) {
this->swap(s);
return *this;
}
//size
size_t size()const {
return _size;
}
//capacity
size_t capacity()const {
return _capacity;
}
//[]
char& operator[](size_t index) {
assert(index < _size);
return _str[index];
}
//[]const
const char& operator[](size_t index)const {
assert(index < _size);
return _str[index];
}
//c_str
const char* c_str() {
return _str;
}
void swap( string& s) {
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
//判斷是否爲空
bool empty() {
if (_size == 0) {
return true;
}
return false;
}
//reserve預留空間
void reserve(size_t num) {
if (num > _capacity) {
char* newstr = new char[num + 1];
strcpy(newstr, _str);
delete[] _str;
_str = newstr;
_capacity = num;
}
}
//push_back
void push_back(const char ch) {
if (_size == _capacity) {
size_t newcapacity = _capacity == 0 ? 2 : 2*_capacity;
reserve(newcapacity);
}
_str[_size++] = ch;
_str[_size] = '\0';
}
//operator+=()字符
string& operator+=(const char ch) {
this->push_back(ch);
return *this;
}
//operator+=()字符串
string& operator+=(const char* str) {
this->append(str);
return *this;
}
//append加字符串
void append(const char* str = "") {
size_t len = strlen(str);
if (len + _size > _capacity) {
/*size_t newcapacity = _capacity = len + _size;
char* newstr = new char[newcapacity + 1];
strcpy(newstr, _str);
delete[] _str;
_str = newstr;*/
reserve(len + _size);
}
strcpy(_str + _size, str);
_size += len;
}
//將有效字符串置0
void clear() {
_size = 0;
}
//resize重置有效字符個數
//小於有效字符個數就截
//大於補字符
void resize(size_t num, const char ch ='\0') {
if (num <= _size) {
_size = num;
}
else {
while (num - _size > 0) {
push_back(ch);
}
}
}
//插入單個字符
string& insert(size_t pos, const char ch) {
assert(pos < _size);
size_t size = _size;
if (_size == _capacity) {
size_t newcapacity = _capacity == 0 ? 2 : 2 * _capacity;
reserve(newcapacity);
}
while (pos<=size)
{
_str[size+1] = _str[size];
--size;
}
_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(_size + len);
}
int size = _size;
while ((int)pos <= size)//無符號-1是最大值,容易死循環
{
_str[size+len] = _str[size];
--size;
}
strncpy(_str + pos, str, len);//不要複製這個字符串尾部的空格,不然會覆蓋移動的字符
_size += len;
return *this;
}
//刪除
//大於等於pos到_size全刪
//小於保留餘下的,並且移動
string& erase(size_t pos,size_t len = npos) {
assert(pos < _size);
if (len>=_size-pos) {
_str[pos] = '\0';
_size = pos;
}
else
{
size_t i = pos+len;
while (i <= _size) {
_str[pos++] = _str[i++];
}
_size -= len;
}
return *this;
}
//find字符
size_t find(const char ch, size_t pos = 0) {
for (size_t i = pos; i < _size; ++i) {
if (_str[i] == ch) {
return i;
}
}
return npos;
}
//find字符串
size_t find(const char* str, size_t pos = 0) {
size_t len = strlen(str);
size_t dst = pos;
while (dst<_size) {
size_t src = 0;
pos = dst;
while (src<len&&_str[dst] == str[src]) {
++src;
++dst;
}
if (src == len) {
return pos;
}
++dst;
}
return npos;
}
bool operator==(const string& s) {
int ret = strcmp(_str, s._str);
if (ret == 0)
return true;
return false;
}
bool operator!=(const string& s) {
if (*this == s) {
return false;
}
return true;
}
bool operator>(const string& s) {
int ret = strcmp(_str, s._str);
if (ret > 0)
return true;
return false;
}
bool operator<(const string& s) {
int ret = strcmp(_str, s._str);
if (ret < 0)
return true;
return false;
}
bool operator>=(const string& s) {
if (*this < s) {
return false;
}
return true;
}
bool operator<=(const string& s) {
if (*this > s) {
return false;
}
return true;
}
const string substr(size_t pos, size_t n=npos) {
assert(pos < _size);
if (_size-pos<n) {
n = _size - pos;
}
char* newstr = new char[n + 1];
strncpy(newstr,_str + pos, n);
newstr[n] = '\0';
string s(newstr);
delete[] newstr;
return s;
}
private:
char* _str;
size_t _size;
size_t _capacity;
const static size_t npos;
};
const size_t string::npos = -1;
//重載<<
ostream& operator <<(ostream& _out, const string& s) {
for (size_t i = 0; i < s.size(); ++i) {
_out << s[i];
}
return _out;
}
//重載>>
istream& operator >>(istream& _in, string& s) {
while (1) {
char ch;
ch = _in.get();//輸入的全接收,包括空格換行
if (ch == '\n') {
break;
}
else
{
s += ch;
}
}
return _in;
}
void test_String1() {
string s1;
//cout << s1 << endl;
string s2("hello");
//cout << s2 << endl;
//cout << s2.size() << " " << s2.capacity() << endl;
string s3;
s3 = s2;
cout << s3 << endl;
//cin >> s1;
//cout << s1 << " " <<s1.empty()<<endl;
s2 += "world";
cout << s2 << endl;
//迭代器訪問
/*string::iterator it = s3.begin();
while (it != s3.end()) {
cout << *it << " ";
++it;
}
//for
for (auto e : s3) {
cout << e;
}*/
//s2.reserve(15);
//s2.reserve(3);
//cout << s2 << endl;
//cout << s2.size() << " " << s2.capacity() << endl;
//s3.resize(2);
//s3.resize(10);
//cout << s3 << endl;
//cout << s3.size() << " " << s3.capacity() << endl;
//s3.push_back(' ');
//cout << s3 << " ";
//cout << s3.size() << " " << s3.capacity() << endl;
//s3.append("world!");
//cout << s3 << " ";
//cout << s3.size() << " " << s3.capacity() << endl;
//s3.insert(0,"a");
//s3.insert(10, "abc");
//s3.insert(5,"a");
//s3.insert(1, 'a');
//s3.erase(2, 8);
//s3.erase(0);
//s3.erase(2, 2);
//cout << s3 << " ";
//cout << s3.size() << " " << s3.capacity() << endl;
//size_t num1 =s3.find('l');
//size_t num2 = s2.find("q",1);
//cout << num1 << " " << num2 << endl;
//cout << (s3>=s2)<< endl;
//cout << s3.substr(0, 8);
}
}
#include<string>
int main() {
string s1("hello");
//cout<<s1.substr(2);
//s1.insert(1,"ac");
//s1 += " world!";
//s1.push_back('!');
//s1.append("world!");
//s1.reserve(16);
//s1.resize(14,'a');
//s1.clear();
//s1.erase();
//cout << s1.substr(2);
//cout << s1 << endl;
//int num = s1.find("ello",0);
//cout << s1<<" "<<s1.size()<<" "<<s1.capacity() <<endl;
/*string::iterator it = s1.begin();
while (it != s1.end()) {
cout << *it;
++it;
}
cout << endl;
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend()) {
cout << *rit;
++rit;
}*/
xff::test_String1();
system("pause");
return 0;
}
3.總結
1.迭代器是c++ STL組件之一,是通用的遍歷容器的方式,講操作和底層實現分離,我們只需要調用對應的接口,就能實現對容器的遍歷,針對不同的數據結構,有規範接口的作用。
2.實現插入刪除等操作時,迭代器會失效,可能會出現重新分配內存空間的情況,迭代器就失效了。
3.clear()清除有效字符,容量不變。
4.reserve(size_t n)預留空間,不改變有效字符個數,擴容作用。
5.resize(size_t n,char ch)改變有效字符個數,小於有效字符個數就只保留到n,大於當前有效字符個數就補ch到n,前面的字符不變。
6.push_back(ch)尾部插入,不可以爲空,可以插空格。
7.append(str) 尾插字符串。
8.erase(pos,n)從pos開始刪除n個字符,默認是最大值size_t npos=-1。
9.insert(_size,str)只能插入字符串,並且小於等於_size。
10.find(str/ch,pos)從pos位置開始查找str/ch,找到返回第一個下標,找不到返回npos,rfind反向查找。
11.c_str() 返回C格式字符串,return _str.
12.substr(pos,n)從pos截取n個字符,默認npos,返回字符串。
13.getline string類的非成員函數,獲取一行字符串,空格也接收,cin會將\n和空格,作爲結束的標誌。
14.reverse(s.begin(),s.end()),結尾是需要逆置的字符的下一個位置。
4.心得體會
通過實現string類,我對string類的認識進一步加強,同時我也更加熟悉構造函數,析構函數等,同時對new,delete的使用更加熟練。初次學習,可能有不對的地方,希望大家指出來,共同進步。