您的位置:首页 > 编程语言 > C语言/C++

[c++]字符串类各种操作的实现以及遇到的bug

2015-06-15 08:53 591 查看
字符串类的结构如下:

Class String:

public:

构造函数:1:未给定初始化的内容则默认指向只包含'\0'的字符串(即空串)---->开辟一个字节的空间,并用'\0'初始化 2:给定初始化的内容则开辟相应的空间并初始化为相应内容;

析构函数:释放动态开辟的空间,即m_data指向的内存空间

初始化函数

赋值函数

private:

char * m_data;------->>>指向动态开辟的空间

对字符串类实现如下操作:

String operator+(const String &s); //s = s1 + s2
	String operator+=(const String &s); //s1 += s2
	char&  operator[](int index);
	bool operator==(String &s);
	bool operator!=(String &s);
	bool operator>(String &s);   //s1 > s2
	bool operator<=(String &s);
	bool operator<(String &s);
	bool operator>=(String &s);
ostream& operator<<(ostream &out, const String &s);
istream& operator>>(istream &in, String &s);


代码如下:

#include<iostream>
using namespace std;

//友元函数声明
class String;
ostream& operator<<(ostream &out,const String &str);
istream& operator>>(istream &in,String &str);

class String
{
//默认的构造函数
public:
	String(const char *str = NULL)
	{
		if(NULL == str)
		{
			m_data = new char[1];
			m_data[0] = '\0';
		}
		else
		{
			m_data = new char[strlen(str) + 1];
			strcpy(m_data,str);
		}
	}
	~String()
	{
		delete []m_data;
	}
	String(const String &str)
	{
		m_data = new char[strlen(str.m_data) + 1];
		strcpy(m_data,str.m_data);
	}
	String& operator=(const String &str)
	{
		if(this != &str)
		{
			delete []m_data;//此步骤易忘记,从而可能造成内存泄露(原因,未考虑对像可能已经过存在,开辟过内存)如:String s("123");s = s1;
			m_data = new char[strlen(str.m_data) + 1];
			strcpy(m_data,str.m_data);
		}
		return *this;
	}
//运算符重载
	//连接:对像 = 对像 + 对像
	String operator+(const String &str)
	{
		 char *s = new char[strlen(m_data) + strlen(str.m_data) + 1];
		 strcpy(s,m_data);
		 strcat(s,str.m_data);
		 String tmp(s);	 //构造临时变量	//return String(s);!!!!!!错误!!
		 delete []s;	 //释放开辟的内存,防止内存泄露
		 return tmp;
	}
	//连接:对像 += 对像  s1 += s
	String& operator+=(const String &str)
	{
		char *s = new char[strlen(m_data) + strlen(str.m_data) + 1];
		strcpy(s,m_data);
		strcat(s,str.m_data);
		delete []m_data;//释放原来的空间
		m_data = s;	    //指向新开辟的空间
		return *this;
	}
	//字符串是否相等,相等返回真,否则返回假  s1 == s?
	bool operator==(const String &str)
	{
		if(strcmp(m_data,str.m_data) == 0)
			return true;
		else 
			return false;
	}
	//字符串是否不相等,不相等返回真,否则返回假 s 1!= s?
	bool operator!=(const String &str)
	{
		if(strcmp(m_data,str.m_data) == 0)
			return false;
		else 
			return true;	
	}
	//s1 > s
	bool operator>(const String &str)
	{
		if(strcmp(m_data,str.m_data) > 0)
			return true;
		else
			return false;
	}
	//s1 >= s
	bool operator>=(const String &str)
	{
		if(strcmp(m_data,str.m_data) >= 0)
			return true;
		else
			return false;
	}
	//s1 < s
	bool operator<(const String &str)
	{
		if(strcmp(m_data,str.m_data) < 0)
			return true;
		else
			return false;
	}
	//s1 <= s
	bool operator<=(const String &str)
	{
		if(strcmp(m_data,str.m_data) <= 0)
			return true;
		else
			return false;
	}
	char& operator[](int index)
	{
		return m_data[index];
	}
friend ostream& operator<<(ostream &out,const String &str);
friend istream& operator>>(istream &in,String &str);

private:
	char *m_data;
};

ostream& operator<<(ostream &out,const String &str)
{
   out<<str.m_data<<endl;
   return out;
}
istream& operator>>(istream &in,String &str)
{
//	std::cout<<"你可以输入"<<strlen(str)<<"个字符"<<endl;
	in>>str.m_data;
	return in;
}

int main()
{
	String s("_helen");  <span style="white-space:pre">	</span> //测试构造
	String s1("zyh");
	s1 += s;	<span style="white-space:pre">	</span>//测试加等:+=
	cout<<s1;		//测试输出:<<

	String s2 = s1;		//测试赋值:=
	cout<<s2;

	String s5 ="1123";	//测试下标:[]
	s5[1] = 'd';
	cout<<s5;

	String s6 ("zyh");
	String s7 ("zyh_helen");

	if(s6 > s7)         <span style="white-space:pre">	</span>//测试比较
	{
		cout<<"s6 > s7"<<endl;
	}
	else 
	{
		cout<<"s6 < s7"<<endl;
	}

	String s4("zyh_helen");
	cin>>s4;		//测试输入

	cout<<s4;
	
	return 0;
}



注意:

String& operator=(const String &str)
	{
		if(this != &str)
		{
			delete []m_data;//此步骤易忘记,从而可能造成内存泄露(原因,未考虑对像可能已经过存在,开辟过内存)如:String s("123");s = s1;
			m_data = new char[strlen(str.m_data) + 1];
			strcpy(m_data,str.m_data);
		}
		return *this;
	}
//运算符重载
	//连接:对像 = 对像 + 对像
	String operator+(const String &str)
	{
		 char *s = new char[strlen(m_data) + strlen(str.m_data) + 1];
		 strcpy(s,m_data);
		 strcat(s,str.m_data);
		 String tmp(s);	 //构造临时变量	//return String(s);!!!!!!错误!!
		 delete []s;	 //释放开辟的内存,防止内存泄露
		 return tmp;
	}
	//连接:对像 += 对像  s1 += s
	String& operator+=(const String &str)
	{
		char *s = new char[strlen(m_data) + strlen(str.m_data) + 1];
		strcpy(s,m_data);
		strcat(s,str.m_data);
		delete []m_data;//释放原来的空间
		m_data = s;	    //指向新开辟的空间
		return *this;
	}


实现如上运算符重载的过程中需要:注意内存泄露的问题!!!!<<<------务必注意,在开辟了新的空间之后,只有释放了原来的内存,才可以指向新开辟的空间

就像:(由于种种原因)另寻新欢,只有处理好前妻的关系(离婚手续,安置费),才可以与新欢开始新的生活,若未处理好与前妻的关系,直接抛弃,那么总有一天你会付出代价,而且是惨重的代价!

测试过程中遇到的如下bug:

测试如下:





解释如下:

String s("123");--->调用构造函数开辟四个字节:存放123\0

cin时存入1234\0,超出了开辟空间的范围,释放空间时出现错误!!

String s;--->调用构造函数开辟一个字节:存放\0
cin时存入11\0,超出了开辟空间的范围,释放空间时出现错误!!

即动态开辟n个字节的空间,初始化时超过其范围,就会出现如上所述bug:DAMAGE:
after Normal block

以下来自:点击打开链接

前几天师弟调试程序的时候出现了这样一个错误,出错的位置是在delete [] 一个动态分配的数组时出现的。

经过调查发现错误是因为他之前在给数组赋值的时候越界了1个位置。

也就是double * a= new double [5],结果赋值的时候给a[5]=5。使用c++的同学都知道,一个5维的动态数组,调用时应该是0~4,但是这里给a[5]赋值并没有出错,反而是delete时才会出错。

这其实是因为在动态分配内存的时候往往分配的是一个连续的地址,这一点从可以使用*[a+3]来取值就能够知道。

因此,在动态分配的时候,会在数组界限外加一个用来标识数组范围的标志,例如a数组,就会在a[-1]和a[5]有两个标志,如果我们在这两个位置赋值,赋值和调用时并不会出错,而是在delete [] a时出错,错误的名称就是“DAMAGE: before Normal block”和“DAMAGE: after Normal block”。一般是后者居多。

因此,当你遇见这个错误的时候,记得去检查一下自己数组的赋值吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: