题目地址http://cxsjsxmooc.openjudge.cn/2019t3sprintw5/001/
实战中学习,你觉得自己基础掌握的不错,是骡子是马show me the code,还是不行。自己在写vector和string的过程中才慢慢真正了解了C++的一些功能,以前都是只知道这些东西,但是不知道有啥用。
目前所用到的知识点:
1、C++中各种构造函数的不同和用处
2、不同操作符重载时的异同
3、友元函数在其中的使用
4、strlen和sizeof的区别
对本题的总结:
1、对=的重载,需要注意判断是否把自己赋值给了自己;且需要返回引用。原因是:
在C++赋值运算符原本的特性中,赋值运算符返回的是左侧的引用,这样(a=b)=c就意味着先执行了(a=b)这个函数,然后返回了a的引用,a的引用还可以被赋值为c。如果不是返回的引用,那么返回值就是一个临时变量,不能被赋值!!!!!
所以自己在写的时候也要返回引用!!!
2、对()的重载,不能返回数组,要返回类的对象!
如果返回数组,因为在函数内部要new出一个空间复制原来的数据,但是new后不会再自己释放。它不是类的对象,会造成内存泄露!!!!返回类的对象就可以了。
但是这样使用new其实还存在一个问题,就是即如果我想通过这样的下标修改某一块的值时不行,因为是两块内存。不能实现string那样的功能。
2、对+的重载,函数返回值类型不用设为引用,并且注意参数的前后顺序,这里不是加减法,a+b和b+a不一样
3、对+=的重载,函数返回值的类型必须为引用,并且函数内要返回*this。
因为mys+="abc"这句话,相当于是mys.operator(+=)("abc"),要想作用到mys上,必须返回当前对象*this的引用。这和+不一样,+返回的值并不是左值的引用
//#include <cstdlib>
#include <iostream>
using namespace std;
//这里,如果传入的s是个空指针,是会报错的,所以vs现在常常提醒用这些函数不安全
//int strlen(const char * s)
//{
// int i = 0;
// for (; s[i]; ++i);
// return i;
//}
//void strcpy(char * d, const char * s)
//{
// int i = 0;
// for (i = 0; s[i]; ++i)
// d[i] = s[i];
// d[i] = 0;
//
//}
//int strcmp(const char * s1, const char * s2)
//{
// for (int i = 0; s1[i] && s2[i]; ++i) {
// if (s1[i] < s2[i])
// return -1;
// else if (s1[i] > s2[i])
// return 1;
// }
// return 0;
//}
//void strcat(char * d, const char * s)
//{
// //所以说strlen求的是到/0的长度,不是整个数组的长度!!!sizeof才是整个数组的长度
// int len = strlen(d);
// //这里一开始还没有反应过来!!牛逼d+len就是d数组的末尾元素\0
// strcpy(d + len, s);
//}
class MyString
{
// 在此处补充你的代码
size_t len;
char* str = nullptr;
public:
MyString(const char* s)
{
//bug1 ==写成了=。。。。。。。。。
if (s == nullptr)
return;
len = strlen(s);
str = new char[len + 1];
strcpy(str, s);
//bug4 写'\0'或者0都行,但是有一处写成了'/0'......
str[strlen(s)] = '\0';
}
MyString()
{
len = 0;
str = nullptr;
}
~MyString()
{
//一定得判断str是否是空,要不删除一个空指针应该是不行的吧
if (str)
delete[]str;
}
MyString(const MyString& mys)
{
if (mys.str == nullptr)
return;
else
{
len = strlen(mys.str);
str = new char[len + 1];
strcpy(str, mys.str);
}
}
//为什么不加friend只能有一个参数,而加了后就可以有两个参数了?
//因为对cout<<1;这句话,实际是operator<<(cout,1),也就是说<<本来是需要两个参数的。如果把<<重载成一个类的成员函数,则参数减1,其中的一个参数就是类对象本身。加了friend后该函数就不是成员函数了,所以要有两个成员函数
friend ostream& operator<<(ostream& cout, const MyString& s)
{
if (s.str != nullptr)
cout << s.str;
return cout;
}
MyString& operator=(const MyString& mys)
{
if (mys.str == str)
return *this;
else
{
//先把原来的空间给清除掉
if (str)
delete[]str;
len = strlen(mys.str);
str = new char[len + 1];
strcpy(str, mys.str);
}
return *this;
}
//这个+和+=的函数主体不是一样的吗??
MyString operator+(const MyString& mys)
{
//这个判断必须要有吧。。
if (mys.str == nullptr)
return *this;
MyString tempmys;
tempmys.len =len + strlen(mys.str);
tempmys.str = new char[tempmys.len + 1];
//先把原来的赋值给strtemp
strcpy(tempmys.str, str);
strcat(tempmys.str, mys.str);
return tempmys;
}
//bug 2 注意顺序。。。这不是加减法!!!重载的成意思是字符串的拼接,所以*this在前面,s在后面
MyString operator+(const char* s)
{
MyString mys(s);
return *this + mys;
}
friend MyString operator+(const char* s, const MyString& rhs)
{
//存在问题??????????
//明白了,因为这里传入的rhs是常引用,而上面重载的+不是常引用,cao
//MyString mys;
//mys = rhs + s;
//return mys;
MyString mys(s);
return mys + rhs;
}
//bug 3 注意,+=返回的是引用,因为mys+="abc"这句话,相当于是mys.operator(+=)("abc"),要想作用到mys上,必须返回当前对象*this的引用
MyString& operator+=(const char* s)
{
MyString mys(s);
*this = *this + mys;
return *this;
}
//这里不能返回数组,因为这样的话,自己要new出一个空间复制原来的数据,但是new后不会再自己释放,它不是类,不会造成内存泄露!!!!
//但是这样又会存在一个问题,即如果我想通过这样的下标修改某一块的值时不行,因为是两块内存
MyString operator()(int i, int j)
{
MyString mys;
mys.len = j;
char* temps = new char[j+1];
int start = 0;
for (start = 0; start < j; start++)
temps[start] = str[i + start];
temps[start] = 0;
mys.str = temps;
return mys;
}
int operator<(const MyString& rhs)
{
if (strcmp(str, rhs.str) < 0)
return true;
else
return false;
}
int operator==(const MyString& rhs)
{
if (strcmp(str, rhs.str) == 0)
return true;
else
return false;
}
int operator>(const MyString& rhs)
{
if (strcmp(str, rhs.str) > 0)
return true;
else
return false;
}
//这里返回值要为引用
char& operator[](int i)
{
return str[i];
}
};
int CompareString(const void * e1, const void * e2)
{
MyString * s1 = (MyString *)e1;
MyString * s2 = (MyString *)e2;
if (*s1 < *s2)
return -1;
else if (*s1 == *s2)
return 0;
else if (*s1 > *s2)
return 1;
}
int main()
{
MyString s1("abcd-"), s2, s3("efgh-"), s4(s1);
MyString SArray[4] = { "big","me","about","take" };
cout << "1. " << s1 << s2 << s3 << s4 << endl;
s4 = s3;
s3 = s1 + s3;
cout << "2. " << s1 << endl;
cout << "3. " << s2 << endl;
cout << "4. " << s3 << endl;
cout << "5. " << s4 << endl;
cout << "6. " << s1[2] << endl;
s2 = s1;
s1 = "ijkl-";
s1[2] = 'A';
cout << "7. " << s2 << endl;
cout << "8. " << s1 << endl;
s1 += "mnop";
cout << "9. " << s1 << endl;
s4 = "qrst-" + s2;
cout << "10. " << s4 << endl;
s1 = s2 + s4 + " uvw " + "xyz";
cout << "11. " << s1 << endl;
qsort(SArray, 4, sizeof(MyString), CompareString);
for (int i = 0; i < 4; i++)
cout << SArray[i] << endl;
//s1的从下标0开始长度为4的子串
cout << s1(0, 4) << endl;
//s1的从下标5开始长度为10的子串
cout << s1(5, 10) << endl;
return 0;
}