自定义String类的实现

  string类是C++中用来处理字符串的极其方便的工具,不同于C语言中的字符串处理函数,string类可以把字符串当成普通的基本数据类型处理,可以灵活地采用赋值“=”,大小判断“< > ==”,还有加法运算“+ +=”等等,而且不用像字符数组一样预设空间大小,总之可以说是兼顾了字符数组的优点,有弥补了C风格的字符串处理起来不方便的地方。

  今天我们就来自己尝试一下对C语言中原有的字符串处理函数进行包装,自定义一个String类出来。

  首先是对String类进行一个总体的声明

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>

using namespace std;

class String
{
public:
	String(const char *str = NULL);
	~String();
	String(const String &x);
	int length()const
	{
		return strlen(sdata);
	}
	String substr(int pos = 0, int len = -1)const;
	int find(const char *str, int pos = 0)const;
	int find(const String &x, int pos = 0)const;
	int find(char ch, int pos = 0)const; 
	int rfind(const char *str, int pos = 0)const;
	int rfind(const String &x, int pos = 0)const;
	int rfind(char ch, int pos = 0)const;
	const char *c_str()const;
	String operator = (const char *str);
	String operator = (const String &x);
	String operator + (const char *str);
	String operator + (const String &x);
	String operator += (const String &x);
	String operator += (const char *str);
	char& operator [] (unsigned int x);
	bool operator == (const char *str)const;
	bool operator == (const String &x)const;
	friend ostream& operator << (ostream &out, const String &x);
	friend istream& operator >> (istream &in, String &x);
private:
	char *sdata;
};

  如果是在工程文件里,那么以上的部分应该放在String.h中,这里只是实现了一些string类较常用的功能,用来给大家展示一下C++语言的优美之处,下面给出各个成员函数的实现

  

//构造函数
String::String(const char *str)
{
	if (!str)
	{
		sdata = new char[1];
		sdata[0] = '\0';
	}
	else
	{
		int len = strlen(str);
		sdata = new char[len + 1];
		strcpy(sdata, str);
	}
}
String::~String()//析构函数
{
	delete[]sdata;
}
String::String(const String &x)//复制构造函数
{
	int len = strlen(x.sdata);
	sdata = new char[len + 1];
	strcpy(sdata, x.sdata);
}
String String::substr(int pos, int len)const//提取子串函数
{
	if (len < 0)
		len = strlen(sdata) - pos;
	String x;
	x.sdata = new char[len + 1];
	strncpy(x.sdata, sdata + pos, len);//strncpy不自动添加'\0'
	x.sdata[len] = '\0';
	return x;
}
//查找函数的三种形式
int String::find(const String &x, int pos)const
{
	return find(x.sdata, pos);
}
int String::find(const char *str, int pos)const
{
	char *cp = strstr(sdata + pos, str);//查找子串函数
	if (cp)
		return cp - sdata;
	else
		return -1;
}
int String::find(char ch, int pos)const
{
	char *cp = strchr(sdata + pos, ch);//查找字符函数
	if (cp)
		return cp - sdata;
	else
		return -1;
}
//反向查找的三种形式,返回目标串最后一次出现的位置
int String::rfind(const char *str, int pos)const
{
	int k = -1;
	int p = find(str, pos);
	while (p >= 0)
	{
		k = p;
		p += strlen(str);
		p = find(str, p);
	}
	return k;
}
int String::rfind(const String &x, int pos)const
{
	return rfind(x.sdata, pos);
}
int String::rfind(char ch, int pos)const
{
	char *cp = strrchr(sdata + pos, ch);//字符反向查找函数
	if (cp)
		return cp - sdata;
	else
		return -1;
}
const char* String::c_str()const//返回c格式字符串
{
	return sdata;
}
//赋值函数的两种形式
String String::operator = (const String &x)
{
	*this = x.sdata;
	return *this;
}
String String::operator = (const char *str)
{
	if (strlen(sdata) >= strlen(str))//检查原空间是否足够
		strcpy(sdata, str);
	else
	{
		delete[]sdata;//原空间不足则需另外开辟空间
		sdata = new char[strlen(str) + 1];
		strcpy(sdata, str);
	}
	return *this;
}
//加法运算的两种形式
String String::operator + (const String &x)
{
	return *this + x.sdata;
}
String String::operator + (const char *str)
{
	String re;
	delete[]re.sdata;
	char *p = new char[strlen(sdata) + strlen(str) + 1];
	p[0] = '\0';
	strcat(p, sdata);
	strcat(p, str);
	re.sdata = p;
	return re;
}
//加等于运算得两种形式
String String::operator += (const String &x)
{
	return *this = *this + x;
}
String String::operator += (const char *str)
{
	return *this = *this + str;
}
char& String::operator [] (unsigned int x)//取字符
{
	int len = strlen(sdata);
	if (x < len) return sdata[x];
	return sdata[len - 1];
}
bool String::operator == (const char *str)const//相等
{
	return strcmp(sdata, str) == 0;
}
bool String::operator == (const String &x)const
{
	return strcmp(sdata, x.sdata) == 0;
}
ostream& operator << (ostream &out, const String &x)//输出流
{
	out << x.sdata;
	return out;
}
istream& operator >> (istream &in, String &x)//输入流
{
	char ch[100];
	in >> ch;
	x = ch;
	return in;
}

  大部分函数的实现都是应用C语言中的字符串处理函数,由此可见String类的方便还是离不开底层C语言的支持(虽然真正的string类应该不会像我一样直接偷懒用C风格的字符串处理函数,但底层的原理大概是一样的),打个比方,String类就像是给原来粗糙的电路板罩上了一个漂亮的外壳,变成了一个对用户更加友好的产品。

  接下来没什么好说的,代码实现并不是很难,但我要提示的一点是,有时候我们可以利用之前定义的函数让代码更加简洁,例如find和rfind的实现

int String::find(const String &x, int pos)const
{
	return find(x.sdata, pos);
}

int String::rfind(const String &x, int pos)const
{
	return rfind(x.sdata, pos);
}

  还有就是‘\0’,因为系统在处理字符串是以‘\0’作为结束标志的,如果处置不当把'\0'给丢了,很容易造成数组访问越界等一系列问题,我在实现对'+'运算符进行重载时就在'\0'上出了错

//加法运算的两种形式
String String::operator + (const String &x)
{
	return *this + x.sdata;
}
String String::operator + (const char *str)
{
	String re;
	delete[]re.sdata;
	char *p = new char[strlen(sdata) + strlen(str) + 1];
	p[0] = '\0';//系统在执行strcat时会去找p中的'\0'作为p字符串的结尾,而如果找不到的话,系统就会一直向后遍历
	strcat(p, sdata);//直到找到一个内存单元内容为'\0',这样就会不知不觉地造成访问越界的问题
	strcat(p, str);
	re.sdata = p;
	return re;
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值