中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++ string類

發布時間:2020-07-16 12:33:29 來源:網絡 閱讀:420 作者:zgw285763054 欄目:編程語言

    string類是C++的一個常見的面試題,考查面試者的基本功,雖然簡單,但是有很多細節需要注意。


#pragma once
#include <assert.h>

/*
	深拷貝與淺拷貝:
        淺拷貝,只是對指針的拷貝,拷貝后兩個指針指向同一個內存空間,深拷貝不但對指針進行拷貝,
	而且對指針指向的內容進行拷貝,經深拷貝后的指針是指向兩個不同地址的指針。淺拷貝是指源對象
	與拷貝對象共用一份實體,僅僅是引用的變量不同(名稱不同)。對其中任何一個對象的改動都會影響另外一個對象。
	    深拷貝是指源對象與拷貝對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。
	    舉個例子,一個人名叫張三,后來用他克隆(假設法律允許)了另外一個人,叫李四,不管是張三缺胳膊少腿
	還是李四缺胳膊少腿都不會影響另外一個人。
*/

class String
{
	friend ostream& operator<<(ostream& _cout, const String& s);
public:
	/*
	String()
		:_pStr(/ *new char('\0')* /new char[1])
	{
		_pStr[0] = '\0'; //不能是"\0"
	}

	//new和delete,new[]和delete[]一定要匹配使用
	//strlen 不能傳NULL
	
	String(char* pStr)
		:_pStr(new char[strlen(pStr)+1])
	{
		strcpy(_pStr, pStr); //strcpy會拷貝'\0'過去
	}
	*/

	//構造函數合并
	String(char* pStr = "")
	{
		_size = strlen(pStr);
		_capacity = _size+1;
		_pStr = new char[_size+1];
		strcpy(_pStr, pStr);
	}

	/*
	//拷貝構造函數常規寫法
	String(const String& s)
		:_pStr(new char[strlen(s._pStr)+1])
	{
		strcpy(_pStr, s._pStr);
	}
	*/

	String(const String& s)
		:_pStr(NULL) //需要先將this->_pStr置為空,否則交換后tmp為隨機值,析構tmp時delete[]出現錯誤
	{
		String tmp(s._pStr);
		std::swap(_pStr, tmp._pStr);
	}

	/*
	//賦值運算符重載常規寫法 -> 釋放原來的空間,開辟和s一樣大的空間
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			/ *
			//存在一致性問題。如果new空間失敗,原來的空間將被釋放,深拷貝失敗
			delete[] _pStr;
			_str = new char[strlen(s._pStr)+1];
			strcpy(_pStr, s._pStr);
			* /

			//先開辟空間,再拷貝
			char* tmp = new char[strlen(s._pStr)+1];
			strcpy(tmp, s._pStr);
			delete[] _pStr;
			_pStr = tmp;
		}

		return *this;
	}
	*/

	/*
	//賦值運算符重載現代寫法
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			String tmp(s._pStr);
			std::swap(_pStr, tmp._pStr);
		}

		return *this;
	}
	*/

	//賦值運算符重載現代寫法
	String& operator=(String s)
	{
		swap(_pStr, s._pStr);

		return *this;
	}

	~String()
	{
		if (_pStr)
			delete[] _pStr;
	}
	
	char* C_Str()
	{
		return _pStr;
	}

	char& operator[](size_t index)
	{
		return _pStr[index];
	}

	void PushBack(const char& ch)
	{
		/*_CheckCapacity(_size + 2);

		_pStr[_size] = ch;
		_pStr[++_size] = '\0';*/

		Insert(_size, ch);
	}

	void PopBack()
	{
		assert(_size > 0);
		--_size;
		_pStr[_size] = '\0';
	}

	void Insert(size_t pos, char ch)
	{
		assert(pos <= _size);

		_CheckCapacity(_size + 2);

		size_t cur = _size;
		while (cur >= pos)
		{
			_pStr[cur+1] = _pStr[cur];
			cur--;
		}
		_pStr[pos] = ch;

		++_size;
	}

	void Insert(int pos, const char* str)
	{
		assert(pos>=0 && pos <= _size);

		//增容
		size_t size = strlen(str);
		_CheckCapacity(_size+1+size);

		//挪動數據
		int index = _size;
		while (index >= pos)
		{
			_pStr[index+size] = _pStr[index];
			--index;
		}

		//拷貝
		for (size_t i = 0; i < size; ++i)
		{
			_pStr[pos++] = str[i];
		}

		_size += size;
	}

	int Find(char ch)
	{
		for (size_t index = 0; index < _size; ++index)
		{
			if (_pStr[index] = ch)
			{
				return index;
			}
		}

		return -1;
	}

	int Find(const char* subStr)
	{
		assert(subStr);

		size_t dstIndex = 0; //要查找的子串
		size_t srcIndex = 0;
		size_t subSize = strlen(subStr);
		for (dstIndex = 0; dstIndex <= _size - subSize; ++dstIndex)
		{
			for (srcIndex = 0; srcIndex < subSize; ++srcIndex)
			{
				if (subStr[srcIndex] != _pStr[dstIndex+srcIndex])
				{
					break;
				}
			}

			if (srcIndex == subSize)
			{
				return dstIndex;
			}
		}

		return -1;
	}

	void Erase(size_t pos)
	{
		assert(pos < _size);

		for (size_t i = pos+1; i <= _size; ++i)
		{
			_pStr[i-1] = _pStr[i];
		}

		--_size;
	}

	String& operator+=(const String& s)
	{
		Insert(_size, s._pStr);

		return *this;
	}
	//String s("Hello");
	//可以使用 s += String(" World"); String(" World") -> 拷貝構造 -> String& s
	//也可使用 s += " World";  " World" -> 構造函數 -> String& s

	//如果改為String& operator+=(String& s)則不能使用 s += " World"。 例如:
	/*
	int i = 0;
	//double& a = i; //i先創建一個臨時對象,然后把臨時對象給double& a,a就成為一個臨時變量的引用。錯誤
	const double& a = i; //加const,可以引用臨時變量。正確
	*/

	/*
	String s1 = "sssssss"; //"sssssss"生成一個匿名對象,匿名對象再構造s1。編譯器將兩步優化為一步:"sssssss"直接構造s1。
	//String& s2 = "sssssss"; //不能引用匿名(臨時)對象。錯誤
	const String& s3 = "sssssss"; //加const,可以引用臨時變量。正確
	*/

	bool operator==(const String& s)
	{
		return (strcmp(_pStr, s._pStr) == 0);
	}

	bool operator>(const String& s)
	{
		return (strcmp(_pStr, s._pStr) > 0);
	}

	bool operator>=(const String& s)
	{
		return (*this > s || *this == s);
	}

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

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

protected:
	void _CheckCapacity(size_t needSize)
	{
		if (_size+1 >= _capacity)
		{
			_capacity = _capacity+needSize > 2*_capacity ? needSize : 2*_capacity;
			_pStr = (char*)realloc(_pStr, _capacity);
		}
	}
	
protected:
	char* _pStr;
	size_t _size;
	size_t _capacity;
};

ostream& operator<<(ostream& _cout, const String& s)
{
	_cout<<s._pStr;
	return _cout;
}


推薦文章:

C++面試中string類的一種正確寫法:http://coolshell.cn/articles/10478.html



向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

太湖县| 亚东县| 佛坪县| 阳城县| 久治县| 甘肃省| 太原市| 广宁县| 大连市| 鸡东县| 永昌县| 勐海县| 醴陵市| 唐山市| 平原县| 航空| 鄄城县| 芜湖县| 客服| 江都市| 修武县| 略阳县| 建昌县| 自治县| 陕西省| 酉阳| 贵德县| 绥化市| 伊金霍洛旗| 韶关市| 阳山县| 北海市| 新干县| 绥棱县| 花莲市| 阜康市| 乐至县| 马鞍山市| 怀宁县| 岳普湖县| 弥勒县|