<C/C++基础>设计一个String类(重载运算符等)

参考资源:

谷歌大神,《C++程序设计语言》


一,设计要求

基本要求:C++的基本数据类型中没有字符串变量。C++提高了两种字符串的表示:C风格的字符串和标准C++引入的string类。String类应由字符串数组以及其长度组成。该类至少应包含两个“私有”成员变量,
还应具有如下成员函数:
1)多种功能的构造函数;
2)析构函数;
3)重载运算符operator>>用于输入,同样重载运算符operator<<用于输出操作;
4)字符操作;
5)字符串的特性描述 ;
6)字符串赋值;
7)字符串的链接等
8)字符串的比较

9)返回指定位置的字串

10)字串交换

11)齐全的查找功能

12)替换功能

13)字串的插入

14)字串的删除

15)字串的流处理

16) 异常处理


二,代码实现(要求未完全实现)


1,"String.h"代码如下

include "iostream"
#include "windows.h"
using namespace std;

class MyString
{
public:
	//默认构造函数
	MyString(int size)
	{
		m_pChars=new char[size];
		memset(m_pChars,0,size);
		m_nLength=0;
		maxSize=size;
	}
	MyString(const char *cstr)
	{
		int len=strlen(cstr);
		m_pChars=new char[len+1];
		memset(m_pChars,0,len);
		strcpy_s(m_pChars,len+1,cstr);
	}
	MyString(int size,const char &cstr)
	{
		m_pChars=new char[size+1];
		memset(m_pChars,'\0',size+1);
		memset(m_pChars,cstr,size);
	}
	//析构函数
	~MyString()
	{
		if (m_pChars!=NULL)
		{
			delete[] m_pChars;
			m_pChars=NULL;
		}
		
	}
	friend ostream& operator<< (ostream&,MyString&);//重载<<运算符  
	friend istream& operator>> (istream&,MyString&);//重载>>运算符 
	MyString& operator=(const char *cstr);//只能被重载为成员函数
	char operator[](const int nPos);//只能被重载为成员函数
	char at(const unsigned int nPos);
private:
	int m_nLength; //获取当前 String 对象中的字符数
	char* m_pChars;
	int maxSize;
};

//输入运算符重载
istream& operator>>( istream &input, MyString &str )  
{  
	input>>str.m_pChars;
	int len=strlen(str.m_pChars);
	str.m_nLength=len+1;
	if (len > str.maxSize)
	{
		cerr<<"错误:输入过多的字符(输入运算符重载)。"<<endl;
		cout<<"三秒后退出程序!"<<endl;
		Sleep(3000);
		exit(1);
	}else
	{
		return input; //使用return可以支持连续使用>>运算符  
	}
} 

//输出运算符重载
ostream& operator<<(ostream& os,MyString& str)  
{  
	os << str.m_pChars << endl;  
	return os;  
}

char MyString::operator[](const int nPos)
{
	if ( nPos>strlen(m_pChars))
	{
		cerr<<"错误:输入过多的字符([]运算符重载)。"<<endl;
		cout<<"三秒后退出程序!"<<endl;
		Sleep(3000);
		exit(1);
	}
	return m_pChars[nPos];
}

char MyString::at(const unsigned int nPos)
{
	if ( nPos> strlen(m_pChars))
	{
		cerr<<"错误:输入过多的字符([]运算符重载)。"<<endl;
		cout<<"三秒后退出程序!"<<endl;
		Sleep(3000);
		exit(1);
	}
	return m_pChars[nPos];
}
//赋值运算符重载
MyString& MyString::operator=(const char *cstr)  
{  
	int len=strlen(cstr);
	this->m_nLength=len+1;
	if (len > maxSize)
	{
		cerr<<"错误:输入过多的字符(赋值运算符重载)。"<<endl;
		cout<<"三秒后退出程序!"<<endl;
		Sleep(3000);
		exit(1);
	}else
	{
		strcpy_s(m_pChars,len+1,cstr);
		return *this;
	}
	
}



(2)主测试程序

// ConsoleAppKeCheng.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include "String.h"
//#include <string>  
#include <sstream> 
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	system("color 0A");
	cout<<"一,MyString类的重载运算符>>以及<<"<<endl;
	MyString str1(10);
	cout<<"1,重载输入:请输入字符串  ";
	cin>>str1;
	cout<<"2,重载输出:您的字符串为  "<<str1<<endl;

	cout<<"二,MyString类的构造函数 "<<endl;
	MyString str2(10);
	str2="Ebow";
	cout<<"1,直接赋值(重载赋值运算符):"<<str2;

	char *cs="Tang";
	MyString str3(cs);
	cout<<"2,复制构造函数:"<<str3;
	char ch='E';
	MyString str4(5,ch);
	cout<<"3,赋值指定数目的字符:"<<str4<<endl;

	cout<<"三,MyString类的字符操作"<<endl;
	MyString str5 = "EbowTang";   
	ch = str5[1];//operator[]返回当前字符串中第n个字符的位置   
	cout<<"指定的字符串:"<<str5;
	cout <<"用[]重载返回指定位置1的元素 "<< ch << endl; 

	MyString str6 = "EbowTang";  
	ch = str6.at(4);//at()返回当前字符串中第n个字符的位置,并且提供范围检查,当越界时会抛出异常!    
	cout<<"用at函数返回指定位置5的元素 " << ch << endl;  
	system("pause");
	return 0;
}



(3)测试结果







附带一篇关于《字符串拼接效率比较文章》

最近写的程序用到大量拼接字符串,为了提高拼接效率,比较了一下+=、append、stringstream、sprintf四种拼接字符串的方法。

测试方法

      比较方法是写了4个函数,分别用+=、append、stringstream、sprintf的方式来拼接字符串,拼接方法是将s1="abcedfg",s2="hijklmn",s3="opqrst"三个字符串拼接到一起,总共循环60次。然后在main函数中依次调用这4个函数,并打时间戳来计时。为了使时间差异更明显,可以取循环N(N可以为100或是1000000等)次调用的时间。代码如下:

#include <iostream>
#include <string>
#include <sys/time.h>
#include <sstream>
#include <stdio.h>
using namespace std;
#define OUT_IN_REPEATE_NUM 10000
#define IN_REPEATE_NUM 60

string s1="abcedfg";
string s2="hijklmn";
string s3="opqrst";
void  plusTest(string& ret)
{
    for(int i=0; i<IN_REPEATE_NUM; i++)
    {
        ret += s1;
        ret += s2;
        ret += s3;
    }
}
void  appendTest(string& ret)
{
    for(int i=0; i<IN_REPEATE_NUM; i++)
    {
        ret.append(s1);
        ret.append(s2);
        ret.append(s3);
    }
}
void sprintfTest(string& ret)
{
    const size_t length=26*IN_REPEATE_NUM;
    char tmp[length];
    char* cp = tmp;
    size_t strLength=s1.length()+s2.length()+s3.length();
    for(int i=0; i<IN_REPEATE_NUM; i++)
    {
        sprintf(cp,"%s%s%s", s1.c_str(), s2.c_str(),s3.c_str());
        cp+=strLength;
    }
    ret = tmp;
}

void  ssTest(string& ret)
{
    stringstream ss;
    for(int i=0; i<IN_REPEATE_NUM; i++)
    {
        ss<<s1;
        ss<<s2;
        ss<<s3;
    }
    ret = ss.str();
}
int main() {
    string ss, plus, append, sprintf;
    struct timeval sTime, eTime;

    gettimeofday(&sTime, NULL);
    for(int i=0; i<OUT_IN_REPEATE_NUM; i++)
    {
        sprintf="";
        sprintfTest(sprintf);
    }
    gettimeofday(&eTime, NULL);
    long SprintfTime = (eTime.tv_sec-sTime.tv_sec)*1000000+(eTime.tv_usec-sTime.tv_usec); //exeTime 单位是微秒

    gettimeofday(&sTime, NULL);
    for(int i=0; i<OUT_IN_REPEATE_NUM; i++)
    {
        append="";
        appendTest(append);
    }
    gettimeofday(&eTime, NULL);
    long AppendTime = (eTime.tv_sec-sTime.tv_sec)*1000000+(eTime.tv_usec-sTime.tv_usec); //exeTime 单位是微秒

    gettimeofday(&sTime, NULL);
    for(int i=0; i<OUT_IN_REPEATE_NUM; i++)
    {
        ss="";
        ssTest(ss);
    }
    gettimeofday(&eTime, NULL);
    long SsTime = (eTime.tv_sec-sTime.tv_sec)*1000000+(eTime.tv_usec-sTime.tv_usec); //exeTime 单位是微秒

    gettimeofday(&sTime, NULL);
    for(int i=0; i<OUT_IN_REPEATE_NUM; i++)
    {
        plus="";
        plusTest(plus);
    }
    gettimeofday(&eTime, NULL);
    long PlusTime = (eTime.tv_sec-sTime.tv_sec)*1000000+(eTime.tv_usec-sTime.tv_usec); //exeTime 单位是微秒

    cout<<"PlusTime is :   "<<PlusTime<<endl;
    cout<<"AppendTime is : "<<AppendTime<<endl;
    cout<<"SsTime is :     "<<SsTime<<endl;
    cout<<"SprintfTime is :"<<SprintfTime<<endl;
    if(ss==sprintf && append==plus && ss==plus)
    {
        cout<<"They are same"<<endl;
    }
    else
    {
        cout<<"Different!"<<endl;
        cout<<"Sprintf: "<<sprintf<<endl;
        cout<<"ss:        "<<ss<<endl;
        cout<<"Plus:     "<<plus<<endl;
        cout<<"Append:"<<append<<endl;
    }

}

测试结果:     

在Linux环境下用g++编译以上代码,运行结果如下(时间单位为μm):

外层循环1000000次

外层循环100000次

外层循环10000次

外层循环1000次

外层循环100次

PlusTime is :     3405450

AppendTime is : 4020078

SsTime is :        7835499

SprintfTime is :  14875433

They are same

PlusTime is :      337229

AppendTime is : 401719

SsTime is :        788242

SprintfTime is :  1517999

They are same

PlusTime is :     32177

AppendTime is : 40265

SsTime is :        78928

SprintfTime is :  150839

They are same

PlusTime is :      3402

AppendTime is : 4074

SsTime is :        7984

SprintfTime is :   15425

They are same

PlusTime is :      369

AppendTime is : 429

SsTime is :         921

SprintfTime is :   1591

They are same


 结论:

根据以上结果,如果是使用Linux系统并且是g++(gcc)编译器,大量拼接字符串的效率从高到低依次为:+=、append()、stringstream、sprintf()。

——菜鸟吉姆斯原创,如有错误,敬请指正!


参考资源:

【1】http://www.cnblogs.com/james6176/p/3222671.html



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值