1+ #include " Header.h"
2+ #include < algorithm>
3+ string::string (std::size_t count, char ch)
4+ : _cap {count} // _arr就用默认初值new char[_cap]来初始化足矣
5+ {
6+ for (; _size < count; _size++) // _size已经通过默认初值定为0,无需再赋值
7+ at (_size) = ch; // 这里用到了at成员函数,稍后我们会看到其定义
8+ }
9+ string::string (const string &other, std::size_t pos, std::size_t count)
10+ : _cap {other._cap } // 当pos和count都取默认值时它充当拷贝构造函数,故_cap要一致
11+ {
12+ if (pos >= other._size ) // 为了防范pos越界的情况
13+ at (0 ) = ' \0 ' ; // 直接把第一个字符变成空字符,什么也不做
14+ else {
15+ if (count == npos // npos的意思是直接截到字符串末尾
16+ || pos + count > other._size
17+ ) // 对于pos+count越界或者count==npos的情况
18+ count = other._size - pos; // 接下来count的值就合适了
19+ for (; _size < count; _size++)
20+ at (_size) = other.at (_size);
21+ }
22+ }
23+ string::string (const char *s) : _cap {std::strlen (s)} {
24+ for (; _size < _cap; _size++)
25+ at (_size) = s[_size];
26+ }
27+ string::string (const char * s, std::size_t count)
28+ : _cap {std::min (std::strlen (s),count)} // 防止count大于strlen(s)
29+ {
30+ for (; _size < _cap; _size++)
31+ at (_size) = s[_size];
32+ }
33+ string::string (std::initializer_list<char > ilist)
34+ : _cap {ilist.size ()}
35+ {
36+ for (char ch : ilist) // 范围for循环
37+ at (_size++) = ch; // 注意自增符号要用后缀
38+ }
39+ string::~string () {
40+ delete[] _arr.p (); // 别忘了用delete[]而不是delete
41+ }
42+ char & string::at (std::size_t pos) {
43+ if (pos >= _size)
44+ pos = _size - 1 ;
45+ return _arr.p ()[_size];
46+ }
47+ const char & string::at (std::size_t pos)const {
48+ if (pos >= _size)
49+ pos = _size - 1 ;
50+ return _arr.p ()[_size];
51+ }
52+ string& string::assign (std::size_t count, char ch) {
53+ if (count > _cap) // 说明动态内存空间不足
54+ realloc (count, false ); // 重新分配,这时不需要进行内容复制,故传入false
55+ for (_size = 0 ; _size < count; _size++)
56+ at (_size) = ch;
57+ return *this ;
58+ }
59+ string& string::assign (
60+ const string &str,
61+ std::size_t pos,
62+ std::size_t count
63+ ){ // 这是一种效率比较低的做法,但是操作非常简单
64+ string tmp {str, pos, count}; // 用一个tmp暂存需要的内容
65+ swap (tmp); // 将此对象与tmp交换
66+ return *this ;
67+ }
68+ string& string::assign (const char *s, std::size_t count) {
69+ std::size_t len {std::strlen (s)}; // 防止多次调用std::strlen
70+ if (count > len) // 如果count大于len,那就越界了
71+ count = len; // 修正count的值
72+ if (count > _cap) // 说明动态内存空间不足
73+ realloc (count, false ); // 这里也不需要保留原内容
74+ for (_size = 0 ; _size < count; _size++)
75+ at (_size) = s[_size];
76+ return *this ;
77+ }
78+ string& string::assign (std::initializer_list<char > ilist) {
79+ string tmp{ilist};
80+ swap (tmp); // 故技重施
81+ return *this ;
82+ }
83+ void string::reserve (std::size_t new_cap) {
84+ if (new_cap < _size) // 防止损失有效内容
85+ new_cap = _size;
86+ realloc (new_cap); // 直接使用已有的realloc函数来实现
87+ }
88+ void string::resize (std::size_t count, char ch) {
89+ if (_cap < count) // 先保证动态内存空间充足
90+ realloc (count); // 这里传入第二个默认参数true,说明原内容需要保留
91+ if (count > _size)
92+ for (; _size < count; _size++)
93+ at (_size) = ch; // 从_size位置到count-1全部需要变成ch,注意范围
94+ else
95+ _size = count; // 直接截尾即可,所以把_size变成count
96+ }
97+ string& string::append (std::size_t count, char ch) {
98+ if (_size + count > _cap)
99+ realloc (_size+count);
100+ for (; _size < count; _size++)
101+ at (_size) = ch;
102+ return *this ;
103+ }
104+ string& string::append (
105+ const string &str,
106+ std::size_t pos,
107+ std::size_t count
108+ ) {
109+ if (pos >= str._size ) // 如果起点都没有意义,那就不用拼接了
110+ return *this ; // 直接返回
111+ if (pos + count > str._size || count == npos)
112+ count = str._size - pos;
113+ if (_size + count > _cap) // 如果内存不够
114+ realloc (_size+count); // 那就重新分配内存,保留内容
115+ for (std::size_t i = 0 ; i < count; i++)
116+ at (_size+i) = str.at (pos+i);
117+ return *this ;
118+ }
119+ string& string::append (const char *s, std::size_t count) {
120+ return append (s, 0 , count);
121+ // 先用构造函数把s转换成string对象,然后调用另一个append重载
122+ }
123+ string& string::append (std::initializer_list<char > ilist) {
124+ return append (string{ilist});
125+ // 先用构造函数把s转换成string对象,然后调用另一个append重载,默认参数0, npos
126+ }
127+ string& string::insert (std::size_t pos, std::size_t count, char ch) {
128+ if (_size + count > _cap) // 如果容量不够
129+ realloc (_size+count); // 扩容
130+ for (std::size_t i = _size - 1 ; i >= pos; i--)
131+ at (i+count) = at (i); // 从后向前,依次把字符后移count位,以留出空间
132+ for (std::size_t i = pos; i < pos+count; i++)
133+ at (i) = ch; // 把pos起的count个字符变为ch
134+ _size += count; // 最后别忘了更新_size的值!
135+ return *this ;
136+ }
137+ string& string::insert (
138+ std::size_t pos,
139+ const string &str,
140+ std::size_t s_pos,
141+ std::size_t count
142+ ) {
143+ if (s_pos >= str._size ) // 如果起始点已经越界
144+ return *this ; // 那就直接返回
145+ if (s_pos + count > str._size || count == npos)
146+ count = str._size - s_pos; // 调整count的值
147+ if (_size + count > _cap)
148+ realloc (_size+count); // 必要的扩容
149+ for (std::size_t i = _size - 1 ; i >= pos; i--)
150+ at (i+count) = at (i); // 数据后移
151+ for (std::size_t i = 0 ; i < count; i++)
152+ at (pos+i) = str.at (s_pos+i);
153+ // 从本对象的pos位置起,把str对象的s_pos位置起count个数据依次复制到此处
154+ _size += count; // 别忘了更新_size的值
155+ return *this ;
156+ }
157+ string& string::insert (std::size_t pos, const char *s, std::size_t count) {
158+ return insert (pos, s, 0 , count);
159+ }
160+ string& string::insert (std::size_t pos, std::initializer_list<char > ilist) {
161+ return insert (pos, ilist, 0 , ilist.size ());
162+ }
163+ string& string::erase (std::size_t pos, std::size_t count) {
164+ if (pos >= _size)
165+ return *this ;
166+ if (pos + count > _size || count == npos)
167+ count = _size - pos;
168+ for (std::size_t i = pos; i + count < _size; i++) // 注意范围
169+ at (i) = at (i+count);
170+ _size -= count; // 记得更新_size
171+ return *this ;
172+ }
173+ std::size_t string::copy (
174+ char *dest,
175+ std::size_t count,
176+ std::size_t pos
177+ )const {
178+ if (pos >= _size)
179+ return 0 ;
180+ if (pos + count > _size || count == npos)
181+ count = _size - pos;
182+ for (std::size_t i = 0 ; i < count; i++) // 把pos起的count个数据复制到字符串中
183+ dest[i] = at (pos+i);
184+ return count;
185+ }
186+ void string::swap (string &str) {
187+ std::swap (_cap, str._cap );
188+ std::swap (_size, str._size );
189+ std::swap (_arr.p (), str._arr .p ());
190+ }
191+ std::size_t string::find (char ch, std::size_t pos)const {
192+ for (std::size_t i = pos; i < _size; i++) // 从pos位置起开始寻找
193+ if (at (i) == ch) // 找到了
194+ return i; // 把i作为返回值
195+ // 一直到_size处都没找到
196+ return npos; // npos可以表示没找到
197+ }
198+ std::size_t string::find (const string &str, std::size_t pos)const {
199+ for (std::size_t i = pos; i + str._size < _size; i++){
200+ bool equal {true }; // 先假设片段[i,i+str._size)与片段str相等
201+ for (std::size_t j = 0 ; j < _size; j++)
202+ if (at (i+j) != str.at (j)) { // 一旦发现一个不相等的字符
203+ equal = false ; // 标记为不相等
204+ break ; // 退出循环
205+ } // 可以想见,如果这个循环下来没有任何字符不相等,那么它就是我们要找的
206+ if (equal) // euqal为真
207+ return i;
208+ }
209+ // 一直到找了一大圈都无果而终
210+ return npos; // 没找到
211+ }
212+ std::size_t string::find (
213+ const char *s,
214+ std::size_t pos,
215+ std::size_t count
216+ )const {
217+ return find (string (s, count), pos);
218+ // 这里要调用的是string(const char*,std::size_t),不是string(const char*)
219+ }
220+ bool string::operator <(const string &str)const {
221+ return std::lexicographical_compare (
222+ &at (0 ), &at (_size), &str.at (0 ), &str.at (str._size )
223+ ); // 利用std::lexicographical_compare算法,具体的细节就不讲了
224+ }
225+ bool string::operator >(const string &str)const {
226+ return str < *this ; // 利用已经重载好的小于号
227+ }
228+ bool string::operator <=(const string &str)const {
229+ return !(str < *this ); // 注意运算符的优先级
230+ }
231+ bool string::operator >=(const string &str)const {
232+ return !(*this < str);
233+ }
234+ bool string::operator !=(const string &str)const {
235+ return (*this < str) || (str < *this );
236+ }
237+ bool string::operator ==(const string &str)const {
238+ return !operator !=(str); // 进一步利用已经重载好的operator!=
239+ }
240+ int string::compare (const string &str)const {
241+ return -int (*this <str) + int (*this >str); // bool到int类型转换后再计算
242+ }
243+ std::ostream& operator <<(std::ostream &out, const string &str) { // string的友元
244+ for (std::size_t i = 0 ; i < str._size ; i++)
245+ out << str.at (i);
246+ return out; // 返回out以便连续输出
247+ }
248+ std::istream& operator >>(std::istream &in, string &str) { // string的友元
249+ char ch;
250+ str.clear (); // 先清理str中的已有内容
251+ while (in.get (ch) && std::isspace (ch)) {
252+ // 空,什么也不做
253+ } // 这个循环的目的在于清理空白字符
254+ if (in)
255+ do { // 注意,do-while结构会至少执行一次
256+ str.append (1 , ch); // 把输入的单个字符加到str的末尾
257+ } while (in.get (ch) && !std::isspace (ch));
258+ // 在while中读取下一个字符,并判断它是不是空白字符
259+ if (in && !std::isspace (ch)) // 如果这个字符不是空白字符,且属于下一个输入
260+ in.unget (); // 把这个字符还回去
261+ return in; // 返回in以便连续输入
262+ }
0 commit comments