之前看到面试要求有需要当场实现stl容器的内容,就先挑了个最简单的string类来实现。从在此期间重新温习了一遍C++关于类的定义、重载的使用还有友元函数的实现。
类的实现首先是构造和析构函数。构造函数这里要判断一下输入的字符串是否为空,具体构造函数的实现如下:
String::String(const char *str)
{
if(!str)//empty
{
length = 0;
data = new char[1];
*data = '\0';
}
else
{
length = strlen(str);
data = new char[length + 1];
strcpy(data, str);
data[length] = '\0';
}
}
除去构造和析构函数,还要实现一些比较简单的功能,比如+,+=,==,[]等,另外还要支持输入与输出,由于C++已经有了输入流和输出流的函数,只需要重载这两个函数即可实现输入和输出的功能,但是要用到友元。
在这几个功能的实现中,为了避免使用C++高危函数,如strcpy,strcat等,这里改成strncpy,strncat,两个函数与原来的区别是多了一个size_t类型的参数,该参数的作用是限定拷贝的字符数量,可以有效防止越界。有一点要注意的是,使用strncpy后,需要自行在新的字符串的最后加上’\0’。这点需要特别注意。
下面是代码。
#include <iostream>
#include <cstring>
#define BUF 256
using namespace std;
class String
{
size_t length;
char *data;
public:
String(const char *str = NULL);
String(const String &str);
~String();
String operator +(const String &str) const;
String& operator =(const String &str);
String& operator +=(const String &str);
bool operator ==(const String &str) const;
char& operator [](int n) const;
size_t size() const;
const char* c_str() const;
friend istream& operator >>(istream& is, String& str);
friend ostream& operator <<(ostream& os, String& str);
};
String::String(const char *str)
{
if(!str)//empty
{
length = 0;
data = new char[1];
*data = '\0';
}
else
{
length = strlen(str);
data = new char[length + 1];
strcpy(data, str);
data[length] = '\0';
}
}
String::String(const String& str)
{
length = str.size();
data = new char[length + 1];
strncpy(data, str.c_str(), str.size());
}
String::~String()
{
delete []data;
length = 0;
}
inline size_t String::size() const
{
return length;
}
inline const char* String::c_str() const
{
return data;
}
String String::operator+(const String& str) const
{
String newString;
newString.length = length + str.size();
newString.data = new char[newString.size() + 1];
strncpy(newString.data, data, length);
strncat(newString.data, str.data, str.size());
return newString;
}
String& String::operator=(const String& str)
{
delete []data;
length = str.size();
data = new char[str.size() + 1];
strncpy(data, str.c_str(), str.size());
return *this;
}
String& String::operator+=(const String& str)
{
String newString;
newString.length = length + str.size();
newString.data = new char[newString.size() + 1];
strncpy(newString.data, data, length);
//cout << newString.data << endl;
strncat(newString.data, str.c_str(), str.size());
//cout << newString.data << endl;
//strcpy(newString.data, data);
//strcat(newString.data, str.c_str());
delete []data;
length = newString.size();
data = new char[length + 1];
strncpy(data, newString.c_str(), length);
data[length] = '\0'; //这里需要特别特别注意!
cout << data << endl;
return *this;
}
bool String::operator==(const String& str) const
{
if(!strcmp(data, str.c_str()))
{
return true;
}
return false;
}
inline char& String::operator[](int n) const
{
if(n >= length)
{
return data[length - 1];
}
return data[n];
}
istream& operator>>(istream &is, String& str)
{
char *tmp = new char[BUF];
is >> tmp;
str.length = strlen(tmp);
strncpy(str.data, tmp, strlen(tmp));
return is;
}
ostream& operator<<(ostream& os, String& str)
{
os << str.data;
return os;
}