0
点赞
收藏
分享

微信扫一扫

String 类的封装C++

安七月读书 2022-04-26 阅读 73
c++

目录

实验代码

String.h

String.cpp

main.cpp主函数

实验总结

测试代码


实验代码

String.h

#pragma once
#include<iostream>
using namespace std;
class String
{
public:
	friend ostream& operator<<(ostream& os, String& c);
	friend istream& operator>>(istream& is, String& c);
	String();
	String(const char* s);
	//复制构造
	String(String& ss);
	//移动构造函数
	String(String&& s)noexcept;
	//返回字符串长度
	int Length();
	//重载=,传入字符串
	String& operator =(const char*c);
	//重载=,深复制
	String& operator =(String& c);
	//重载= 移动构造
	String& operator=(String&& c);
	//重载= 传入单个字符
	String& operator=(char c);
	//重载+= 连接字符串
	String& operator+=(String& c);
	//重载+ 
	String operator + (String & c);
	//重载[]
	char operator[](int i);
	//重载==
	bool operator==(String& c);
	//重载<
	bool operator<(String& c);
	~String() 
	{ 
		if (this->m_str != NULL)
		{
			delete m_str;
			m_str = NULL;
		}	
	}
private:
	char* m_str;
	int m_size;//含有的长度
};

String.cpp

#include"String.h"
String::String():m_size(0)
{
	this->m_str = new char();
}
//有参构造
String::String(const char* s ): m_size(strlen(s))
{
	this->m_str = new char[this->m_size+1];
	//strcpy_s(m_str, m_size+1, s);
	strcpy(m_str, s);
}
//复制构造
String::String(String& ss):m_size(ss.Length())
{
	this->m_str = new char[m_size+1];
	//strcpy_s(m_str, m_size+1, ss.m_str);
	strcpy(m_str, ss.m_str);
}
//移动构造函数
String::String(String&& s)noexcept
{
	this->m_size = s.m_size;
	this->m_str = new char[this->m_size + 1];
	strcpy(this->m_str, s.m_str);
}
//重载[]
char String::operator[](int i)
{
	return this->m_str[i];
}
//重载==
bool String::operator==(String& c)
{
	if (strcmp(this->m_str, c.m_str))//不相等时,返回非0,进入if
		return false;
	return true;
}
//重载<
bool String::operator<(String& c)
{
	if (strcmp(this->m_str, c.m_str) < 0)
		return true;
	return false;

}
//赋值传入字符串
String& String::operator=(const char* c)
{
	this->m_size = strlen(c);
	this->m_str = new char[this->m_size + 1];
	strcpy(this->m_str, c);
	return *this;
}
//重载=,深复制
String& String::operator =(String& c)
{
	this->m_size = c.Length();
	this->m_str = new char[m_size+1];
	strcpy(this->m_str, c.m_str);
	return *this;
}
//重载= 移动构造
String& String::operator=(String&& c)
{
	this->m_size = c.Length();
	this->m_str = new char[m_size + 1];
	strcpy(this->m_str, c.m_str);
	return *this;
}
//重载= 传入单个字符
String& String::operator=(char c)
{
	this->m_size = 1;
	this->m_str = new char[2];
	this->m_str[0] = c;
	this->m_str[1] = '\0';
	return *this;
}
//重载+= 连接字符串
String& String::operator+=(String& c)
{
	this->m_size += c.m_size;//更新空间值
	char* temp= strcat(this->m_str, c.m_str);//连接后赋值临时变量
	this->m_str = new char[this->m_size + 1];//开辟新空间
	strcpy(this->m_str, temp);//赋值
	return *this;
}
//重载+ 
String String::operator + (String& c)
{
	String temp;
	temp.m_size = this->m_size + c.m_size;
	temp.m_str = new char[temp.m_size + 1];
	strcpy(temp.m_str, this->m_str);
	strcat(temp.m_str, c.m_str);
	return temp;
}
//返回字符串长度
int String::Length()
{
	return this->m_size;
}
//重载<<
ostream& operator<<(ostream &os, String& c)
{
	os << c.m_str;
	return os;
}
istream& operator>>(istream& is, String& c)
{
	/*第一想法(错),创建一个String s;
	时, 由于默认构造,分配空间0,因此后输入的话空间不足,输出会报错,无法分配*/
	//is>>c.m_str;
	// return is;

/*第二想法(对),可以先创建一个对象,空间给足够,输入值后,调整指针和空间大小后赋值给c,但缺点是
创建一个比较大的对象空间开销太大,导致浪费*/
	//String temp;
	//temp.m_str = new char[1000];
	//is >> temp.m_str;
	//temp.m_size = strlen(temp.m_str);
	//c = temp;

	/*思考了一下,可以先输入字符串,创建临时字符串指针存储,c的空间为temp的大小,
	开辟空间为size+1,之后把这个临时的字符串赋值给c,这样开销最小,动态分配*/
	is >> c.m_str;
	const char* temp = c.m_str;
	c.m_size = strlen(temp);
	c.m_str = new char[c.m_size + 1];
	strcpy(c.m_str,temp);
	return is;
}

main.cpp主函数

#include"String.h"
int main()
{
	String s1("help!"), s2("Good!"), s3(s2), s4, s5;
	cout << "s1=" << s1 << endl;//s1=help!
	s3 = "help!";
	cout << "s3=" << s3 << endl;//s3=help!
	s3 = s2;
	cout << "s3=" << s3 << endl;//s3=Good!
	s3 += s2;
	cout << "s3=" << s3 << endl;//s3=Good!Good!
	cin >> s4;//jobs
	cout << "s4=" << s4 << endl;//s4=jobs
	s5 = s3+s4;
	cout << "s5=" << s5 << endl;//s5=Good!Good!jobs
	s5 = 'g';
	cout << "s5=" << s5 << endl;//s5=g
	cout << "strlen(s5)=" << s5.Length() << endl;//strlen(s5)=1
	cout << boolalpha << (s3 == s1) << endl;//s3=Good!Good!和s1=help! 返回false
	cout << boolalpha << (s3 < s1) << endl;//成立返回true
	return 0;
}

实验总结

总结一下,容易出现内存分配不足问题,重载>>时动态分配,由于内部存在指针,所以析构时会清除指针,要进行深复制(防止堆区的数据被释放两次,这个会报错),重载的时候要注意时返回String还是String&,很有影响,String& 返回本身因此可以链式操作,String则不可以,然后注意重载各种操作符号即可完成此测试。

测试代码

s4输入jobs截图如下:

 

举报

相关推荐

0 条评论