Common operations in string class

Keywords: C Back-end

1. Basic concept of string container

c language style string is too complex and difficult to master, which is not suitable for the development of large programs

2. Common operations of string container string constructor

string();//Create an empty string, for example: string str;
string(const string &str)//Use a string object to initialize another string object
string(const char*str)//Initialize with string s
string (int n,char c)//Initialize with n strings c

Let's experiment

1.string ()

#include<iostream>
using namespace std;
#include<string>
 int main()
{
	string s;
	cout << s;
}

Operation results:

We can find that the string is empty

2.string (const string&str);

#include<iostream>
using namespace std;
int main()
{
	string s = "abvede";
	string s1(s);
	cout << s1;
}

Operation results:

3.string (const char*str);

#include<iostream>
using namespace std;
int main()
{
	string s1("abdedf");
	cout << s1;
}

  Operation results:

4.string (int n,char c)

#include<iostream>
using namespace std;
int main()
{
	string s1(3, 'a');
	cout << s1;
}

 

  3. Basic assignment operation of string class

string &operator=(const char*s)//Assigns a char * type string to the current string
string &operator=(const string &s)Put string s Assign to current string
string& operator=(char c)Assigns a character to the current string
string &assign (const char*s)Put string s Assign to current string
string &assign(const char*s,int n)Put string s Before n Characters are assigned to the current string
string &assign(const string&s)Put string s Assign to current string
string &assign(int n,char c)use n Characters are assigned to the current string
string &assign(const string &s,int start,int n)take s from start start n Characters are assigned to the string

Example: String & operator = (const char * s)

#include<iostream>
using namespace std;
int main()
{
	string s = "aveddfhf";
	cout << s << endl;
	return 0;
}

Operation results:

 2.string &operator=(const string&s)

#include<iostream>
using namespace std;
int main()
{
	string s = "aveddfhf";
	string s1;
	s1 = s;
	cout << s1<< endl;
	return 0;
}

Operation results:

3.string&operator=(char c);

#include<iostream>
using namespace std;
int main()
{
	string s1;
	s1 = 'a';
	cout << s1 << endl;
	return 0;
}

 

4.string  &assign(const char*s)

#include<iostream>
using namespace std;
int main()
{
	string s1;
	s1.assign("djfgfjdfgh");
	cout << s1 << endl;
}

Operation results:

string access character operation and traversal method

1.

//string access character operation
//char&operator[](int n); Take characters by []
//char&at(int n); Get characters by at

  Example:

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

Operation results:

  Obtain by at:

#include<iostream>
using namespace std;
int main()
{
	string str = "hello world";
	for (int i = 0; i < str.size(); i++) {
		cout << str.at(i) << endl;
	}
}

Operation results:

We can find that there is no difference between the two running results. Is there any difference between the two methods?

Difference between [] and at:

[] access cross-border program will directly hang up, while at access cross-border will throw exception out_of_range

#include<iostream>
using namespace std;
int main()
{
	string str = "hello world";
	cout << str[100] << endl;
}

Operation results:

  

We can see that the program crashes directly

Obtain by at:

#include<iostream>
using namespace std;
int main()
{
	string str = "hello world";

	try {
		cout << str.at(100) << endl;
	}
	catch (out_of_range& e) {
		cout << e.what() << endl;
	}

}

Operation results:

How to access the last element or the first element in a string

Access the first element:

1. Adoption []

2. Adoption

3. Pass the method object. front() of the member function;

4. Through iterator

Accessing the last element is similar to accessing the first element

1. Adoption []

2. Adoption

3. Method through member function

4. Through iterator

  Example:

#include<iostream>
using namespace std;
int main()
{
	string str = "hello world";
	cout << str[0] << endl;//By []
	cout << str.at(0) << endl;//Through at
	cout << str.front() << endl;//By member function
	cout << *str.begin() << endl;//Through iterator
	return 0;
}

Operation results:

Access the last element:

#include<iostream>
using namespace std;
int main()
{
	string str = "hello world";
	cout << str[str.size() - 1] << endl;
	cout << str.at(str.size() - 1) << endl;
	cout << str.back() << endl;
	cout << *(str.end() - 1) << endl;//Note that str.end() returns the next position of the last element
	return 0;
}

Operation results:

2. Several traversal methods of string object

1. Loop through [] or at plus for or while

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

  Operation results:

2. Through iterator

#include<iostream>
using namespace std;
int main()
{
	string str = "hello world";
	string::iterator it = str.begin();
	while (it != str.end()) {
		cout << *it;
		it++;
	}
	return 0;
}

Operation results:

3. Traverse through the range for

#include<iostream>
using namespace std;
int main()
{
	string str = "hello world";
	for (auto& e : str) {
		cout << e;
	}
}

  Operation results:

  4. Use for in algorithm_ Each to traverse

#include<iostream>
using namespace std;
#include<algorithm>
void myprint(char ch) {
	cout << ch;
}
int main()
{
	string str = "hello world";
	for_each(str.begin(), str.end(), myprint);
}

Operation results:

Splicing operation in string

/string Class
//String & operator + = (const char * STR) overload+=
//String & operator + = (const string & STR) overload+=
//String & operator + = (const char CH) overload+=
//String & append (const char * str) connects the string str to the end of the current string
//String & append (const char * str, int n) connects the first n characters of string str to the end of the current string
//String & append (const string & S) is the same as + =
//String & append (const string & S, int pos, int n) connects n characters from pos position in string s to the current string
//String & append (int n, char c) adds n characters C to the end of the current string

Not one by one here

string&operator(const char ch)

#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s = "ab";
	s += 'c';
	cout << s << endl;
}

Operation results:

string&operator+=(const char*str)

#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s = "ab";
	s += "abcdeff";
cout<<s<<endl;
}

Operation results:

 string &append(const char*str,int n);

#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s = "ab";
	s.append("abcdef", 3);
	cout << s << endl;
}

Operation results:

string&append(int n,char ch);

#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s = "ab";
	s.append(3, '0');
	cout << s << endl;
}

Operation results:

Find and replace in string

//Int find (const string & str, int POS = 0) const finds the position where str first appears. By default, it starts from position 0
//int find(const char*s,int pos=0) finds the position where s first appears, starting from pos
// int find(const char*s,int pos,int n) finds the position where the first n characters of s first appear from the pos position
//int find(const char c,int pos=0) finds the position where the character c first appears
//Int rfind (const string & str, int pos = NPOs) const finds the last occurrence of str, starting from pos
//int rfind(const char*s,int pos=npos)const finds the last position of S, starting from pos
//int rfind(const char*s,int pos,int n) starts from the pos position to find the position where the first n characters of s appear for the first time
//int rfind(const char ch,int pos=0)const finds the position where the character ch last appeared
//String & replace (int pos, int n, const string & STR) replaces n characters starting from pos position as a string
//String & replace (int pos, int n, const char * s) replaces n characters starting from pos with string s
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s1="abcdef";
	string s2 = "abc";
	int ret = s1.find(s2);
	cout << ret;

}

Operation results:

#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s1="abcdef";
	string s2 = "abc";
	int ret = s1.find(s2);
	cout << ret;

}

We look in s1 and start at position 0 in s2

Operation results:

 

int rfind(string&s,int pos=npos);

#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s1="abcdefabc";
	string s2 = "abc";
	int ret = s1.rfind(s2);
	cout << ret;

}

Operation results:

 

If not found, - 1 is returned

The difference between find and rfind:

find is looking from left to right, and rfind is looking from right to left

String string

string substr(int pos=0,int n=npos)const Return by pos Beginning n A string of characters

  example

#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s1="abcdefabc";
	cout << s1.substr(0, 3);

}

Operation results:

 

string insert and delete operations

/string&insert(int pos,const char*s)Insert string
//String & insert (int POS, const string & S) inserts a string
//String & insert (int POS, int n, char c) inserts n characters C at the specified position
//String & erase (int pos, int n = NPOs) deletes n characters starting from pos

I won't test here. I can test it myself

C in string_ Str (key)

string.c_str is a function in the string class encapsulated by Borland, which returns the first character address of the current string.

The return value of the c_str function is const   Char * cannot be directly assigned to char *, so we need to perform corresponding operation conversion.
 

#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
	string s = "Chelse";
	const char* str = s.c_str();
	cout << str << endl;
	s[1] = 'm';
	cout << str << endl;

}

Operation results:


First output   Certainly   Chelse;
What about the second output:   Chelse or Cmelse?
The answer is Cmelse.
const   The value of char * should be a constant. How can you change the value?
This is the pit encountered by many people. Maybe you will answer it smoothly during the interview, but in the actual project, you often fall into the pit and can't extricate yourself.
const   char*,   char   const*,   char*   What's the difference between const
const   Char * and char   Const * is equivalent. It refers to the pointer to the character constant, that is, the pointer can change the point, but the content it points to cannot be changed.
And char*   const, on the contrary, refers to a constant pointer, that is, the pointer cannot be changed, but the content pointed to by the pointer can be changed   The content pointed to by char * cannot be changed in this class.

So why has it changed here? It's the same as STR const   The life cycle of char * is related to the implementation of string class. The pointer returned by c_str() of string is managed by string, so its life cycle is the life cycle of string object. The implementation of string class actually encapsulates a pointer of char *, and c_str() directly returns the reference of the pointer. Therefore, the change of string object will directly affect the executed c_str() Pointer reference returned.

 

string Simulation Implementation:

#pragma once 
#include<iostream>
using namespace std;
#include<string.h>
#include<assert.h>
namespace ksy {
	class string
	{
	public:
		typedef char* iterator;
		/*string() :_str(nullptr)
		{}
		string(char*str)
			:_str(str)
		{}*/
		/*string(const char* str = "")
			:_str(new char[strlen(str)+1])
		{
		
			strcpy(_str, str);

		}*/

		/*string&operator=(string& s) {
			if (&s != this) {
				char* tmp = new char[s.size() + 1];
				delete this->_str;
				strcpy(tmp, s._str);
				_str = tmp;
			}
			return *this;
		}*/
		
		void reserve(int n) {
			if (n > _capacity) {
				
				char* newstr = new char[n+1];
				strcpy(newstr, _str);
				delete[]_str;
				_str = newstr;
				_capacity = n;
			}
		}

		void resize(int n,char ch='\0') {
			if (n < _size) {
				_str[n] = '\0';
				_size = n;
			}
			else {
				if (n > _capacity) {
					reserve(n);
				}
				for (int i = _size; i < n; i++) {
					_str[i] = ch;
				}
				_size = n;
				_str[_size] = '\0';

			}

		}
		iterator begin() {
			return _str;
		}
		iterator end() {
			return _str + _size;
		}
		friend ostream& operator<<(ostream& cout, const string& s);
		friend istream& operator>>(istream& cin, string& s);

		string(const  char* str = "") {
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];//'\ 0' is not a valid character
			strcpy(_str, str);
		 }
		~string() {
			delete[]_str;
			_str = nullptr;
			_size = _capacity;
	}

		string(const string& s)
			:_str(nullptr)
		{
			string tmp(s._str);
			swap(_str, tmp._str);
	    }
		string& operator=(string s) {
			if (&s != this) {
				swap(_str, s._str);
			}
			return *this;
		}

		size_t size() {
			return _size;
		}

		size_t size()const {
			return _size;
		}

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

		char& operator[](int i) {
			assert(i < _size);
			return _str[i];
		}

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

		const char* c_str() {
			return _str;
		}
		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) {
			int len = strlen(str);
			if (_size + len > _capacity) {
				reserve(_size + len);
			}
			strcpy(_str + _size, 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 > 0 && pos < _size);
			if (_size == _capacity) {
				size_t newcapacity = _capacity == 0 ? 2 : 2 * _capacity;
				reserve(newcapacity);
			}
			int end = _size;
			while (_size >= pos) {
				_str[end + 1] = _str[end];
				end--;
			}
			_str[pos] = ch;
			_size++;
			return *this;
		}
		string& insert(size_t pos, const char* str)
		{
			assert(pos < _size);
			int len = strlen(str);
			if (len + _size > _capacity) {
				reserve(len + _size);
			} 
			
			int end = _size;
			while (end >= pos) {
				_str[end+len] = _str[end];
				--end;
			}
			strncpy(_str + pos, str, len);
			_size += len;
			return *this;
		}
		string& 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;
			}
			return *this;
		}
		size_t  find(char ch, size_t pos = 0)
		{
			for (int 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 || *this == s;
		}

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

		bool operator==(const string& s)
		{
			int ret = strcmp(_str, s._str);
			return ret == 0;
		}


	private:
		char* _str;
		int _size;
		int _capacity;
		static size_t npos;
	};
	size_t string ::npos = -1;

  ostream& operator<<(ostream& cout, const string& s) {
	  for (size_t i = 0; i < s.size(); i++) {
		  cout << s[i];
	  }
	  return cout;
	}
  istream& operator>>(istream& cin, string& s) {
	  
	  while (1) {
		  char ch;
		  ch = cin.get();
		  if (ch == ' ' || ch == '\n') {
			  break;
		  }
		  else {
			  s += ch;
		  }

	  }
	  return cin;
  }

  void test_string() {
	  string s("hfdf");
	 /* cout << s << endl;
	  cout << s.capacity() << " " << s.size();
	  string s1(s);
	  cout << s1 << endl;
	  cout << s1.size() << " " << s1.capacity() << endl;*/
	  for (auto& e : s) {
		  cout << e;
	  }
 }

}

Posted by cheeks2k on Thu, 28 Oct 2021 03:05:47 -0700