编程语言
首页 > 编程语言> > C++学习笔记------Mstring类的实现

C++学习笔记------Mstring类的实现

作者:互联网

2.2 Mstring类的实现

Mstring类基本结构:

class Mstring
{
private:
	char* _str;
	int _len;//容量
	int _val_len;//数据长度(有效数据长度),不包括'\0'

    /*
    	以下成员方法不对外提供
    */
	bool is_full();//判满
	bool is_empty();//判空
	void revert();//按照1.5倍进行扩容
	 

public:
	Mstring();
	Mstring(const char* str);
	Mstring(const Mstring& src);
	 
	Mstring& operator=(/*this,*/const Mstring& src);
	 
	 
    //增加和删除字符
	void push_back(char c);
	char pop_back();
	 
	 
	bool operator>(/*this, */const Mstring& src);
	 
	bool operator==(const Mstring& src);
	 
	Mstring operator+(/*this, */const Mstring& src);
	 
	//->(箭头运算符), * 解引用运算符
    //普通对象调用该方法 
	char& operator[](int pos);//普通对象可以进行修改
	//常对象调用该方法
	char operator[](/*常对象指针*/int pos)const; //对常对象无法进行修改  
	
    ~Mstring()
    {//防止内存泄露
        if (_str != NULL)
        {
            delete[]_str;
        }
        /*_str = NULL;  不用加吗?*/
	}
	 
    
    friend ostream& operator<<(ostream& out, const Mstring& src);

	 
};

实际上该部分并非要一开始实现,在完成push_back()和pop_back()时可以先使用,后面再考虑实现

bool is_full()//判满
{//_len表示实际容量,_val_len表示有效字符(不包括'\0')
    return _len == _val_len+1;
}

bool is_empty()
{
    return _val_len == 0;//判断有效字符个数是否为0
}

void revert()//按照1.5倍进行扩容
{
    if (_len==0)//调用默认构造函数时,_len是0,这时候接一个push_back()操作,就需要扩容
    {
        _len = 10;//默认字符容量从10开始
    }

    _len = _len + (_len >> 1);//右移除2,执行效率高
    
    char* tmp = new char[_len];//开辟一块新的内存
    strcpy_s(tmp, _val_len+1, _str);//把已有内容进行拷贝,包括'\0'

    //释放原来的内存,防止内存泄漏
    if (_str != NULL)
    {
        delete[]_str;
    }
    _str = tmp;
}
Mstring()//在类构造之前一定要先构造它的所有成员
    //:_str(),_len(),_val_len(),成员属性的定义,一定会有成员属性的定义或者初始化,只是大部分都是系统自动完成了
    //const,引用以及成员对象(可能)需要手动实现
{
    _str = NULL;
    _len = 0;
    _val_len = 0;
}
Mstring(const char* str)
{
    if (str == NULL)
    {
        _str = NULL;
        _len = 0;
        _val_len = 0;
    }
    _len = strlen(str) + 1;//+1表示'\0'
    _val_len = _len-1;
    _str = new char[_len];
    strcpy_s(_str, _len, str);
}
Mstring(const Mstring& src)//拷贝构造
{ 
    _len = src._len;
    _val_len = src._val_len;
    
    //防止浅拷贝,拷贝构造哪来的释放
    _str = new char[_len];
    strcpy_s(_str, _len, src._str);
}
void push_back(char c)
{
    if (_str==NULL)//默认构造后,直接push_back()
    {
        _val_len = 1;//也就是实际容量从2开始才行
    }
    if (is_full())
    {
        revert();
    }
    if (_val_len == 0)
    {
        _val_len = 1;
    }
    _str[_val_len] = c;//把原来'\0'的位置覆盖掉
    _str[++_val_len] = 0;//后一位放'\0',_val_len加一

}
char pop_back()
{
    if (is_empty()||_str==NULL)
    {
		return 0;
    }
    char c = _str[_val_len - 1];
    _str[_val_len] = 0;
    _val_len--;

    return c;//不能返回局部变量的引用和指针
}
Mstring& operator=(/*this,*/const Mstring& src)
{
    //防止自赋值,避免下一步释放内存时出错
    if (&src != this)
    {
        return *this;
    }
    //防止内存泄漏
    if (_str != NULL)
    {
        delete[]_str;
    }
    //防止浅拷贝
    _len = src._len;
    _val_len = src._val_len;

    _str = new char[_len];
    strcpy_s(_str, _len, src._str);

    return *this;
}
bool operator>(/*this, */const Mstring& src)
{//strcmp(str1, str2)--->相等返回0, str1>str2返回>0, str1>str2返回<0
    return strcmp(_str, src._str)>0;
}


bool operator==(const Mstring& src)
{
    return strcmp(_str, src._str) == 0;
}

//所谓加法,在这时拼接操作
Mstring operator+(/*this, */const Mstring& src) 
{
    Mstring tmp = *this;
    //注意i=0, src._str[0]是第一个元素的位置,src._str[_val_len-2]是'\0'的位置
    for (int i=0;i<src._val_len-1;i++) //(_val_len-1)---->'\0'的位置
    {
        tmp.push_back(src._str[i]);//push_back()有扩容处理
    }
    return tmp;
}
char& operator[](int pos)//普通对象可以进行修改
{
    return _str[pos];

}

//常对象调用该方法
char operator[](/*常对象指针*/int pos)const //对常对象无法进行修改  
{
    return _str[pos];
}
//注意在类中设置友元
ostream& operator<<(ostream& out, const Mstring& src)
{
	for (int i=0;i<src._val_len;i++)
	{
		out << src._str[i];
	}
	return out;
}

​ 测试:

int main()
{
	Mstring str("12345");
	cout << str<<endl;
	for (int i = '0'; i < '9'; i++)
	{
		str.push_back(i);
		cout << str << endl;
	}
	for (int i = 1; i < 9; i++)
	{
		cout << str.pop_back() << endl;
		cout << str << endl;
	}
	 
	return 0;
}

输出结果:

结果

标签:Mstring,val,src,len,char,C++,str,------
来源: https://www.cnblogs.com/ChenFei-Blogs/p/15095423.html