STL简介&string相关知识点

一、STL

STL(standard template libaray-标准模板库):是********C++****标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架****。

二、string类基本操作

string类文档介绍

cplusplus.com/reference/string/string/?kw=string

复制代码
void test_string1()
{
	string s1;
	string s2("hello world");
	string s3(s2);
	string s4(s2, 1, 5);
	string s5(s2, 1, 60);
	string s6(s2, 1);
	const char* str = "hello world";
	string s7(str, 5);
	string s8(100, '#');

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;
	cout << s6 << endl;
	cout << s7 << endl;
	cout << s8 << endl;
}
复制代码
void test_string2()
{
	string s1("hello world");

	//遍历+修改
	//下标+[]
	s1[0]++; 
	cout << s1 << endl;
	//s1的每个字符都++
	for (size_t i = 0; i < s1.size(); i++)
	{
		s1[i]++;
	}
	cout << s1 << endl;

	//迭代器 [begin(),end()] s1的每个字符都--
	//迭代器是所有容器主流的遍历+修改方式
    string::iterator it1 = s1.begin();
	while (it1 != s1.end())
	{
		(*it1)--;
		++it1;
	}
	cout << s1 << endl;

	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);

	vector<int>::iterator it2 = v.begin();
	while (it2 != v.end())
	{
		cout << *it2 << " ";
		++it2;
	}
	cout << endl;

	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);

	list<int>::iterator it3 = lt.begin();
	while (it3 != lt.end())
	{
		cout << *it3 << " ";
		++it3;
	}
	cout << endl;

	//范围for
	auto x = 10;
	auto y = 10.1;
	cout << x << endl;
	cout << y << endl;

	int& z = x;
	auto& m = z;
	m++;
	auto p1 = &x;
	//只能是指针
	auto* p2 = &x;

	//自动取容器数据赋值给e
	//自动判断结束
	//自动迭代
	//本质底层也会替换成迭代器,auto e = *迭代器
	for (char& e : s1)
	{
		e--;
	}
	for (auto e : s1)
	{
		cout << e << " ";
	}
	cout << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	int array[] = { 1,2,3,4,5 };
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
	{
		cout << array[i] << endl;
	}
	for (auto e : array)
	{
		cout << e << " ";
	}
	cout << endl;
}

void test_string3()
{
	string s1("hello world");
	const string s2("hello world");

	string::iterator it1 = s1.begin();
	while (it1 != s1.end())
	{
		(*it1)--;
		++it1;
	}
	cout << s1 << endl;

	string::const_iterator it2 = s2.cbegin();
	while (it1 != s2.cend())
	{
		//(*it2)--;不能修改
		++it2;
	}
	cout << s2 << endl;

	string::reverse_iterator it3 = s1.rbegin();
	while (it3 != s1.rend())
	{
		cout << *it3 << " ";
		++it3;
	}
	cout << endl;

	string::const_reverse_iterator it4 = s2.rbegin();
	while (it4 != s2.rend())
	{
		cout << *it4 << " ";
		++it4;
	}
	cout << endl;

	for (auto ch : s2)
	{
		cout << ch << " ";
	}
	cout << endl;
}

void test_string4()
{
	string s1("123456");
	cout << s1.max_size() << endl;

	//均不包含\0
	cout << s1.capacity() << endl;
	cout << s1.size() << endl;

	string s2;
	size_t old = s1.capacity();
	cout << "capacity:" << old << endl;
	for (size_t i = 0; i < 100; i++)
	{
		s2.push_back('x');
		if (s2.capacity() != old)
		{
			cout << "capacity:" << s2.capacity() << endl;
			old = s2.capacity();
		}
	}
	cout << s1 << endl;
	s1.clear();
	cout << s1 << endl;

	cout << "size:" << s2.size() << endl;
	cout << "capacity:" << s2.capacity() << endl;
	//s2.clear();
	for (size_t i = 0; i < 100; i++)
	{
		s2.pop_back();
	}
	s2.shrink_to_fit();
	cout << "size:" << s2.size() << endl;
	cout << "capacity:" << s2.capacity() << endl;
}

void test_string5()
{
	string s1("123456");
	cout << "size:" << s1.size() << endl;
	cout << "capacity:" << s1.capacity() << endl;

	//确定知道需要多少空间,提前开好,避免扩容,提高效率
	s1.reserve(100);
	cout << "size:" << s1.size() << endl;
	cout << "capacity:" << s1.capacity() << endl << endl;

	string s2("123456");
	cout << "size:" << s2.size() << endl;
	cout << "capacity:" << s2.capacity() << endl;

	//插入数据,让size到n个
	//n > capacity > size;
	s2.resize(20,'x');
	cout << s2 << endl;
	cout << "size:" << s2.size() << endl;
	cout << "capacity:" << s2.capacity() << endl;

	//capacity > n > size;
	s2.resize(25, 'x');
	cout << s2 << endl;
	cout << "size:" << s2.size() << endl;
	cout << "capacity:" << s2.capacity() << endl;

	//删除数据
	//n < size
	s2.resize(5);
	cout << s2 << endl;
	cout << "size:" << s2.size() << endl;
	cout << "capacity:" << s2.capacity() << endl;
}

void test_string6()
{
	string s1("123456");
	s1[0]++;
	cout << s1 << endl;

	//越界检查,断言
	s1[15];//s1.operator[](15);
	s1.at(0)--;
	cout << s1 << endl;
	//越界抛异常
	s1.at(15);
}

void test_string7()
{
	string s1("hello world");
	//s1.push_back(' ');
	//s1.append("hello bit");
	//s1.append(10, 'x');
	s1 += ' ';
	s1 += "hello world";
	cout << s1 << endl;

	s1 = 'x';
	cout << s1 << endl;

	s1.assign(10, 'y');
	cout << s1 << endl;

	//insert 谨慎使用,涉及底层数据的挪动,效率低下
	string s2("hello world");
	s2.insert(0, "yyy");
	cout << s2 << endl;

	s2.insert(0,1,'!');
	cout << s2 << endl;

	s2.insert(s2.begin(),'!');
	cout << s2 << endl;

	string s3("hello world");
	s3.erase(5, 1);
	cout << s3 << endl;

	string s4("hello world");
	cout << s4 << endl;
	s4.replace(5, 1, "#");
	cout << s4 << endl;

	//所有空格替换为%%
	string s5("hello  world  hello  world");
	//size_t pos = s5.find(' ');
	//while (pos != string::npos)
	//{
	//	s5.replace(pos, 1, "%%");
	//	pos = s5.find(' ', pos + 2);
	//}
	//cout << s5 << endl;

	string s6;
	s6.reserve(s5.size());
	for (auto ch : s5)
	{
		if (ch == ' ')
		{
			s6 += "%%";
		}
		else
		{
			s6 += ch;
		}
		cout << s6 << endl;
	}
}

void test_string8()
{
	string filename("test.cpp");
	FILE* fout = fopen(filename.c_str(), "r");
	if (fout == nullptr)
	{
		cout << "fopen error" << endl;
		return;
	}
	
	char ch = fgetc(fout);
	while (ch != EOF)
	{
		cout << ch;
		ch = fgetc(fout);
	}
}

string findsuffix(const string& filename)
{
	size_t i = filename.find('.');
	if (i != string::npos)
	{
		return filename.substr(i);
	}
	else
	{
		//string empty;
		//return empty;
		//return "";
		return string();
	}
}

vector<string> split_url(const string& url)
{
	vector<string> v;
	size_t i1 = url.find(":");
	if (i1 != string::npos)
	{
		cout << url.substr(0, i1) << endl;
	}

	size_t i2 = i1 + 3;
	size_t i3 = url.find('/', i2);
	if (i3 != string::npos)
	{
		v.push_back(url.substr(i2, i3 - i2));
		v.push_back(url.substr(i3 + 1));
	}
	return v;
}


void test_string9()
{
	string filename1("test.cpp");
	string filename2("test.c");
	string filename3("test");
	string filename4("test.cpp.tar");

	cout << findsuffix(filename1) << endl;
	cout << findsuffix(filename2) << endl;
	cout << findsuffix(filename3) << endl;
	cout << findsuffix(filename4) << endl;

	string url1 = "http://legacy.cplusplus.com/refernce/string/string/";
	string url2 = "ftp://legacy.cplusplus.com/refernce/string/string/";

	//split_url(url1);
	//split_url(url2);

	vector<string> ret = split_url(url1);
}

void test_string10()
{
	std::string str("please,replace the vowels in this sentence by asterisks");
	std::size_t found = str.find_first_not_of("aeiou");
	while (found != std::string::npos)
	{
		str[found] = '*';
		found = str.find_first_not_of("aeiou", found + 1);
	}
	std::cout << str << '\n';

	string s1("xxx");
	string s2("xxx11");
	const char* str = "232222";

	s1 == s2;
	s1 == str;
	str == s1;
}

int main()
{
	//test_string1();
	//test_string2();
	//test_string3();
	//test_string4();
	//test_string5();
	//try
	//{
	//	test_string6();
	//}
	//catch (const exception& e)
	//{
	//	cout << e.what() << endl;
	//}
	//try
	//{
	//	test_string7();
	//}
	//catch (const exception& e)
	//{
	//	cout << e.what() << endl;
	//}
	//test_string8();
	//test_string9();
	//test_string10();
	return 0;
}

三、string模拟实现

复制代码
//string.h

#pragma once
#include<string.h>
#include<assert.h>
#include<iostream>

using namespace std;

namespace bit
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin();
	    iterator end();

		const_iterator begin() const;
		const_iterator end() const;

		//string();
		string(const char* str="");
		const char* c_str() const;
		~string();

		string(const string& s);
		string& operator=(const string& s);

		size_t size() const;
		char& operator[](size_t i);
		const char& operator[](size_t i) const;

		void reserve(size_t n);
		void push_back(char ch);
		void pop_back();
		void append(const char* str);
		string& operator+=(char ch);
		string& operator+=(const char* str);

		string& insert(size_t pos, char ch);
		string& insert(size_t pos, const char* str);
		string& earse(size_t pos=0, size_t len = npos);

		size_t find(char ch, size_t pos = 0) const;
		size_t find(const char* str, size_t pos = 0) const;

		void clear();
		string substr(size_t pos, size_t len = npos) const;

		bool operator<(const string& s)const;
		bool operator<=(const string& s)const;
		bool operator>(const string& s)const;
		bool operator>=(const string& s)const;
		bool operator==(const string& s)const;
		bool operator!=(const string& s)const;

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

	ostream& operator<<(ostream& out, const string& s);
	istream& operator>>(istream& in,string& s);
	istream& getline(istream& in, string& s, char delim = '\n');
}

//string.cpp

#define _CRT_SECURE_NO_WARNINGS
#include"string.h"

namespace bit
{
	const size_t string::npos = -1;
	//string::string()
	//	:_str(new char[1]{'\0'})
	//	,_size(0)
	//	,_capacity(0)
	//{}

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

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

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

	string& string::operator=(const string& s)
	{
		if (this != &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;
	}

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

	size_t string::size() const
	{
		return _size;
	}
	char& string::operator[](size_t i)
	{
		assert(i < _size);
		return _str[i];
	}
	const char& string::operator[](size_t i) const
	{
		assert(i < _size);
		return _str[i];
	}

	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;
	}

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


	void string::push_back(char ch)
	{
		if (_size >= _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
			reserve(newcapacity);
		}

		_str[_size] = ch;
		++_size;
		_str[_size] = '\0';
	}

	void string::pop_back()
	{
		assert(_size > 0);
		--_size;
		_str[_size] = '\0';
	}

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

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

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

	string& string::insert(size_t pos, char ch)
	{
		assert(pos <= _size);

		if (_size >= _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
			reserve(newcapacity);
		}

		int end = _size;
		while (end >= (int)pos)
		{
			_str[end + 1] = _str[end];
			--end;
		}
		_str[pos] = ch;
		++_size;

		return *this;
	}


	string& string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);

		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			size_t newcapacity = 2 * _capacity > _size + len ? 2 * _capacity : _size + len;
			reserve(newcapacity);
		}

		int end = _size+len;
		while (end > pos+len-1)
		{
			_str[end] = _str[end-len];
			--end;
		}

		for (size_t i = 0; i < len; i++)
		{
			_str[pos + i] = str[i];
		}
		_size += len;

		return *this;
	}

	string& string::earse(size_t pos, size_t len)
	{
		assert(pos < _size);

		//要删除的数据,大于pos后面的字符
		//pos后面全删
		if (len == npos || len >= (_size - pos))
		{
			_size = pos;
			_str[_size] = '\0';
		}
		else
		{
			size_t i = pos + len;
			memmove(_str + pos, _str + i, _size + 1 - i);
			_size -= len;
		}

		return *this;
	}

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

	size_t string::find(const char* str, size_t pos) const
	{
		const char* p1 = strstr(_str + pos, str);
		if (p1 == nullptr)
		{
			return npos;
		}
		else
		{
			return p1 - _str;
		}
	}

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


	string string::substr(size_t pos, size_t len) const
	{
		if (len == npos || len >= _size - pos)
		{
			len = _size - pos;
		}
		string ret;
		ret.reserve(len);

		for (size_t i = 0; i < len; i++)
		{
			ret += _str[pos + i];
		}
		return ret;
	}

	bool string::operator<(const string& s)const
	{
		size_t i1 = 0, i2 = 0;
		while (i1 < _size && i2 < s._size)
		{
			if (_str[i1] < s[i2])
			{
				return true;
			}
			else if (_str[i1] > s[i2])
			{
				return false;
			}
			else
			{
				++i1;
				++i2;
			}
		}
		return i2 < s._size;
	}

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

	}

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

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

	bool string::operator==(const string& s)const
	{
		size_t i1 = 0, i2 = 0;
		while (i1 < _size && i2 < s._size)
		{
			if (_str[i1] != s[i2])
			{
				return false;
			}
			else
			{
				++i1;
				++i2;
			}
		}
		return i1 == _size && i2 == s._size;
	}

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

	ostream& operator<<(ostream& out, const string& s)
	{
		//out << s.c_str();
		for (size_t i = 0; i < s.size(); i++)
		{
			out << s[i];
		}
		return out;
	}

	istream& operator>>(istream& in, string& s)
	{
		s.clear();

		char buff[128];
		int i = 0;
		char ch = in.get();
		while (ch != ' ' & ch != '\n')
		{
			buff[i++] = ch;
			if (i == 127)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}
			ch = in.get();

			if (i > 0)
			{
				buff[i] = '\0';
				s += buff;
			}
		}
		return in;
	}

	istream& getline(istream& in, string& s, char delim = '\n')
	{
		s.clear();

		char buff[128];
		int i = 0;
		char ch = in.get();
		while (ch != delim)
		{
			buff[i++] = ch;
			if (i == 127)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}
			ch = in.get();

			if (i > 0)
			{
				buff[i] = '\0';
				s += buff;
			}
		}
		return in;

	}
}

//test.cpp

#include"string.h"
namespace bit
{
	void test_string1()
	{
		string s1;
		cout << s1.c_str() << endl;

		string s2("hello world");
		cout << s2.c_str() << endl;

		for (size_t i = 0; i < s2.size(); ++i)
		{
			s2[i]++;
		}
		cout << s2.c_str() << endl;

		for (auto ch : s2)
		{
			cout << ch << " ";
		}
		cout << endl;
		string::iterator it1 = s1.begin();
		while (it1 != s1.end())
		{
			cout << *it1 << " ";
		}
		cout << endl;
	}

	void test_string2()
	{
		const string s1("hello world");
		string::const_iterator it1 = s1.begin();
		while (it1 != s1.end())
		{
			cout << *it1 << " ";
			++it1;
		}
		cout << endl;
	}

	void test_string3()
	{
		string s1("hello world");
		s1.push_back('x');
		cout << s1.c_str() << endl;

		s1.append("hello hehe");
		cout << s1.c_str() << endl;

		s1 += 'y';
		s1 += "zzzzzz";
		cout << s1.c_str() << endl;

		string s2("hello world");
		s2 += '\0';
		s2 += '\0';
		s2 += '!';
		cout << s2 << endl;
		cout << s2.c_str() << endl;

		s2 += "yyyyyyyyyyyyy";
		cout << s2 << endl;
		cout << s2.c_str() << endl;
	}


	void test_string4()
	{
		string s1("hello world");
		s1.insert(6, 'x');
		cout << s1 << endl;

		s1.insert(0, 'x');
		cout << s1 << endl << endl;

		string s2("hello world");
		s2.insert(6, 'xxxx');
		cout << s2 << endl;
		s2.insert(0, 'xxxx');
		cout << s2 << endl<<endl;

		string s3("hello world");
		s3.earse(7);
		cout << s3 << endl;

		string s4("hello world");
		s4.earse(7,100);
		cout << s3 << endl;

		string s5("hello world");
		s5.earse(7,3);
		cout << s5 << endl;


		s5.pop_back();
		s5.pop_back();
		s5.pop_back();
		cout << s5 << endl;
	}
	void split_url(const string& url)
	{
		size_t i1 = url.find(":");
		if (i1 != string::npos)
		{
			cout << url.substr(0, i1) << endl;
		}

		size_t i2 = i1 + 3;
		size_t i3 = url.find('/', i2);
		if (i3 != string::npos)
		{
			cout<<url.substr(i2, i3 - i2)<<endl;
			cout<<url.substr(i3 + 1)<<endl;
		}
		cout << endl;
	}
	void test_string5()
	{
		string url1 = "http://legacy.cplusplus.com/refernce/string/string/";
		string url2 = "ftp://legacy.cplusplus.com/refernce/string/string/";

		split_url(url1);
		split_url(url2);
	}

	void test_string6()
	{
		string s1("hello"), s2("hello");
		string s3("hellox"), s4("hello");
		string s5("hello"), s6("hellox");

		cout << (s1 < s2) << endl;
		cout << (s3 < s4) << endl;
		cout << (s5 < s6) << endl;
	}

	void test_string7()
	{
		string s1("hello"), s2("hello");
		cout << s1 << s2 << endl;

		cin >> s1 >> s2;
		cout << s1 <<" "<< s2 << endl;

		string line;
		getline(cin, line, '!');
		cout << line << endl;

		cin >> s1;
		cout << s1 << endl;
		cout << s1.size() << endl;
	}

	void test_string8()
	{
		string s1("hello"), s2("worldxxxxx");
		string s3(s1);
		cout << s1 << endl;
		cout << s3 << endl;

		s1[0] = 'x';
		cout << s1 << endl;
		cout << s3 << endl;

		s1 = s2;
		cout << s1 << endl;
		cout << s2 << endl;
	}


}

int main()
{
	//bit::test_string1();
	//bit::test_string2();
	//bit::test_string3();
	//bit::test_string4(); 
	//bit::test_string5();
	//bit::test_string6();
	//bit::test_string7();
	//bit::test_string8();
	//cout << typeid(bit::string::iterator).name() << endl;
	//cout << typeid(std::string::iterator).name() << endl;

	return 0;
}
相关推荐
坤坤子吖2 小时前
Linux 线程同步与互斥——互斥锁
linux·服务器·c++·笔记·学习
TDTC_XQ2 小时前
Linux网络编程accept的讲解
linux·服务器·c++
半摆烂日常2 小时前
手机表单的左滑操作:触摸事件的处理细节
大数据·开发语言·人工智能·智能手机·https·c#
星夜离尘562 小时前
MATLAB滑动RMS如何接报警:窗口未满和缺样不能当成正常
开发语言·matlab
开开心心就好2 小时前
白天晚上自动调蓝光,护眼工具亮度可调
服务器·开发语言·算法·pdf·ocr·intellij-idea·idea
张张123y2 小时前
后端第十一课:RAG 落地实战(从 0 到 1 接上私有知识库,并设计一个好用的 RAG)
开发语言·人工智能·python·机器学习·fastapi·rag
梅梅绵绵冰2 小时前
JVM虚拟机
java·开发语言·jvm
FlightYe2 小时前
音视频修炼之容器与协议(一):MP4和MOV的box剖析
android·linux·c++·ffmpeg·音视频
Shaoshing3 小时前
消息顺序
java·开发语言