C++学习之路,从0到精通的征途:string类的模拟实现

目录

一.string类的成员变量与成员函数

二.string类的接口实现

1.构造函数,析构函数,拷贝构造函数,赋值重载

(1)构造函数

(2)析构函数

(3)拷贝构造函数

(4)赋值重载

2.迭代器

3.容量:size,capacity,empty,resize,reserve

(1)size

(2)capacity

(3)empty

(4)reserve

(5)resize

4.访问:operator[]

5.修改:push_back,operator+=,append,clear,swap,c_str

(1)push_back

(2)operator[]

(3)append

(4)operator+=

[(5) clear](#(5) clear)

(6)swap

(7)c_str

6.逻辑运算符

7.查找:find

8.在固定位置插入数据:insert

9.删除固定位置的数据:erase

10.流插入,流提取运算符重载:<<,>>

(1)流插入<<

(2)流提取>>

三.现代版写法的string类

1.构造函数

2.拷贝构造函数

3.赋值重载

四.代码总览

string.h

string.cpp

test.cpp


一.string类的成员变量与成员函数

cpp 复制代码
namespace my_string
{
	class string
	{
		friend std::ostream& operator<<(std::ostream& _cout, const my_string::string& s);
		friend std::istream& operator>>(std::istream& _cin, my_string::string& s);
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		string(const char* str = "")
			:_size(strlen(str))
		{                                                              
			_str = new char[_size + 1];
			_capacity = _size;
			memcpy(_str, str, _size + 1);
		}

		string(const string& s)
		{
			_str = new char[s._capacity + 1];
			memcpy(_str, s._str, s._size + 1);
			_size = s._size;
			_capacity = s._capacity;
		}

		string& operator=(const string& s)
		{
			char* tmp = new char[s._capacity + 1];
			memcpy(tmp, s._str, s._size + 1);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
			return *this;
		}

		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}

		// iterator
		iterator begin();
		iterator end();
		const_iterator begin() const;
		const_iterator end() const;

		// capacity
		size_t size() const;
		size_t capacity() const;
		bool empty() const;
		void resize(size_t n, char c = '\0');
		void reserve(size_t n);

		// access
		char& operator[](size_t index);
		const char& operator[](size_t index)const;

		// relational operators
		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);

		// modify
		void push_back(char c);
		string& operator+=(char c);
		void append(const char* str);
		string& operator+=(const char* str);
		void clear();
		void swap(string& s);
		const char* c_str() const;

		// 返回c在string中第一次出现的位置
		size_t find(char c, size_t pos = 0) const;
		// 返回子串s在string中第一次出现的位置
		size_t find(const char* s, size_t pos = 0) const;
		// 在pos位置上插入字符c/字符串str,并返回该字符的位置
		string& insert(size_t pos, char c);
		string& insert(size_t pos, const char* str);
		// 删除pos位置上的元素,并返回该元素的下一个位置
		string& erase(size_t pos, size_t len);

	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	public:
		static const size_t npos;
	};
}

二.string类的接口实现

1.构造函数,析构函数,拷贝构造函数,赋值重载

(1)构造函数

cpp 复制代码
string(const char* str = "")
	:_size(strlen(str))
{                                                              
	_str = new char[_size + 1];
	_capacity = _size;
	memcpy(_str, str, _size + 1);
}

_size在初始化列表中用给定的字符串的长度初始化,若没有给定字符串,则采用缺省值的空字符串。

在函数体内初始化_str,new一个size+1大小的连续空间,用来存放给定的字符串的'\0',申请完空间后,最后将给定字符串中的数据按字节拷贝给_str。

(2)析构函数

cpp 复制代码
~string()
{
	delete[] _str;
	_str = nullptr;
	_size = _capacity = 0;
}

(3)拷贝构造函数

cpp 复制代码
string(const string& s)
{
	_str = new char[s._capacity + 1];
	memcpy(_str, s._str, s._size + 1);
	_size = s._size;
	_capacity = s._capacity;
}

如果在这里不写拷贝构造,那么编译器则会调用默认的拷贝构造来进行浅拷贝,则会导致同一块空间被析构两次,所以这里需要手动写深拷贝,并将数据按字节转移到新对象中。

(4)赋值重载

cpp 复制代码
string& operator=(const string& s)
{
	char* tmp = new char[s._capacity + 1];
	memcpy(tmp, s._str, s._size + 1);
	delete[] _str;
	_str = tmp;
	_size = s._size;
	_capacity = s._capacity;
	return *this;
}

赋值重载与拷贝构造的区别在于需要将被赋值对象所申请的资源释放,并返回被赋值的对象,实现连续赋值。

2.迭代器

string类的迭代器以指针为底层逻辑进行实现:

cpp 复制代码
typedef char* iterator;
typedef const char* const_iterator;
cpp 复制代码
string::iterator string::begin()
{
	return _str;
}

string::iterator string::end()
{
	return _str + _size;
}

string::const_iterator string::begin() const
{
	return _str;
}

string::const_iterator string::end() const
{
	return _str + _size;
}

有了迭代器之后就可以实现范围for:

3.容量:size,capacity,empty,resize,reserve

(1)size

cpp 复制代码
size_t string::size() const
{
	return _size;
}

(2)capacity

cpp 复制代码
size_t string::capacity() const
{
	return _capacity;
}

(3)empty

cpp 复制代码
bool string::empty() const
{
	return _size == 0;
}

(4)reserve

reserve所传的参数n一般分为两种情况:

根据std中的reserve,我们在n<capacity的情况下,对容量不做处理。

在n>capacity的情况下,进行异地扩容,并将原数据复制到新空间中,释放旧空间,更新capacity大小:

cpp 复制代码
void string::reserve(size_t n)
{
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];
		memcpy(tmp, _str, _size + 1);
		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}

(5)resize

resize所传的参数n一般分为三种情况:

当n<size,删除数据,不改变容量。

当size<n<capacity,插入数据,不改变容量。

当n>capacity,先进行扩容,再插入数据。

由于resize如果不传用来插入的数据c,则直接用'\0'进行填充,所以缺省值采用'\0':

cpp 复制代码
void resize(size_t n, char c = '\0')
{
    if (n < _size)
    {
        _str[_size] = '\0';
    }
    else
    {
        if (n > _capacity)
        {
            reserve(n);
        }
 
        for (int i = _size; i < n; i++)
        {
            _str[i] = c;
        }
    }
 
    _size = n;
}

4.访问:operator[]

cpp 复制代码
char& string::operator[](size_t index)
{
	return _str[index];
}

const char& string::operator[](size_t index) const
{
	return _str[index];
}

5.修改:push_back,operator+=,append,clear,swap,c_str

(1)push_back

cpp 复制代码
void string::push_back(char c)
{
	if (_size == _capacity)
	{
		size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
		reserve(newcapacity);
	}
	_str[_size++] = c;
	_str[_size] = '\0';
}

(2)operator[]

cpp 复制代码
string& string::operator+=(char c)
{
	push_back(c);
	return *this;
}

string& string::operator+=(const char* str)
{
	append(str);
	return *this;
}

(3)append

cpp 复制代码
void string::append(const char* str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
        // 扩容
		size_t newcapacity = _size + len > 2 * _capacity ? _size + len : 2 * _capacity;
		reserve(newcapacity);
	}
	memcpy(_str + _size, str, len + 1);
	_size += len;
}

(4)operator+=

cpp 复制代码
// += 单个字符
string& string::operator+=(char c)
{
	push_back(c);
	return *this;
}

// += 字符串
string& string::operator+=(const char* str)
{
	append(str);
	return *this;
}

(5) clear

cpp 复制代码
void string::clear()
{
	_str[0] = '\0';
	_size = 0;
}

(6)swap

cpp 复制代码
void string::swap(string& s)
{
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

(7)c_str

cpp 复制代码
const char* string::c_str() const
{
	return _str;
}

6.逻辑运算符

对于比较运算符,字符的ASCII码相等,则继续比较,不相等,则根据实际情况返回比较结果,若到比较结束,并未返回,则根据字符串的长度来决定返回结果:

以operator<和operator==为例:

cpp 复制代码
bool string::operator<(const string& s)
{
	size_t end1 = _size - 1;
	size_t end2 = s._size - 1;
	size_t begin1 = 0;
	size_t begin2 = 0;
	while (begin1 != end1 && begin2 != end2)
	{
		if (_str[begin1] < s._str[begin2])
		{
			return true;
		}
		else if (_str[begin1] > s._str[begin2])
		{
			return false;
		}
		begin1++;
		begin2++;
	}
	//if (begin1 == end1 && begin2 != end2)
	//{
	//	return true;
	//}
	//else
	//{
	//	return false;
	//}
	return begin1 == end1 && begin2 != end2;
}

bool string::operator==(const string& s)
{
	size_t end1 = _size - 1;
	size_t end2 = s._size - 1;
	size_t begin1 = 0;
	size_t begin2 = 0;
	while (begin1 != end1 && begin2 != end2)
	{
		if (_str[begin1] != s._str[begin2])
		{
			return false;
		}
		begin1++;
		begin2++;
	}
	return begin1 == end1 && begin2 == end2;
}

这里的比较没有使用strcmp的原因是strcmp在遇到'\0'后则不再比较,无法解决字符串中包含'\0'的情况。

在实现了任一比较大小和相等后,剩余的比较运算符则可以直接进行复用:

cpp 复制代码
bool string::operator<=(const string& s)
{
	return *this < s || *this == s;
}

bool string::operator>(const string& s)
{
	return !(*this <= s);
}

bool string::operator>=(const string& s)
{
	return !(*this < s);
}

bool string::operator!=(const string& s)
{
	return !(*this == s);
}

7.查找:find

(1)从pos位置开始向后查找字符c,返回c在string中第一次出现的位置,没找到返回npos

cpp 复制代码
size_t string::find(char c, size_t pos) const
{
	assert(pos < _size);
	for (int i = pos; i < _size; ++i)
	{
		if (_str[i] == c)
		{
			return i;
		}
	}
	return npos;
}

(2)从pos位置开始向后查找字符串s,返回s在string中第一次出现的位置,没找到返回npos

cpp 复制代码
size_t string::find(const char* s, size_t pos) const
{
	assert(pos < _size);
	const char* tmp = strstr(_str + pos, s);
	if (tmp == nullptr)
	{
		return npos;
	}
	return tmp - _str;
}

8.在固定位置插入数据:insert

(1)在pos位置上插入字符c

cpp 复制代码
string& string::insert(size_t pos, char c)
{
	assert(pos <= _size);
	if (_size == _capacity)
	{
        // 扩容
		size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
		reserve(newcapacity);
	}
	//size_t end = _size + 1;
	//while (end > pos)
	//{
	//	_str[end] = _str[end - 1];
	//	end--;
	//}
	memmove(_str + pos + 1, _str + pos, _size - pos + 1);
	_str[pos] = c;
	_size++;
	return *this;
}

(2)在pos位置上插入字符串str

cpp 复制代码
string& string::insert(size_t pos, const char* str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		size_t newcapacity = _size + len > 2 * _capacity ? _size + len : 2 * _capacity;
		reserve(newcapacity);
	}
	memmove(_str + pos + len, _str + pos, _size + 1 - pos);
	memcpy(_str + pos, str, len);
	_size += len;
	return *this;
}

9.删除固定位置的数据:erase

当从pos位置开始要删除元素的个数大于剩余元素个数或等于npos时,将pos为之后的字符全部删除。

当从pos位置开始要删除元素的个数小于剩余元素个数时,将要被删除的元素用后面的元素覆盖:

cpp 复制代码
string& string::erase(size_t pos, size_t len)
{
	assert(pos < _size);
	if (len == npos || len >= _size - pos)
	{
		_str[pos] = '\0';
		_size = pos;
		return *this;
	}
	memmove(_str + pos, _str + pos + len, _size + 1 - (pos + len));
	_size -= len;
	return *this;
}

10.流插入,流提取运算符重载:<<,>>

(1)流插入<<

cpp 复制代码
std::ostream& operator<<(std::ostream& _cout, const my_string::string& s)
{
	for (int i = 0; i < s.size(); ++i)
	{
		_cout << s[i];
	}
	return _cout;
}

(2)流提取>>

cpp 复制代码
std::istream& operator>>(std::istream& _cin, my_string::string& s)
{
	// 每次提取前需要将s中的数据清除
	s.clear();
	// 模拟string中的buff缓冲区,当所输入的字符串有效数据个数小于256时,存放到buff中
	char buff[256];
	// 使用get函数,能够输入空白字符和换行符
	char ch = _cin.get();
	size_t i = 0;
	while (ch != ' ' && ch != '\n')
	{
		buff[i++] = ch;
		ch = _cin.get();
		if (i == 255)
		{
			s += buff;
			// 重置buff
			i = 0;
		}
	}

	// buff中有剩余字符
	if (i > 0)
	{
		buff[i] = '\0';
		s += buff;
	}
	return _cin;
}

三.现代版写法的string类

1.构造函数

用迭代器初始化string类:

cpp 复制代码
template <class InputIterator>
string(InputIterator first, InputIterator last)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}

2.拷贝构造函数

cpp 复制代码
// s2(s1)
string::string(const string& s)
{
	//string tmp(s._str);
	string tmp(s.begin(), s.end());
	swap(tmp);
}

这里用s1的成员变量_str构造tmp,再将tmp和s2交换swap,这样tmp中的成员变量就与s2中的成员变量交换,出函数体后tmp同时也会被析构。

3.赋值重载

cpp 复制代码
string& string::operator=(string tmp)
{
	swap(tmp);
	return *this;
}

四.代码总览

string.h

cpp 复制代码
#pragma once
#include<string.h>
#include<assert.h>
#include<iostream>

namespace my_string
{
	class string
	{
		friend std::ostream& operator<<(std::ostream& _cout, const my_string::string& s);
		friend std::istream& operator>>(std::istream& _cin, my_string::string& s);
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		string(const char* str = "")
			:_size(strlen(str))
		{                                                              
			_str = new char[_size + 1];
			_capacity = _size;
			memcpy(_str, str, _size + 1);
		}

		string(const string& s)
		{
			_str = new char[s._capacity + 1];
			memcpy(_str, s._str, s._size + 1);
			_size = s._size;
			_capacity = s._capacity;
		}

		string& operator=(const string& s)
		{
			char* tmp = new char[s._capacity + 1];
			memcpy(tmp, s._str, s._size + 1);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
			return *this;
		}

		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}

		// iterator
		iterator begin();
		iterator end();
		const_iterator begin() const;
		const_iterator end() const;

		// capacity
		size_t size() const;
		size_t capacity() const;
		bool empty() const;
		void resize(size_t n, char c = '\0');
		void reserve(size_t n);

		// access
		char& operator[](size_t index);
		const char& operator[](size_t index) const;

		// relational operators
		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);

		// modify
		void push_back(char c);
		string& operator+=(char c);
		void append(const char* str);
		string& operator+=(const char* str);
		void clear();
		void swap(string& s);
		const char* c_str() const;

		// 返回c在string中第一次出现的位置
		size_t find(char c, size_t pos = 0) const;
		// 返回子串s在string中第一次出现的位置
		size_t find(const char* s, size_t pos = 0) const;
		// 在pos位置上插入字符c/字符串str,并返回该字符的位置
		string& insert(size_t pos, char c);
		string& insert(size_t pos, const char* str);
		// 删除pos位置上的元素,并返回该元素的下一个位置
		string& erase(size_t pos, size_t len);

	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	public:
		static const size_t npos;
	};
}

string.cpp

cpp 复制代码
#include"string.h"

namespace my_string
{
	const size_t string::npos = -1;

	std::ostream& operator<<(std::ostream& _cout, const my_string::string& s)
	{
		for (int i = 0; i < s.size(); ++i)
		{
			_cout << s[i];
		}
		return _cout;
	}

	std::istream& operator>>(std::istream& _cin, my_string::string& s)
	{
		// 每次提取前需要将s中的数据清除
		s.clear();
		// 模拟string中的buff缓冲区,当所输入的字符串有效数据个数小于256时,存放到buff中
		char buff[256];
		// 使用get函数,能够输入空白字符和换行符
		char ch = _cin.get();
		size_t i = 0;
		while (ch != ' ' && ch != '\n')
		{
			buff[i++] = ch;
			ch = _cin.get();
			if (i == 255)
			{
				s += buff;
				// 重置buff
				i = 0;
			}
		}

		// buff中有剩余字符
		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}
		return _cin;
	}

	const char* string::c_str() const
	{
		return _str;
	}

	size_t string::size() const
	{
		return _size;
	}

	size_t string::capacity() const
	{
		return _capacity;
	}

	string::iterator string::begin()
	{
		return _str;
	}

	string::iterator string::end()
	{
		return _str + _size;
	}

	string::const_iterator string::begin() const
	{
		return _str;
	}

	string::const_iterator string::end() const
	{
		return _str + _size;
	}

	bool string::empty() const
	{
		return _size == 0;
	}

	void string::resize(size_t n, char c)
	{
		//if (n < _size)
		//{
		//	_str[n] = '\0';
		//	_size = n;
		//}
		//if (n > _size && n < _capacity)
		//{
		//	while (_size != n)
		//	{
		//		_str[_size++] = c;
		//	}
		//	_str[n] = '\0';
		//}
		//if (n > _capacity)
		//{
		//	(*this).reserve(n);
		//}
		if (n > _size)
		{
			if (n > _capacity)
			{
				reserve(n);
			}
			memset(_str + _size, c, n - _size);
		}
		_str[n] = '\0';
		_size = n;
	}

	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* tmp = new char[n + 1];
			memcpy(tmp, _str, _size + 1);
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}
	}

	char& string::operator[](size_t index)
	{
		return _str[index];
	}

	const char& string::operator[](size_t index) const
	{
		return _str[index];
	}

	bool string::operator<(const string& s)
	{
		size_t end1 = _size - 1;
		size_t end2 = s._size - 1;
		size_t begin1 = 0;
		size_t begin2 = 0;
		while (begin1 != end1 && begin2 != end2)
		{
			if (_str[begin1] < s._str[begin2])
			{
				return true;
			}
			else if (_str[begin1] > s._str[begin2])
			{
				return false;
			}
			begin1++;
			begin2++;
		}
		//if (begin1 == end1 && begin2 != end2)
		//{
		//	return true;
		//}
		//else
		//{
		//	return false;
		//}
		return begin1 == end1 && begin2 != end2;
	}

	bool string::operator==(const string& s)
	{
		size_t end1 = _size - 1;
		size_t end2 = s._size - 1;
		size_t begin1 = 0;
		size_t begin2 = 0;
		while (begin1 != end1 && begin2 != end2)
		{
			if (_str[begin1] != s._str[begin2])
			{
				return false;
			}
			begin1++;
			begin2++;
		}
		return begin1 == end1 && begin2 == end2;
	}

	bool string::operator<=(const string& s)
	{
		return *this < s || *this == s;
	}

	bool string::operator>(const string& s)
	{
		return !(*this <= s);
	}

	bool string::operator>=(const string& s)
	{
		return !(*this < s);
	}

	bool string::operator!=(const string& s)
	{
		return !(*this == s);
	}

	void string::push_back(char c)
	{
		if (_size == _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
			reserve(newcapacity);
		}
		_str[_size++] = c;
		_str[_size] = '\0';
	}

	void string::append(const char* str)
	{
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			size_t newcapacity = _size + len > 2 * _capacity ? _size + len : 2 * _capacity;
			reserve(newcapacity);
		}
		memcpy(_str + _size, str, len + 1);
		_size += len;
	}

	string& string::operator+=(char c)
	{
		push_back(c);
		return *this;
	}

	string& string::operator+=(const char* str)
	{
		append(str);
		return *this;
	}

	void string::clear()
	{
		_str[0] = '\0';
		_size = 0;
	}

	void string::swap(string& s)
	{
		std::swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);
	}

	size_t string::find(char c, size_t pos) const
	{
		assert(pos < _size);
		for (int i = pos; i < _size; ++i)
		{
			if (_str[i] == c)
			{
				return i;
			}
		}
		return npos;
	}

	size_t string::find(const char* s, size_t pos) const
	{
		assert(pos < _size);
		const char* tmp = strstr(_str + pos, s);
		if (tmp == nullptr)
		{
			return npos;
		}
		return tmp - _str;
	}

	string& string::insert(size_t pos, char c)
	{
		assert(pos <= _size);
		if (_size == _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
			reserve(newcapacity);
		}
		//size_t end = _size + 1;
		//while (end > pos)
		//{
		//	_str[end] = _str[end - 1];
		//	end--;
		//}
		memmove(_str + pos + 1, _str + pos, _size - pos + 1);
		_str[pos] = c;
		_size++;
		return *this;
	}

	string& string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);
		if (len == npos || len >= _size - pos)
		{
			_str[pos] = '\0';
			_size = pos;
			return *this;
		}
		memmove(_str + pos, _str + pos + len, _size + 1 - (pos + len));
		_size -= len;
		return *this;
	}

	string& string::insert(size_t pos, const char* str)
	{
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			size_t newcapacity = _size + len > 2 * _capacity ? _size + len : 2 * _capacity;
			reserve(newcapacity);
		}
		memmove(_str + pos + len, _str + pos, _size + 1 - pos);
		memcpy(_str + pos, str, len);
		_size += len;
		return *this;
	}
}

test.cpp

cpp 复制代码
#include"string.h"
using namespace std;

namespace my_string
{
	void Test_String1()
	{
		string s1("Hello world");
		cout << s1.c_str() << endl;                              
		cout << s1.size() << endl;           
		cout << s1.capacity() << endl;

		string s2 = "Hello";
		cout << s2.c_str() << endl;
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;

		string s3(s2);
		cout << s3.c_str() << endl;
		cout << s3.size() << endl;
		cout << s3.capacity() << endl;

		string s4 = s1;
		cout << s4.c_str() << endl;
		cout << s4.size() << endl;
		cout << s4.capacity() << endl;

		s4 = s2;
		cout << s4.c_str() << endl;
		cout << s4.size() << endl;
		cout << s4.capacity() << endl;
	}

	void Test_String2()
	{
		string s1 = "Hello World";
		string::iterator it = s1.begin();
		while (it != s1.end())
		{
			(*it)++;
			cout << *it << ' ';
			++it;
		}
		cout << endl;

		const string s2(s1);
		string::const_iterator cit = s2.begin();
		while (cit != s2.end())
		{
			cout << *cit << ' ';
			++cit;
		}
		cout << endl;

		for (char e : s2)
		{
			cout << e << ' ';
		}
	}

	void Test_String3()
	{
		string s1 = "Hello World";
		s1.reserve(100);
		cout << s1.c_str() << endl;
		cout << s1.size() << endl;
		cout << s1.capacity() << endl;

		cout << s1[0] << endl;
		++s1[0];
		cout << s1.c_str() << endl;

		string s2 = "Hello";
		s2.resize(2);
		cout << s2.c_str() << endl;
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;

		s2.resize(4);
		cout << s2.c_str() << endl;
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;

		s2.resize(10);
		cout << s2.c_str() << endl;
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;

		//std::string s2 = "Hello";
		//s2.resize(2);
		//cout << s2.c_str() << endl;
		//cout << s2.size() << endl;
		//cout << s2.capacity() << endl;

		//s2.resize(4);
		//cout << s2.c_str() << endl;
		//cout << s2.size() << endl;
		//cout << s2.capacity() << endl;

		//s2.resize(10);
		//cout << s2.c_str() << endl;
		//cout << s2.size() << endl;
		//cout << s2.capacity() << endl;

	}

	void Test_String4()
	{
		string s1 = "Hello World";
		string s2 = "Hello";
		cout << (s1 < s2) << endl;
		cout << (s2 < s1) << endl;

		string s3(s1);
		cout << (s1 == s3) << endl;
		cout << (s2 == s3) << endl;
		cout << (s1 >= s2) << endl;
		cout << (s1 != s2) << endl;
		cout << (s2 <= s1) << endl;

	}

	void Test_String5()
	{
		string s1("Hello");
		s1.push_back('x');
		s1 += 'x';
		s1 += "xxxxx";
		cout << s1.c_str() << endl;
		cout << s1.size() << endl;
		cout << s1.capacity() << endl;

		const char* p = "Worldxxxxxxx";
		string s3 = "Hello ";
		cout << s3.c_str() << endl;
		cout << s3.size() << endl;
		cout << s3.capacity() << endl;
		s3.append(p);
		cout << s3.c_str() << endl;
		cout << s3.size() << endl;
		cout << s3.capacity() << endl;

		string s4 = "Hello";
		string s5 = "Worldxxxxxxxx";
		cout << s4.c_str() << endl;
		cout << s4.size() << endl;
		cout << s4.capacity() << endl;
		cout << s5.c_str() << endl;
		cout << s5.size() << endl;
		cout << s5.capacity() << endl;
		s4.swap(s5);
		cout << s4.c_str() << endl;
		cout << s4.size() << endl;
		cout << s4.capacity() << endl;
		cout << s5.c_str() << endl;
		cout << s5.size() << endl;
		cout << s5.capacity() << endl;
	}

	void Test_String6()
	{
		string s1 = "Hello ";
		cout << s1.find('e') << endl;
		s1 += "World";
		cout << s1.find("Wor") << endl;
		cout << s1.c_str() << endl;
		cout << s1.size() << endl;
		cout << s1.capacity() << endl;
		// "Hello World"
		s1.insert(0, 'x');
		cout << s1.c_str() << endl;
		cout << s1.size() << endl;
		cout << s1.capacity() << endl;

		string s2 = "Hello World";
		//s2.erase(1, 2);
		s2.insert(11, "xxx");
		cout << s2.c_str() << endl;
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;
	}

	void Test_String7()
	{
		string s1 = "Hello World";
		cout << s1 << endl;
		cin >> s1;
		cout << s1 << endl;
	}

}

int main()
{
	my_string::Test_String2();
	return 0;
}
相关推荐
码农新猿类4 分钟前
服务器本地搭建
linux·网络·c++
Hanson Huang11 分钟前
【数据结构】堆排序详细图解
java·数据结构·排序算法·堆排序
Susea&11 分钟前
数据结构初阶:队列
c语言·开发语言·数据结构
慕容静漪14 分钟前
如何本地安装Python Flask并结合内网穿透实现远程开发
开发语言·后端·golang
ErizJ16 分钟前
Golang|锁相关
开发语言·后端·golang
软件测试曦曦16 分钟前
16:00开始面试,16:08就出来了,问的问题有点变态。。。
自动化测试·软件测试·功能测试·程序人生·面试·职场和发展
GOTXX20 分钟前
【Qt】Qt Creator开发基础:项目创建、界面解析与核心概念入门
开发语言·数据库·c++·qt·图形渲染·图形化界面·qt新手入门
搬砖工程师Cola29 分钟前
<C#>在 .NET 开发中,依赖注入, 注册一个接口的多个实现
开发语言·c#·.net
巨龙之路37 分钟前
Lua中的元表
java·开发语言·lua
徐行1101 小时前
C++核心机制-this 指针传递与内存布局分析
开发语言·c++