C++字符串类运算符重载
//重点
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//定义MyString类 字符串数组
class MyString
{
public:
//构造和析构函数
MyString()
{
m_len = 0;
m_p = NULL;
}
//MyString(int len = 0)
//{
// if (len < 0) {
// m_len = 0;
// return; //直接返回到main函数
// }
// m_len = len;
// m_p = new char[len + 1];
//}
MyString(const char *p) //MyString a(“dddd”);需要能实现这样的初始化
{
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p, p);
}
MyString(const MyString& obj) //拷贝构造函数,先释放旧内存
{
if (obj.m_len > 0) { // 长度大于0才需要拷贝
m_len = obj.m_len;
m_p = new char[m_len + 1];
strcpy(m_p, obj.m_p); //复制字符串内容
}
}
~MyString()
{
if (m_p != NULL) {
delete[] m_p;
m_len = 0;
}
}
//运算符重载
char& operator[](int i)
{
return m_p[i];
}
MyString& operator=(MyString& s)
{
if (m_p != NULL) {
delete[] m_p;
m_len = 0;
}
m_len = s.m_len;
m_p = new char[m_len + 1];
strcpy(m_p, s.m_p);
return *this;
}
//重载=运算符后再重载这个函数是否可行? 证明可行
MyString& operator=(const char *p) //s1 = "ddddd";需要能实现这样的赋值
{
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p, p);
return *this;
}
bool operator==(MyString& s)
{
if (m_len != s.m_len) {
return false;
}
for (int i = 0; i < m_len; ++i) {
if (m_p[i] != s[i]) {
return false;
}
}
return true;
}
bool operator!=(MyString& s)
{
return !(*this == s);
}
bool operator>(MyString& s) //实现链式编程,返回值为引用?还是bool?
{
if (strcmp(m_p, s.m_p) > 0) {
return true;
}
else {
return false;
}
}
bool operator<(MyString& s)
{
return !(*this > s);
}
friend ostream& operator<<(ostream& out, MyString& s);
friend istream& operator>>(istream& in, MyString& s);
private:
int m_len;
char *m_p;
};
ostream& operator<<(ostream& out, MyString& s)
{
cout << "The string is: " << endl;
for (int i = 0; i < s.m_len; ++i) {
out << s[i];
}
return out;
}
istream& operator>>(istream& in, MyString& s)
{
cout << "Please input " << s.m_len << " characters: " << endl;
for (int i = 0; i < s.m_len; ++i) {
in >> s[i];
}
return in;
}
int main()
{
MyString s1("ddddd"),s2;
//cin >> s1;
//s1[3] = 'f'; //这个实现了?
cout << s1 << endl;
s2 = "zzzzz"; //这个如何实现?
cout << s2 << endl;
if (s1 < s2) {
cout << "s1 < s2" << endl;
}
else {
cout << "s1 > s2" << endl;
}
s2 = s1;
cout << s2 << endl;
if (s1 == s2) {
cout << "s1 == s2" << endl;
}
else {
cout << "s1 != s2" << endl;
}
cout << s2[1] << endl;
return 0; //以上运算符重载调试成功!
}
注意点:
- 要支持空串“”
- 实参 “zzzzz” 应该对应形参 const char *p
- strlen在参数为NULL情况下会出错,只能在strlen使用之前先判断一下
- 重载 = 运算符对应两种参数情况,s1 =s2; s1 = “ddddd”;
- out << s.m_p; 重载 << 运算符的优化,可以直接输出属性,不需使用循环输出字符数组
- 重载 == 和!=也对应两种参数情况
- C++里边只要是非零都认为是真,只有在值为0的时候才认为是假。重载 == 时使用 return !strcmp(m_p,p); 可以代替对字符数组每个值的比较。
- 重载 == 和!=运算符的函数定义后面加 const 表示不可更改指针指向的内存数据。
- 重载 > 和 < 运算符也对应两种参数情况,可直接使用return strcmp(m_p, s.m_p); 和 return strcmp(s.m_p, m_p); ,调换两个参数的位置
- 有时需要把类的指针 露出来,strcpy(s3.c_str(), “aaaa”); 这样用函数调用 (对比MFC)
- MyString s4; cin >> s4; //注意:此时s4调用无参构造函数,由于指针没有分配内存,无法输入数据,程序直接跳过;解决方案:声明另外的有参构造函数 MyString(int len = 0)
- 重载 >> 和 << 运算符可以直接使用 in >> s.m_p; out << s.m_p; 而不使用循环输出字符数组,不然有时会出现意想不到的问题。
完善和优化后的代码:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//定义MyString类 字符串数组
class MyString
{
public:
//重载 >> 和 << 运算符
friend ostream& operator<<(ostream& out, MyString& s);
friend istream& operator>>(istream& in, MyString& s);
//构造和析构函数
//MyString() //完善:要支持空串“”
//{
// m_len = 0;
// //m_p = NULL;
// m_p = new char[m_len + 1];
// strcpy(m_p, "");
//}
MyString(int len = 0)
{
if (len == 0) {
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p, "");
}
else {
m_len = len;
m_p = new char[m_len + 1];
strcpy(m_p, "");
}
}
//MyString(int len = 0) //和上面的例程没差别吧?
//{
// if (len < 0) {
// m_len = 0;
// return; //直接返回到main函数
// }
// m_len = len;
// m_p = new char[len + 1];
//}
MyString(const char *p) //MyString a(“dddd”);需要能实现这样的初始化
{
if (p == NULL) { //完善:要支持MyString s3 = NULL;不加这个编译会出现断点
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p, "");
}
else {
m_len = strlen(p); // strlen在参数为NULL情况下会出错
m_p = new char[m_len + 1];
strcpy(m_p, p);
}
}
MyString(const MyString& obj) //拷贝构造函数,先释放旧内存
{
if (obj.m_len > 0) { // 长度大于0才需要拷贝
m_len = obj.m_len;
m_p = new char[m_len + 1];
strcpy(m_p, obj.m_p); //复制字符串内容
}
}
~MyString()
{
if (m_p != NULL) {
delete[] m_p;
m_p = NULL; //完善
m_len = 0;
}
}
//运算符重载
char& operator[](int i)
{
return m_p[i];
}
MyString& operator=(MyString& s)
{
if (m_p != NULL) {
delete[] m_p;
m_len = 0;
}
m_len = s.m_len;
m_p = new char[m_len + 1];
strcpy(m_p, s.m_p);
return *this;
}
//重载=运算符后再重载这个函数是否可行? 证明可行
MyString& operator=(const char *p) //s1 = "ddddd";需要能实现这样的赋值
{
/*m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p, p);
return *this;*/
if (m_p != NULL) { //完善:1 先释放旧内存
delete[] m_p;
m_len = 0;
}
if (p == NULL) { //2 分配新内存,要支持s1 = "";即空串
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p, ""); //3 复制内容
}
else {
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p, p);
}
return *this;
}
bool operator==(MyString& s) const
{
if (m_len != s.m_len) {
return false;
}
/*for (int i = 0; i < m_len; ++i) {
if (m_p[i] != s[i]) {
return false;
}
}
return true;*/
else {
return !strcmp(m_p, s.m_p); //优化:用字符串比较函数
}
}
bool operator==(const char *p) const //完善:要支持s3 == "dddd"判断
{
if (p == NULL) {
if (m_len != 0) {
return false;
}
else {
return true;
}
}
else {
if (m_len != strlen(p)) {
return false;
}
/*for (int i = 0; i < m_len; ++i) {
if (m_p[i] != p[i]) {
return false;
}
}*/
else {
return !strcmp(m_p, p); //优化:用字符串比较函数
}
}
}
bool operator!=(MyString& s) const //!= 也对应两种参数的情况
{
return !(*this == s);
}
bool operator!=(const char *p) const
{
return !(*this == p);
}
//bool operator>(MyString& s) //实现链式编程,返回值为引用?还是bool?
//{
// if (strcmp(m_p, s.m_p) > 0) {
// return true;
// }
// else {
// return false;
// }
//}
//bool operator<(MyString& s)
//{
// return !(*this > s);
//}
int operator>(MyString& s) //完善:大于和小于号的重载优化
{
return strcmp(m_p, s.m_p);
}
int operator>(const char *p)
{
return strcmp(m_p, p);
}
int operator<(MyString& s)
{
return strcmp(s.m_p, m_p); //调换两个参数的位置
}
int operator<(const char *p)
{
return strcmp(p, m_p);
}
//把类的指针 露出来
char *c_str()
{
return m_p;
}
const char *c_str2() //指针指向的内存数据不可更改
{
return m_p;
}
int getLen()
{
return m_len;
}
private:
int m_len;
char *m_p;
};
ostream& operator<<(ostream& out, MyString& s)
{
cout << "The string is: " << endl;
/*for (int i = 0; i < s.m_len; ++i) {
out << s[i];
}*/
out << s.m_p; //优化
return out;
}
istream& operator>>(istream& in, MyString& s)
{
cout << "Please input " << s.m_len << " characters: " << endl;
/*for (int i = 0; i < s.m_len; ++i) {
in >> s[i];
}*/
in >> s.m_p; //优化
return in;
}
int main()
{
MyString s3 = NULL;
s3 = "";
if (s3 == "") {
cout << "s3 == """ << endl;
}
else {
cout << "s3 != """ << endl;
}
strcpy(s3.c_str(), "aaaa");
cout << s3 << endl;
MyString s4(5);
cin >> s4; //注意:此时s4调用无参构造函数,由于指针没有分配内存,无法输入数据,程序直接跳过
cout << s4 << endl; //注意:运行到这里会出现无法停止的问题!!此时把s3部分注释掉是可正常运行的
//MyString s1("ddddd"),s2;
cin >> s1;
s1[3] = 'f'; //这个实现了?
//cout << s1 << endl;
//s2 = "zzzzz"; //这个如何实现?
//cout << s2 << endl;
//if (s1 < s2) {
// cout << "s1 < s2" << endl;
//}
//else {
// cout << "s1 > s2" << endl;
//}
//s2 = s1;
//cout << s2 << endl;
//if (s1 == s2) {
// cout << "s1 == s2" << endl;
//}
//else {
// cout << "s1 != s2" << endl;
//}
//cout << s2[1] << endl;
return 0; //以上运算符重载调试成功!
}