草庐IT

<三>自己实现string,加入迭代器功能

ericshi1985 2023-03-28 原文

迭代器的功能:
提供一种统一的方式,来透明的遍历容器
理解 begin()方法,end()方法, ++ , * 的用处
其中 C++11 中提供的foreach的方式,其底层还是通过迭代器来进行遍历的.

#include <iostream>
using namespace std;

class MyString2 {

public:

	//构造函数
	MyString2(const char * pSource = nullptr) {
		if (pSource != nullptr) {
			pString = new char[strlen(pSource) + 1];
			strcpy(pString, pSource);
		}
		else {
			pString = new char[1];
			pString[0] = '\0';
		}
		cout << "MyString构造函数,对象地址=" << this << endl;
	}

	//拷贝构造
	MyString2(const MyString2 & _rValue) {

		pString = new char[strlen(_rValue.pString) + 1];
		strcpy(pString, _rValue.pString);
		cout << "MyString拷贝构造函数" << endl;
	}

	//赋值函数
	MyString2 & operator=(const MyString2 & _rValue) {

		if (this == &_rValue) {
			return *this;
		}
		delete[] this->pString;
		this->pString = nullptr;

		char * _tpString = new char[strlen(_rValue.pString) + 1];
		strcpy(_tpString, _rValue.pString);

		cout << "MyString赋值函数" << endl;

	}

	//可编辑
	char & operator[](int index) {

		int len = strlen(this->pString);
		if (index<0) { return pString[0]; }
		else if (index>len) { return pString[index]; }
		else { return pString[index]; }

	}

	//不可编辑
	const char operator[](int index) const {

		int len = strlen(this->pString);
		if (index<0) { return pString[0]; }
		else if (index>len) { return pString[index]; }
		else { return pString[index]; }

	}

	bool operator>(const MyString2 & _rValue) const {
		return strcmp(this->pString, _rValue.pString)>0;
	}
	
	bool operator<(const MyString2 & _rValue) const {
		return strcmp(this->pString, _rValue.pString)<0;
	}
	
	bool operator==(const MyString2 & _rValue) const {
		return strcmp(this->pString, _rValue.pString) == 0;
	}

	int length() const {
		return strlen(this->pString);
	}

	~MyString2() {
		if (this->pString != nullptr) {
			delete[] this->pString;
			this->pString = nullptr;
			cout << "MyString析构函数" << this << endl;
		}
	}

	const char * c_str()  const { return this->pString; }

	//给Mystring 设计迭代器
	class Iterator {
		public:

			Iterator(char * _p=nullptr):p(_p) {
				this->p = _p;
			}
		    char & operator*() {
				return *p;
			}

			//前置++
			void operator++() {
				p++;
			}
			//
			bool operator!=(const Iterator & _val) {		
				return p!=_val.p;
			}
		private:

			char * p;
	};
	// begin() 返回的 用MyString的首元素地址,通过Iterator封装一下
	Iterator begin() const {
		return  Iterator(this->pString);
	}
	// end() 返回的是 用 MyString 的最尾元素的下一个地址 再用Iterator封装一下
    Iterator end() const {
		return  Iterator(this->pString+this->length());
	}

private:
	char * pString;
	friend MyString2 operator+  (const MyString2 & s1, const MyString2 &s2);
	friend ostream & operator<<(ostream & out, const MyString2 &s);
	
};

MyString2 operator+(const MyString2 & s1, const MyString2 &s2) {

	/*
	方式1 这段代码有 内存泄漏问题  tp 没有释放掉
	int newLength = strlen(s1.pString) + strlen(s2.pString) + 1;
	char *tp = new char[newLength + 1];//重新申请空间
	strcpy(tp, s1.pString);
	strcat(tp, s2.pString);

	MyString s(tp);
	cout << "operator+ = " << &s << endl;
	return s;
	*/

	/*
	方式2 对比方式1 效果更高
	*/
	MyString2 s;
	int newLength = strlen(s1.pString) + strlen(s2.pString) + 1;
	s.pString = new char[newLength + 1];//重新申请空间
	strcpy(s.pString, s1.pString);
	strcat(s.pString, s2.pString);
	cout << "operator+ = " << &s << endl;
	return s;
}

ostream & operator<<(ostream & out, const MyString2 &s) {
	cout << s.pString << endl;
	return out;
}

void test2() {

	MyString2 s1("12345");
	MyString2 s2("6789ABC");

	cout << s1 << endl;
	cout << s2 << endl;

	MyString2 s3 = s1 + s2;
	cout << s3 << endl;
	cout << "s3 = " << &s3 << endl;

	for (int i = 0; i < s3.length(); i++) {
		cout << s3[i] << endl;
	}

	cout << "--------------------" << endl;
	s3[0] = 'W';
	for (int i = 0; i < s3.length(); i++) {
		cout << s3[i] << endl;
	}

	const MyString2 s4("hello");

	for (int i = 0; i < s4.length(); i++) {
		cout << s4[i] << endl;
	}

	cout << "------iterator Begin------" << endl;
	MyString2::Iterator it_begin = s4.begin();
	MyString2::Iterator it_end   = s4.end();

	for (  ;it_begin!=it_end; ++it_begin) {
	
		cout << *it_begin <<" ";

	}
	cout << endl;
	cout << "------iterator End------" << endl;


}
int main() {
	test2();
	system("pause");
	return 0;
}

有关<三>自己实现string,加入迭代器功能的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby - 如何离开加入Arel? - 2

    Arel3.0.2提供了两个类来指定连接类型:Arel::Nodes::InnerJoin和Arel::Nodes::OuterJoin并使用InnerJoin默认。foo=Arel::Table.new('foo')bar=Arel::Table.new('bar')foo.join(bar,Arel::Nodes::InnerJoin)#innerfoo.join(bar,Arel::Nodes::OuterJoin)#outerfoo.join(bar,???)#left如果要生成左连接,如何连接两个表? 最佳答案 你可以使用

  3. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  4. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  5. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  6. ruby-on-rails - Nokogiri:使用 XPath 搜索 <div> - 2

    我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll

  7. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  8. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  9. ruby - 从 String#split 返回的零长度字符串 - 2

    在Ruby1.9.3(可能还有更早的版本,不确定)中,我试图弄清楚为什么Ruby的String#split方法会给我某些结果。我得到的结果似乎与我的预期相反。这是一个例子:"abcabc".split("b")#=>["a","ca","c"]"abcabc".split("a")#=>["","bc","bc"]"abcabc".split("c")#=>["ab","ab"]在这里,第一个示例返回的正是我所期望的。但在第二个示例中,我很困惑为什么#split返回零长度字符串作为返回数组的第一个值。这是什么原因呢?这是我所期望的:"abcabc".split("a")#=>["bc"

  10. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

随机推荐