字符串类运算符重载

C++字符串类运算符重载

//重点

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//定义MyString类 字符串数组
class MyString
{
public:
	//构造和析构函数
	MyString()
	{
		m_len = 0;
		m_p = NULL;
	}
	//MyString(int len = 0)
	//{
	//	if (len < 0) {
	//		m_len = 0;
	//		return;		//直接返回到main函数
	//	}
	//	m_len = len;
	//	m_p = new char[len + 1];
	//}
	MyString(const char *p)		//MyString a(“dddd”);需要能实现这样的初始化
	{
		m_len = strlen(p);
		m_p = new char[m_len + 1];
		strcpy(m_p, p);
	}

	MyString(const MyString& obj)	//拷贝构造函数,先释放旧内存
	{
		if (obj.m_len > 0) {	//	长度大于0才需要拷贝
			m_len = obj.m_len;
			m_p = new char[m_len + 1];
			strcpy(m_p, obj.m_p);	//复制字符串内容
		}
	}
	~MyString()
	{
		if (m_p != NULL) {
			delete[] m_p;
			m_len = 0;
		}
	}
	//运算符重载
	char& operator[](int i)
	{
		return m_p[i];
	}
	MyString& operator=(MyString& s)
	{
		if (m_p != NULL) {
			delete[] m_p;
			m_len = 0;
		}
		m_len = s.m_len;
		m_p = new char[m_len + 1];
		strcpy(m_p, s.m_p);
		return *this;
	}
	//重载=运算符后再重载这个函数是否可行?		证明可行
	MyString& operator=(const char *p)	//s1 = "ddddd";需要能实现这样的赋值
	{
		m_len = strlen(p);
		m_p = new char[m_len + 1];
		strcpy(m_p, p);
		return *this;
	}

	bool operator==(MyString& s)
	{
		if (m_len != s.m_len) {
			return false;
		}													
		for (int i = 0; i < m_len; ++i) {						
			if (m_p[i] != s[i]) {
				return false;
			}
		}
		return true;
	}
	bool operator!=(MyString& s)
	{
		return !(*this == s);
	}

	bool operator>(MyString& s)	//实现链式编程,返回值为引用?还是bool?
	{
		if (strcmp(m_p, s.m_p) > 0) {
			return true;
		}
		else {
			return false;
		}
	}
	bool operator<(MyString& s)
	{
		return !(*this > s);
	}

	friend ostream& operator<<(ostream& out, MyString& s);
	friend istream& operator>>(istream& in, MyString& s);

private:
	int m_len;
	char *m_p;
};

ostream& operator<<(ostream& out, MyString& s)
{
	cout << "The string is: " << endl;
	for (int i = 0; i < s.m_len; ++i) {
		out << s[i];
	}
	return out;
}
istream& operator>>(istream& in, MyString& s)
{
	cout << "Please input " << s.m_len << " characters: " << endl;
	for (int i = 0; i < s.m_len; ++i) {
		in >> s[i];
	}
	return in;
}

int main()
{
	MyString s1("ddddd"),s2;
	//cin >> s1;
	//s1[3] = 'f';	//这个实现了?
	cout << s1 << endl;

	s2 = "zzzzz";		//这个如何实现?
	cout << s2 << endl;

	if (s1 < s2) {
		cout << "s1 < s2" << endl;
	}
	else {
		cout << "s1 > s2" << endl;
	}

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

	if (s1 == s2) {
		cout << "s1 == s2" << endl;
	}
	else {
		cout << "s1 != s2" << endl;
	}

	cout << s2[1] << endl;

	return 0;	//以上运算符重载调试成功!
}

注意点:

  1. 要支持空串“”
  2. 实参 “zzzzz” 应该对应形参 const char *p
  3. strlen在参数为NULL情况下会出错,只能在strlen使用之前先判断一下
  4. 重载 = 运算符对应两种参数情况,s1 =s2; s1 = “ddddd”;
  5. out << s.m_p; 重载 << 运算符的优化,可以直接输出属性,不需使用循环输出字符数组
  6. 重载 == 和!=也对应两种参数情况
  7. C++里边只要是非零都认为是真,只有在值为0的时候才认为是假。重载 == 时使用 return !strcmp(m_p,p); 可以代替对字符数组每个值的比较。
  8. 重载 == 和!=运算符的函数定义后面加 const 表示不可更改指针指向的内存数据。
  9. 重载 > 和 < 运算符也对应两种参数情况,可直接使用return strcmp(m_p, s.m_p); 和 return strcmp(s.m_p, m_p); ,调换两个参数的位置
  10. 有时需要把类的指针 露出来,strcpy(s3.c_str(), “aaaa”); 这样用函数调用 (对比MFC)
  11. MyString s4; cin >> s4; //注意:此时s4调用无参构造函数,由于指针没有分配内存,无法输入数据,程序直接跳过;解决方案:声明另外的有参构造函数 MyString(int len = 0)
  12. 重载 >> 和 << 运算符可以直接使用 in >> s.m_p; out << s.m_p; 而不使用循环输出字符数组,不然有时会出现意想不到的问题。

完善和优化后的代码:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//定义MyString类 字符串数组
class MyString
{
public:
	//重载 >> 和 << 运算符
	friend ostream& operator<<(ostream& out, MyString& s);
	friend istream& operator>>(istream& in, MyString& s);

	//构造和析构函数
	//MyString()		//完善:要支持空串“”
	//{
	//	m_len = 0;
	//	//m_p = NULL;
	//	m_p = new char[m_len + 1];
	//	strcpy(m_p, "");
	//}

	MyString(int len = 0)
	{
		if (len == 0) {
			m_len = 0;
			m_p = new char[m_len + 1];
			strcpy(m_p, "");
		}
		else {
			m_len = len;
			m_p = new char[m_len + 1];
			strcpy(m_p, "");
		}
	}

	//MyString(int len = 0)		//和上面的例程没差别吧?
	//{
	//	if (len < 0) {
	//		m_len = 0;
	//		return;		//直接返回到main函数
	//	}
	//	m_len = len;
	//	m_p = new char[len + 1];
	//}

	MyString(const char *p)		//MyString a(“dddd”);需要能实现这样的初始化
	{
		if (p == NULL) {	//完善:要支持MyString s3 = NULL;不加这个编译会出现断点
			m_len = 0;
			m_p = new char[m_len + 1];
			strcpy(m_p, "");
		}
		else {
			m_len = strlen(p);	// strlen在参数为NULL情况下会出错
			m_p = new char[m_len + 1];
			strcpy(m_p, p);
		}
	}

	MyString(const MyString& obj)	//拷贝构造函数,先释放旧内存
	{
		if (obj.m_len > 0) {	//	长度大于0才需要拷贝
			m_len = obj.m_len;
			m_p = new char[m_len + 1];
			strcpy(m_p, obj.m_p);	//复制字符串内容
		}
	}
	~MyString()
	{
		if (m_p != NULL) {
			delete[] m_p;
			m_p = NULL;	//完善
			m_len = 0;
		}
	}
	//运算符重载
	char& operator[](int i)
	{
		return m_p[i];
	}
	MyString& operator=(MyString& s)
	{
		if (m_p != NULL) {
			delete[] m_p;
			m_len = 0;
		}
		m_len = s.m_len;
		m_p = new char[m_len + 1];
		strcpy(m_p, s.m_p);
		return *this;
	}
	//重载=运算符后再重载这个函数是否可行?		证明可行
	MyString& operator=(const char *p)	//s1 = "ddddd";需要能实现这样的赋值
	{
		/*m_len = strlen(p);
		m_p = new char[m_len + 1];
		strcpy(m_p, p);
		return *this;*/
		if (m_p != NULL) {	//完善:1 先释放旧内存
			delete[] m_p;
			m_len = 0;
		}
		if (p == NULL) {	//2 分配新内存,要支持s1 = "";即空串
			m_len = 0;
			m_p = new char[m_len + 1];
			strcpy(m_p, "");	//3 复制内容
		}
		else {
			m_len = strlen(p);
			m_p = new char[m_len + 1];
			strcpy(m_p, p);
		}
		return *this;
	}

	bool operator==(MyString& s) const
	{
		if (m_len != s.m_len) {
			return false;
		}													
		/*for (int i = 0; i < m_len; ++i) {						
			if (m_p[i] != s[i]) {
				return false;
			}
		}
		return true;*/
		else {
			return !strcmp(m_p, s.m_p);	//优化:用字符串比较函数
		}
	}
	bool operator==(const char *p) const	//完善:要支持s3 == "dddd"判断
	{
		if (p == NULL) {
			if (m_len != 0) {
				return false;
			}
			else {
				return true;
			}
		}
		else {
			if (m_len != strlen(p)) {
				return false;
			}
			/*for (int i = 0; i < m_len; ++i) {
				if (m_p[i] != p[i]) {
					return false;
				}
			}*/
			else {
				return !strcmp(m_p, p);	//优化:用字符串比较函数
			}
		}
	}

	bool operator!=(MyString& s) const	//!= 也对应两种参数的情况
	{
		return !(*this == s);
	}
	bool operator!=(const char *p) const
	{
		return !(*this == p);
	}

	//bool operator>(MyString& s)	//实现链式编程,返回值为引用?还是bool?
	//{
	//	if (strcmp(m_p, s.m_p) > 0) {
	//		return true;
	//	}
	//	else {
	//		return false;
	//	}
	//}
	//bool operator<(MyString& s)
	//{
	//	return !(*this > s);
	//}

	int operator>(MyString& s)		//完善:大于和小于号的重载优化
	{
		return strcmp(m_p, s.m_p);
	}
	int operator>(const char *p)
	{
		return strcmp(m_p, p);
	}
	int operator<(MyString& s)
	{
		return strcmp(s.m_p, m_p);	//调换两个参数的位置
	}
	int operator<(const char *p)
	{
		return strcmp(p, m_p);
	}

	//把类的指针 露出来
	char *c_str()
	{
		return m_p;
	}
	const char *c_str2()	//指针指向的内存数据不可更改
	{
		return m_p;
	}
	int getLen()
	{
		return m_len;
	}

private:
	int m_len;
	char *m_p;
};

ostream& operator<<(ostream& out, MyString& s)
{
	cout << "The string is: " << endl;
	/*for (int i = 0; i < s.m_len; ++i) {
		out << s[i];
	}*/
	out << s.m_p;	//优化
	return out;
}
istream& operator>>(istream& in, MyString& s)
{
	cout << "Please input " << s.m_len << " characters: " << endl;
	/*for (int i = 0; i < s.m_len; ++i) {
		in >> s[i];
	}*/
	in >> s.m_p;	//优化
	return in;
}

int main()
{
	MyString s3 = NULL;
	s3 = "";
	if (s3 == "") {
		cout << "s3 == """ << endl;
	}
	else {
		cout << "s3 != """ << endl;
	}

	strcpy(s3.c_str(), "aaaa");
	cout << s3 << endl;

	MyString s4(5);
	cin >> s4;	//注意:此时s4调用无参构造函数,由于指针没有分配内存,无法输入数据,程序直接跳过
	cout << s4 << endl;		//注意:运行到这里会出现无法停止的问题!!此时把s3部分注释掉是可正常运行的
	

	//MyString s1("ddddd"),s2;
	cin >> s1;
	s1[3] = 'f';	//这个实现了?
	//cout << s1 << endl;

	//s2 = "zzzzz";		//这个如何实现?
	//cout << s2 << endl;

	//if (s1 < s2) {
	//	cout << "s1 < s2" << endl;
	//}
	//else {
	//	cout << "s1 > s2" << endl;
	//}

	//s2 = s1;
	//cout << s2 << endl;

	//if (s1 == s2) {
	//	cout << "s1 == s2" << endl;
	//}
	//else {
	//	cout << "s1 != s2" << endl;
	//}

	//cout << s2[1] << endl;

	return 0;	//以上运算符重载调试成功!
}
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值