如何選擇鎮(zhèn)江網(wǎng)站建設(shè)優(yōu)化設(shè)計五年級下冊語文答案
目錄
一.實現(xiàn)string類
1.string的構(gòu)造及析構(gòu)
2.string類的遍歷
3.string類的插入和刪除
4.string類的空間處理
5.string類的查找
6.string類的輸出和輸入
7.string類的常用判斷
二.整體代碼
1.string.h
2.string.cpp
一.實現(xiàn)string類
在前一節(jié)中我們了解了STL中string的部分接口,在這里我們實現(xiàn)一個自己的string類
當(dāng)我們實現(xiàn)自己的string類時,名字會與庫內(nèi)的沖突,所以可以選擇用命名空間解決
1.string的構(gòu)造及析構(gòu)
當(dāng)我們在開空間的時候一般要多開一個用于存放\0
拷貝構(gòu)造和賦值用傳統(tǒng)方法寫一般是開新空間,復(fù)制過去,釋放舊空間,但是在這里我們使用現(xiàn)代寫法,直接將空間交換過來使用
而在swap函數(shù)中使用::,是為了讓他去調(diào)用庫中的函數(shù),而不是類中的
string(const char* str = "")
{_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];//strcpy(_str,str);不安全,會報錯,無法實現(xiàn)功能,在后面主要使用strcpy_sstrcpy_s(_str, strlen(str) + 1, str);//c11標(biāo)準(zhǔn)
}//深拷貝,若用編譯器自動生成的為淺拷貝,析構(gòu)時會出現(xiàn)問題
string(const string& s):_str(nullptr),_size(0),_capacity(0)
{string tmp(s._str);//his->swap(tmp);swap(tmp);
}void swap(string& s)
{::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);
}~string()
{delete[] _str;_str = nullptr;_size = _capacity = 0;
}string& operator=(string s)
{//this->swap(s);swap(s);return *this;
}
2.string類的遍歷
對于string類的遍歷我們可以通過[]+下標(biāo),迭代器,范圍for語句遍歷,以及c_str
所以我們需要自己定義迭代器,重載[]
typedef char* iterator;iterator begin()
{return _str;
}iterator end()
{return _str + _size;
}char& operator[](size_t i)
{assert(i < _size);return _str[i];
}const char& operator[](size_t i) const
{assert(i < _size);return _str[i];
}const char* c_str()
{return _str;
}
3.string類的插入和刪除
對于插入我們都要考慮的便是容量不夠需要增容,同時也應(yīng)該考慮字符串開始為空的情況,如果為空就給一個容量,否則就擴2倍
push_back的話我們只需要將字符加在末端即可
append將插入的字符串復(fù)制到原字符串末尾即可
+=對于單個push_back,字符串復(fù)用append
insert插入單個字符時,將字符從末尾開始向后移一位,將字符插入頭即可,插入字符串時后移的位數(shù)變?yōu)椴迦胱址拈L度
erase刪除主要考慮兩種情況,刪除一部分和全部刪完,全部刪完比較簡單,將刪除的位置變?yōu)閈0,將size變?yōu)閜os即可,刪除部分,將后面的字符前移覆蓋
void push_back(char ch){if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;reserve(newcapacity);}_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);strcpy_s(_str + _size, strlen(str) + 1, str);_size += len;}string& operator+=(char ch){this->push_back(ch);return *this;}string& operator+=(const char* str){this->append(str);return *this;}string& insert(size_t pos, char ch){assert(pos < _size);if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;reserve(newcapacity);}int end = _size;while (end >= (int)pos){_str[end + 1] = _str[end];--end;}_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 end = _size;while (end >= (int)pos){_str[end + len] = _str[end];--end;}for (size_t i = 0; i < len; ++i){_str[pos++] = str[i];}_size += len;return *this;}void 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[i - len] = _str[i];++i;}_size -= len;}}
4.string類的空間處理
reserve比較簡單,直接開出一段空間即可,而resize則需要考慮空間的縮小,縮小的話將給定位置變?yōu)閈0,放大空間的話,reserve空間,然后將size后面的都填上給定的或默認(rèn)字符
size_t size() const{return _size;}size_t capacity() const{return _capacity;}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];//strcpy(tmp, _str);strcpy_s(tmp, strlen(_str) + 1, _str);delete[] _str;_str = tmp;_capacity = n;}}void resize(size_t n, char ch = '\0'){if (n < _size){_str[n] = '\0';_size = n;}else{if (n > _capacity){reserve(n);}for (size_t i = _size; i < n; ++i){_str[i] = ch;}_size = n;_str[_size] = '\0';}}
5.string類的查找
size_t find(char ch, size_t pos = 0)
{for (size_t i = pos; i < _size; ++i){if (_str[i] == ch){return i;}}return npos;
}size_t find(const char* str, size_t pos = 0)
{char* p = strstr(_str, str);if (p == nullptr){return npos;}else{return p - _str;}
}
6.string類的輸出和輸入
ostream& operator<<(ostream& out, const string& s){for (size_t i = 0; i < s.size(); ++i){cout << s[i];}return out;}//getline()只需要去掉if中的' '即可istream& operator>>(istream& in, string& s){while (1){char ch;ch = in.get();if (ch == ' ' || ch == '\n'){break;}else{s += ch;}}return in;}
7.string類的常用判斷
bool operator<(const string& s)
{int ret = strcmp(_str, s._str);return ret < 0;
}bool operator==(const string& s)
{int ret = strcmp(_str, s._str);return ret == 0;
}bool operator<=(const string& s)
{return *this < s || *this == s;
}bool operator>(const string& s)
{return !(*this <= s);
}bool operator>=(const string& s)
{return !(*this < s);
}bool operator!=(const string& s)
{return !(*this == s);
}
二.整體代碼
1.string.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace wzyl
{class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char* str = ""){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];//strcpy(_str,str);不安全,會報錯,無法實現(xiàn)功能,在后面主要使用strcpy_sstrcpy_s(_str, strlen(str) + 1, str);//c11標(biāo)準(zhǔn)}//深拷貝,若用編譯器自動生成的為淺拷貝,析構(gòu)時會出現(xiàn)問題string(const string& s):_str(nullptr),_size(0),_capacity(0){string tmp(s._str);//his->swap(tmp);swap(tmp);}void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}string& operator=(string s){//this->swap(s);swap(s);return *this;}size_t size() const{return _size;}size_t capacity() const{return _capacity;}char& operator[](size_t i){assert(i < _size);return _str[i];}const char& operator[](size_t i) const{assert(i < _size);return _str[i];}const char* c_str(){return _str;}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];//strcpy(tmp, _str);strcpy_s(tmp, strlen(_str) + 1, _str);delete[] _str;_str = tmp;_capacity = n;}}void resize(size_t n, char ch = '\0'){if (n < _size){_str[n] = '\0';_size = n;}else{if (n > _capacity){reserve(n);}for (size_t i = _size; i < n; ++i){_str[i] = ch;}_size = n;_str[_size] = '\0';}}void push_back(char ch){if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;reserve(newcapacity);}_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);strcpy_s(_str + _size, strlen(str) + 1, str);_size += len;}string& operator+=(char ch){this->push_back(ch);return *this;}string& operator+=(const char* str){this->append(str);return *this;}string& insert(size_t pos, char ch){assert(pos < _size);if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;reserve(newcapacity);}int end = _size;while (end >= (int)pos){_str[end + 1] = _str[end];--end;}_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 end = _size;while (end >= (int)pos){_str[end + len] = _str[end];--end;}for (size_t i = 0; i < len; ++i){_str[pos++] = str[i];}_size += len;return *this;}void 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[i - len] = _str[i];++i;}_size -= len;}}size_t find(char ch, size_t pos = 0){for (size_t i = pos; i < _size; ++i){if (_str[i] == ch){return i;}}return npos;}size_t find(const char* str, size_t pos = 0){char* p = strstr(_str, str);if (p == nullptr){return npos;}else{return p - _str;}}bool operator<(const string& s){int ret = strcmp(_str, s._str);return ret < 0;}bool operator==(const string& s){int ret = strcmp(_str, s._str);return ret == 0;}bool operator<=(const string& s){return *this < s || *this == s;}bool operator>(const string& s){return !(*this <= s);}bool operator>=(const string& s){return !(*this < s);}bool operator!=(const string& s){return !(*this == s);}private:char* _str;size_t _size;//有效字符個數(shù)size_t _capacity;//能存多少有效字符,\0不是有效字符static size_t npos;};size_t string::npos = -1;ostream& operator<<(ostream& out, const string& s){for (size_t i = 0; i < s.size(); ++i){cout << s[i];}return out;}//getline()只需要去掉if中的' '即可istream& operator>>(istream& in, string& s){while (1){char ch;ch = in.get();if (ch == ' ' || ch == '\n'){break;}else{s += ch;}}return in;}void test_string1(){string s1("hello");string s2;cout << s1 << endl;cout << s2 << endl;cout << s1.c_str() << endl;cout << s2.c_str() << endl;//3種遍歷方式for (size_t i = 0; i < s1.size(); ++i){s1[i] += 1;cout << s1[i] << " ";}cout << endl;string::iterator it = s1.begin();while (it != s1.end()){*it -= 1;cout << *it << " ";++it;}cout << endl;//范圍for是由迭代器支持的,所以這段代碼最后會被替換成迭代器for (auto e : s1){cout << e << " ";}cout << endl;}void test_string2(){string s1("hello");s1.push_back(' ');s1.push_back('w');s1.push_back('o');s1.push_back('r');s1.push_back('l');s1.push_back('d');cout << s1 << endl;s1.append("xxxxxxxxx");cout << s1 << endl;string s2;s2 += "hello";s2 += ' ';s2 += "world";cout << s2 << endl;}void test_string3(){string s1("hello");s1.insert(1, 'x');s1.insert(1, "xyz");s1.insert(0, 'p');cout << s1 << endl << endl;string s2("hello");s2.reserve(10);cout << s2 << endl;cout << s2.size() << endl;cout << s2.capacity() << endl << endl;s2.resize(10, 'x');cout << s2 << endl;cout << s2.size() << endl;cout << s2.capacity() << endl << endl;s2.resize(18, 'a');cout << s2 << endl;cout << s2.size() << endl;cout << s2.capacity() << endl << endl;s2.resize(2);cout << s2 << endl;cout << s2.size() << endl;cout << s2.capacity() << endl;}void test_string4(){string s("helloworld");s.erase(5, 2);cout << s << endl;s.erase(5, 4);cout << s << endl;string s1("abcdabcdef");cout << s1.find("cde") << endl;cout << s1.find("fgh") << endl;}void test_string5(){string s;cin >> s;cout << s << endl;string s1(s);cout << s1 << endl;string s2 = s1;cout << s2 << endl;}
}
2.string.cpp
#include "string.h"int main()
{wzyl::test_string1();wzyl::test_string2();wzyl::test_string3();wzyl::test_string4();wzyl::test_string5();return 0;
}