您的位置:首页 > 编程语言 > C语言/C++

C++ - string 基本版

2015-10-03 21:43 681 查看
真正去了解如何写一个string类的时候,发现有好多知识点。

复制控制(复制构造函数、赋值操作符、析构函数)

运算符重载(+, ==, !=, <, <=, >, >=, +=, []等等)

深拷贝(对于字符串拷贝的处理)

友元(cin, cout)

内联函数(为了提高效率,这些函数都是内联函数)

const的用法(返回值为常量、常量函数、输入为常量)

引用(输入为引用、返回值为引用(如+, []))

异常安全(operator=)

这些也还只是基本版的内容,还有

隐式共享写时拷贝(智能指针)

C++11的右值引用、Move语义

iterator

gcc中string(basic_string)的写法又是另外一种层面的东西了……

本文给出基本版的代码

#include <iostream>
#include <vector>
#include <string>
#include <iomanip> // setw
#include <cstdio>
using namespace std;

class MyString { // inline
public:
// constructor
MyString(const char* str = NULL);
MyString(const MyString&);
MyString(size_t, char); // ? memset?
// destructor
~MyString();

bool empty();
size_t size() const; // string::size_type?

const char* c_str() const;
void swap(MyString&);
// operator +, ==, !=, <, <=, >, >=, +=
char& operator[](size_t); // unsigned int??
MyString& operator=(const MyString&);
MyString operator+(const MyString&) const;
bool operator==(const MyString&);
// friend istream, ostream
friend istream& operator>>(istream&, MyString&);
friend ostream& operator<<(ostream&, MyString&);
private:
char *m_data;

};

int main() {
MyString mstr, s1, s2;
cin >> mstr;
cout << mstr << endl;
mstr[0] = 'k';
cout << mstr << endl;
s1 = s2 = mstr;
s2[2] = '3';
cout << s1 << " " << (s1 == s2) << " " << s2 << endl;
MyString s3(10, 'm');
cout << s3 << endl;
return 0;
}
inline MyString::MyString(const char* str) {
// error C2572: “MyString::MyString”: 重定义默认参数 : 参数 1  // 去掉 = NULL
if (!str) {
m_data = new char[1];
m_data[0] = '\0';
}
else {
m_data = new char[strlen(str) + 1];
strcpy(m_data, str);
}
}
inline MyString::MyString(const MyString &object) {
m_data = new char[object.size() + 1];
strcpy(m_data, object.c_str());
}
inline MyString::MyString(size_t n, char ch) {
m_data = new char[n + 1];
memset(m_data, ch, n);
m_data
= '\0';
}
inline MyString::~MyString() {
delete []m_data;
}
size_t MyString::size() const {
return strlen(m_data);
}
const char* MyString::c_str() const {
return m_data;
}

void MyString::swap(MyString &rhs) {
std::swap(m_data, rhs.m_data);
}

char& MyString::operator[](size_t i) {
// 考虑错误处理
return m_data[i];
}
MyString& MyString::operator=(const MyString& rhs) {
if (this != &rhs) {
MyString temp(rhs);
swap(temp);
}
return *this;
}
bool MyString::operator==(const MyString& rhs) {
return strcmp(m_data, rhs.c_str()) ? false : true;
}
MyString MyString::operator+(const MyString& rhs) const {
MyString newS;
//if (!rhs.m_data) { // 不可能为NULL
//  newS = *this;
//}
//else if (!this->m_data) {
//  newS = rhs.m_data;
//}
//else {
newS.m_data = new char[size() + rhs.size() + 1];
strcpy(newS.m_data, m_data);
strcat(newS.m_data, rhs.m_data);
//}
return newS;
}

istream& operator>>(istream& in, MyString& rhs) {
// 第一种方法:字符串长度受限
//char temp[255];
//in >> setw(255) >> temp;
////rhs = MyString(temp); // ok
//rhs = temp;
////strcpy(rhs.m_data, temp); // ??有问题,确实有问题,m_data并没有分配空间,因此也可以先分配空间再拷贝
//return in;

// 第二种方法:字符串长度不受限,但在个别情况下有bug,详见注释
//const int BUFFER_SIZE = 255; // 可以以5来做测试
//char buffer[BUFFER_SIZE];
//char *end = buffer + BUFFER_SIZE - 1;
//rhs = ""; // clear
//do {
//  *end = '#';
//  //in >> setw(BUFFER_SIZE) >> buffer; // 如果输入恰好是BUFFER_SIZE - 1,则会出问题
//  //in.get(buffer, BUFFER_SIZE); // 并不能以空格分隔,直接输入换行也会出问题,暂时还不清楚为什么?难道是因为get了两次?
//  in.get(buffer, BUFFER_SIZE, ' '); // 如果以空格分隔,又不能识别换行
//  rhs += buffer;
//} while (*end == '\0');
//in.get();
//// http://www.cplusplus.com/reference/istream/istream/get/ //// The delimiting character is not extracted from the input sequence if found,
//// and remains there as the next character to be extracted from the stream (see
//// getline for an alternative that does discard the delimiting character).
//return in;

// 第三种方法:单字符处理,尝试get(char &c)
const int BUFFER_SIZE = 255; // 可以以5来做测试
char buffer[BUFFER_SIZE];
int i = 0;
char ch;
rhs = "";
// 标准输入流忽略空格和\n // http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ do {
in.get(ch);
} while (ch == ' ' || ch == '\n');

while (true) {
if (ch == ' ' || ch == '\n') {
buffer[i] = '\0';
rhs += buffer;
break;
}
else {
buffer[i++] = ch;
if (i == BUFFER_SIZE - 1) {
buffer[i] = '\0';
rhs += buffer;
i = 0;
}
}
in.get(ch);
}
return in;
}
ostream& operator<<(ostream& out, MyString& rhs) {
out << rhs.m_data;
return out;
}


最后附上一些参考资料。

STL 的string类怎么啦?

意图(Intention)、规格(Specification)、实现(Implementation)

标准C++类string的Copy-On-Write技术(一)

引用计数器(智能指针)

C++面试中string类的一种正确写法

C++ string实现原理

C++ string类的隐式共享写时拷贝的实现及设计要点

C++中String类的实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ string 实现