C++--string

 

目录

1.string的介绍 

1.1简单介绍

1.2构造函数

1.3容量操作

1.4访问以及遍历

1.5修改操作

1.6非成员函数 

2.模拟实现

2.1深浅拷贝概念

2.2写时拷贝 

2.3代码实现(包含测试用例) 


1.string的介绍 

c语言中虽然也有字符串,但是其与对应的函数是分离的,不符合c++中面向对象的思想。而且c++中的string类使用起来更方便、快捷。

string - C++ Reference

1.1简单介绍

1. string是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作

1.2构造函数

1.3容量操作

 注意:

1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
2. clear()只是将string中有效字符清空,不改变底层空间大小。
3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。

1.4访问以及遍历

begin 获取一个字符的迭代器 + end 获取最后一个字符下一个位置的迭 代器

 []返回pos位置的字符,const string类对象调用

1.5修改操作

push_back
在字符串后尾插字符 c
append
在字符串后追加一个字符串
operator+= (重点)
在字符串后追加字符串 str
c_str(重点)
返回 C 格式字符串
find + npos(重点)
从字符串 pos 位置开始往后找字符 c ,返回该字符在字符串中的位置
rfind
从字符串 pos 位置开始往前找字符 c ,返回该字符在字符串中的位置
substr
str 中从 pos 位置开始,截取 n 个字符,然后将其返回
注意:
1. 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留

1.6非成员函数 

2.模拟实现

在模拟实现string类时尤其要考虑深浅拷贝问题,若没显示写使用编译器默认生成的,则是浅拷贝

说明:上述String类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题是,s1、s2共用同一块内存空间,在释放时同一块空间被释放多次而引起程序崩溃,这种拷贝方式,称为浅拷贝。

2.1深浅拷贝概念

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。
 
深拷贝:如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须显式给出。一般情况都是按照深拷贝方式提供。
 
显式深拷贝的写法

2.2写时拷贝 

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给计数增加1,当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源,如果计数为1,说明该对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使该资源。

2.3代码实现(包含测试用例) 

.h

#pragma once
#include<iostream>
#include<assert.h>
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(const char* str="");
		string(const string& str);
		string& operator=(string str);
		~string();
		const char* c_str() const;
		size_t size() const;
		char& operator[](size_t pos);
		const char& operator[](size_t pos) const;

		void reserve(size_t n);
		void pushback(char ch);
		void append(const char* str);

		string& operator+=(char ch);
		string& operator+=(const char* str);

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos = 0, size_t len=npos);
		size_t find(char ch, size_t pos = 0);
		size_t find(const char* str, size_t pos = 0);
		void swap(string& str);
		bool operator<(const string& str) const;
		bool operator>(const string& str) const;
		bool operator<=(const string& str) const;
		bool operator>=(const string& str) const;
		bool operator==(const string& str) const;
		bool operator!=(const string& str) const;
		void clear();

	private:
		char* _str=nullptr;
		size_t _size = 0;
		size_t _capacity = 0;
		const static size_t npos;
	};
	
	ostream& operator<<(ostream& os,const string& str);
	istream& operator>>(istream& os,string& str);
}

.cpp

#define  _CRT_SECURE_NO_WARNINGS 1
#include"string.h"
namespace bit{
	const size_t string::npos = -1;
	string::string(const char* str)
		:_size(strlen(str))
	{
		_str = new char[_size + 1];
		_capacity = _size;
		strcpy(_str, str);
	}

	string::string(const string& str) {
		string tmp(str.c_str());
		swap(tmp);
	}

	string& string::operator=(string str) {
		swap(str);
		return *this;
	}

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

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

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

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

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

	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(tmp, _str);
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}
	}

	void string::pushback(char ch) {
		insert(_size,ch);
	}

	void string::append(const char* str) {
		insert(_size,str);
	}

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

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

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

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

		size_t end = _size + 1;
		while (end > pos) {
			_str[end] = _str[end - 1];
			end--;
		}
		_str[pos] = ch;
		_size++;
	}
	void string::insert(size_t pos, const char* str) {
		assert(pos <= _size);
		size_t len = strlen(str);
		if (_size + len > _capacity) {
			reserve(_size + len);
		}
		size_t end = _size + len;
		while (end>pos+len-1) {
			_str[end] = _str[end - len];
			end--;
		}
		memcpy(_str + pos, str, len);
		_size += len;
	}
	void string::erase(size_t pos, size_t len) {
		assert(pos <= _size);
		if (len >= _size - pos) {
			_str[pos] = '\0';
			_size = pos;
		}
		else {
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}
	}

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

	size_t string::find(const char* str, size_t pos) {
		assert(pos <= _size);
		char* p = strstr(_str,str);
		return p - _str;
	}

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

	bool string::operator<(const string& str) const {
		return std::strcmp(_str, str._str) < 0;
	}
	bool string::operator>(const string& str) const {
		return !(*this <= str);
	}
	bool string::operator<=(const string& str) const {
		return *this < str || *this == str;
	}
	bool string::operator>=(const string& str) const {
		return !(*this < str);
	}
	bool string::operator==(const string& str) const {
		return std::strcmp(_str, str._str) == 0;
	}
	bool string::operator!=(const string& str) const {
		return !(*this==str);
	}

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

	ostream& operator<<(ostream& os, const string& str) {
		for (int i = 0; i < str.size(); i++) {
			os << str[i];
		}
		return os;
	}
	istream& operator>>(istream& is, string& str) {
		str.clear();
		char buff[128];
		int i = 0;
		char ch=is.get();
		while (ch != '\n' && ch != ' ') {
			buff[i++]= ch;
			if (i == 127) {
				buff[i] = '\0';
				str += buff;
				i = 0;
			}
			ch = is.get();
		}
		buff[i] = '\0';
		str += buff;
		return is;
	}
}

 test

#define  _CRT_SECURE_NO_WARNINGS 1
#include"string.h"
namespace bit{
	void test_string1() {
		string s;
		cout << s.c_str() << endl;
		string ss("hello world");
		cout << ss.c_str() << endl;
		for (int i = 0; i < ss.size(); i++) {
			cout << ss[i] << " ";
		}
		//string::iterator it1 = ss.begin();
		//while (it1 != ss.end()) {
		//	cout << *it1 << endl;
		//	it1++;
		//}
	}
	void test_string2() {
		const string s("1");
		s.begin();
		s[0];
	}

	void test_string3() {
		string s("hello world");
		s.pushback('x');
		cout << s.c_str() << endl;
		s.append("yy");
		cout << s.c_str() << endl;
	}
	void test_string4() {
		string s,a;
		s += '1';
		a=s += "a";
		cout << s.c_str() << endl;
		cout << a.c_str() << endl;
	}
	void test_string5() {
		string s("hello world");
		s.insert(0, '1');
		s.insert(0, '1');
		s.insert(0, '1');
		cout << s.c_str() << endl;
		s.insert(0, "22");
		cout << s.c_str() << endl;
	}
	void test_string6() {
		string s("hello world");
		size_t i = s.find('z');
		cout << i << endl;
		string a(s);
		cout << a.c_str() << endl;
		string b;
		b = s;
		cout << b.c_str() << endl;
	}
	void test_string7() {
		string s("hello world");
		string a("abc");
		cout << s.c_str() << endl;
		cout << a.c_str() << endl;
		bool flag=s > a;
		cout << flag << endl;
	}
	void test_string8() {
		string s("hello world");
		cout << s << endl;
		cin >> s;
		cout << s << endl;
	}
	void test_string9() {
		string s("hello world");
		cout << s << endl;
		cin >> s;
		cout << s << endl;
	}
	void test_string10() {
		string s("hello world");
		string s2(s);
		cout << s2 << endl;
		string s3;
		s3 = s2;
		cout << s3 << endl;
	}
	void test_string11() {
		string s("hello world");
		string s1("hh");
		s = s1;
		cout << s << endl;
	}
}

int main() {
	//bit::test_string2();
	bit::test_string11();
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值