13天带你了解C++ ---DAY9 C++之string

目录

1.string容器

2.构造函数和析构函数的相关操作

3.迭代器

4.容量相关

5.元素访问相关

6.元素遍历相关

7.字符串操作

7.1   operator+=

7.2   append

7.3 push_back

7.4 insert && erase

7.5swap

8.string模拟实现


1.string容器

string容器是C++标准模板库提供的专门用来存储操作字符串的容器。下边介绍了string容器的一些基本操作,均参考于C++官方文档

2.构造函数和析构函数的相关操作

#include<iostream>
#include<string>
using namespace std;
int main() {
	const char* arr = "world";
	 string s0("hello");
	 string s1(s0);
	 string s2(s0,0,2);
	 string s3(10,'a');
	 string s4(arr, 3);
	 string s5(s0.begin(), s0.begin() + 3);
     ~string();
	return 0;
}

3.迭代器

begin() 和end()

        begin()和end()目前可以看成两个指针,begin()指向字符串的头部,end()指向字符串尾部的下一个位置,即 \0 的位置。我们可以使用begin()和end()进行遍历操作和获取位置操作。

        

rbegin(),rend()

        rbegin()和rend()正好与上边的begin() 和end()相反,rbegin()指向字符串的尾部,即 \0 的位置,rbegin()指向字符串头部。

#include<iostream>
#include<string>
using namespace std;
int main() {
	 string s0("hello world!");
	 string s1(s0.begin(), s0.end());
     string s2(s0.rbegin(), s0.rend());
	return 0;
}

4.容量相关

size:字符串中有效元素的个数,不包括 \0
capcity:字符串底层顺序表的空间的大小



size_t size() const;

 此方法可以求字符串的长度,和C语言中length()方法相似

size_t capacity() const;

        此方法可以查看顺序表实际上内部容量,因为string是可以自己扩容的,所以他的容量一定比存储的字符串多,当拷贝的字符串大于capacity时,String底层动态扩容。

void resize (size_t n); void resize (size_t n, char c);

        此函数作用是更新有效元素个数,当n<size,则将字符串阶段只保留前n个元素,不改变capcity,当n>size && n<capcity  ,则在原字符串后填充参数c,直到等于n。当n>capcity,则编译器会先申请一块大于n的空间,然后将原来字符串拷贝进去,使用参数c填充,再销毁原空间。

void reserve (size_t n );   

        此方法可以调整顺序表的容量大小,不会修改有效元素个数,此函数作用是将字符串容量变为n个,当n大于capcity时正常扩容;  当n小于原来capcity且大于有效元素个数时(size),则缩减capcity;  当n小于有效元素个数时,编译器忽略这条指令。

void clear(); 

        清空有效元素,但是不改变capcity大小

bool empty() const;

        检测这个字符串是否为空,空则返回true,非空则返回false;

5.元素访问相关

operator[]

char& operator[] (size_t pos);     const char& operator[] (size_t pos) const;

string底层就是一个字符数组,所以可以像访问数组一样使用[]访问字符串。

at

char& at (size_t pos);                 const char& at (size_t pos) const;

at和[]在使用效果方面完全一致,使用方法举例  cout << str.at(i);

区别:[]在越界访问时会触发assert断言,at会抛出异常,可供用户捕获。

6.元素遍历相关

1.for循环

2.范围for

3.迭代器

#include<iostream>
#include<string>
using namespace std;
int main() {
	 string s0("hello world!");
	 //for循环
	 for (int i = 0; i < s0.size(); i++) {
		 cout << s0[i];
	 }
	 cout << endl;

	 //范围for
	 for (auto e : s0) {
		 cout << e;
	 }
	 cout << endl;

	 //迭代器
	 string::iterator it = s0.begin();
	 while (it !=s0.end()) {
		 cout << *it;
		 it++;
	 }
	 cout << endl;
	 
   	 return 0;
}

结论:不同的方法都可以达到遍历效果。

7.字符串操作

7.1   operator+=

#include<iostream>
#include<string>
using namespace std;
int main() {
	 string s0("hello world!");
	 string s1("aa");
	 const char* p = "***";
	 s1 += s0;
	 s1 += p;
	 s1 += '+';
	 cout << s1<<endl;
   	 return 0;
}

7.2   append

#include<iostream>
#include<string>
using namespace std;

int main() {
	string s1("hello world!");
	const char* s2 = "bye";
	s1.append( s2, 10);
	s1.append(3,'c');
	s1.append("hello");
	cout << s1 << endl;
	return 0;
}

7.3 push_back

#include<iostream>
#include<string>
using namespace std;

int main() {
	string s1("hello world!");
	const char* s2 = "bye";
	s1.push_back('c');
	cout << s1 << endl;
	return 0;
}

7.4 insert && erase

#include<iostream>
#include<string>
using namespace std;

int main() {
	string s1("hello world!");
	s1.insert(6, "!!! ", 4);
	s1.erase(6,4);
	return 0;
}

7.5swap

#include<iostream>
#include<string>
using namespace std;

int main() {
	string s1("hello world!");
	string s2;
	s2.swap(s1);
	return 0;
}

8.string模拟实现

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;
namespace str {
	class string {
	public:
		typedef char* iterator;
		typedef char* reverse_iterator;


		//构造函数
	
		string(const char* a="") {
			if (a == nullptr) {
				assert(false);
			}
			_size = strlen(a);
			_str = new char[_size + 1];
			strcpy(_str, a);
			_capcity = _size;
		}

		string(size_t n,char s) {
			_str = new char[n+1];
			memset(_str,s,n);
			*(_str + n) = '\0';
			_size = n;
			_capcity = n;
		}

		string(const string& s)
				:_str(nullptr)
		{
			/*
			 浅拷贝,两个对象地址相同,不安全
			 _size = s._size;
			 _capcity = s._capcity;
			 _str=s._str;
			*/
			///解决方式:深拷贝//
			string tmp(s._str);
			this->swap(tmp);

		}

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


		//赋值运算符重载
		string& operator=(string s) {
			swap(s);
			return *this;
		}

		//迭代器
		iterator begin() {
			return this->_str;
		}
		iterator end() {
			return _str + _size;
		}
		reverse_iterator rbegin() {
			return _str+_size;
		}
		reverse_iterator rend() {
			return _str;
		}

		//capcity相关
		size_t size()const {
			return _size;
		}
		size_t length()const {
			return _size;
		}
		size_t capcity()const {
			return _capcity;
		}
		bool empty()const {
			if (_size == 0) {
				return true;
			}
			return false;
		}
		void resize(size_t newsize,char s) {
			size_t oldsize = size();
			if (newsize < 0) {
				assert(0);
			}
			if (newsize <= oldsize) {
				_str[newsize] = '\0';
			}
			else {
				if ( newsize > _capcity) {
					reserve(newsize);			
				}
				append(newsize - oldsize, s);
			}
			_size = newsize;
		}

		void reserve(size_t newsize) {
			if (newsize > _capcity) {
				char* tem = new char[newsize+1];
				strcpy(tem,_str);
				delete[] _str;
				_str=tem;
				_capcity = newsize;
			}
			
		}
		//访问相关

		//modify相关  
		string& append(size_t n,char a) {
			if (n + _size > _capcity) {
				reserve(n + _size);
			}
				memset(_str+_size, a, n);
				_str[_size + n] = '\0';
				_size = n + _size;
				return *this;
		}
		string& append(const char* str) {
			size_t len=strlen(str);
			if (len + _size > _capcity) {
				reserve(len + _size);
			}
			strcat(_str,str);
			_size = len + _size;
			return *this;
		}
		//Element acess

		char& operator[](size_t index) {
			assert(index < _size);
			return _str[index];
		}
		const char& operator[](size_t index)const {
			assert(index < _size);
			return _str[index];
		}


		/modify
		void push_back(char s) {
			append(1,s);
		}
		string& operator+=(const string& s) {
			append(s._str);
			return *this;
		}

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

		
		//insert erase  swap
		string& insert(size_t pos,const string& s) {
			size_t len = strlen(s._str);
			char* p=s._str;
			if (len + _size > _capcity) {
				reserve(len+_size);
			}
			for (int i = _size+len; i>=pos; i--) {
				_str[i+len] = _str[i];
			}
			while (*p != '\0') {
				_str[pos] = *p;
				p++;
			}
			return *this;
		} 
		string& earse(size_t pos,size_t n) {
			assert(pos<_size);
			while (_str[pos] != '\0') {
				_str[pos] = _str[pos + 1];
			}
			return *this;
		}


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

		size_t rfind(char ch, size_t pos = npos) {
			if (pos == npos) {
				pos = _size - 1;
			}
			for (int i = _size-1; i >=0; i--) {
				if (ch == _str[i]) {
					return i;
				}
			}
			return npos;
		}

		string substr(size_t pos = 0, size_t n =npos) {
			if (n == npos) {
				n = _size - pos;
			}
			char* tmp = new char[n + 1];
			strncpy(tmp, _str + pos, n);
			tmp[n] = '\0';

			string strret(tmp);
			delete[] tmp;
			return strret;
		}
		void swap(string& s) {
			std::swap(_str,s._str);
			std::swap(_size, s._size);
			std::swap(_capcity, s._capcity);
		}
		friend ostream& operator<<(ostream& _cout, const string& s)
		{
			_cout << s._str;
			return _cout;
		}


	private:
		char* _str;
		size_t _size;
		size_t _capcity;
		static size_t npos;
	};
	size_t string::npos = -1;
	void TestString1()
	{
		str::string s1;
		str::string s2("hello");
		str::string s3(s2);
		str::string s4(10, 'A');
		cout << s4.size() << std::endl;


		cout << s2 << endl;
		for (auto e : s3)
			cout << e;
		cout << endl;

		auto it = s4.begin();
		while (it != s4.end())
		{
			cout << *it;
			++it;
		}
		cout << endl;
	}

	void TestString2()
	{
		str::string s("hello");
		s.resize(10, '!');
		std::cout << s << std::endl;

		s.resize(7, '!');
	}

	void TestString3()
	{
		str::string s("abc.cpp");
		str::string ret = s.substr(s.rfind('.') + 1);
		cout << ret << endl;
	}
}


int main() {
	str::TestString1();
	str::TestString2();
	str::TestString3();
	return 0;
}


版权声明:本文为m0_61720091原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。