面向对象程序设计第二次实验课——mystring类实现

来源:互联网 发布:淘宝电击棍 编辑:程序博客网 时间:2024/05/16 05:36
#pragma once#include <cstring>#include <iostream>using namespace std;const size_t MAX_CHAR_IN_NODE = 100;// 定义链块 struct Node {    char s[MAX_CHAR_IN_NODE];    Node *next;};class myString;myString operator+ (const myString& lhs, const myString& rhs);class myString {    friend myString operator+ (const myString& lhs, const myString& rhs);    friend ostream& operator<< (ostream& out, const myString& rhs);    public:        myString(void);        myString(const char *s);        myString(const myString& ms);        ~myString(void);        myString& operator= (const myString& rhs);        myString& operator+= (const myString& rhs);        const char& operator[] (size_t index) const;        char& operator[] (size_t index);        myString operator() (size_t l, size_t r) const;        size_t len(void) const {return len_;}    private:        Node *head_; // 链块头指针         size_t cntNode_; // the num of Node        size_t len_; // the length of string};
#include "myString.h"ostream& operator<< (ostream& out, const myString& rhs){    for (Node *p = rhs.head_; p; p = p -> next) {        for (size_t i = 0; i < MAX_CHAR_IN_NODE; i ++)            if (p->s[i] != '\0')                cout << p -> s[i];            else                 break;    }    return out;}myString operator+ (const myString& lhs, const myString& rhs){    myString ret(lhs);    ret += rhs;    return ret;} myString::myString(void) : cntNode_(1), len_(0) {    head_ = new Node;    head_ -> s[0] = '\0';    head_ -> next = NULL;}myString::myString(const myString& ms) :     cntNode_(ms.cntNode_), len_(ms.len_){    // 创建链块     head_ = new Node;    head_ -> next = NULL;    Node *q = head_;    for (size_t i = 1; i < cntNode_; i ++) {        Node *p = new Node;        q -> next = p;        p -> next = NULL;        q = q -> next;    }    // 进行拷贝     for (Node *p = head_, *q = ms.head_; q; p = p -> next, q = q -> next) {        strcpy(p->s, q->s);    }}myString::myString(const char *s){    // 计算参数     len_ = strlen(s);    cntNode_ = (len_ + 1) / MAX_CHAR_IN_NODE;    if ((len_ + 1) % MAX_CHAR_IN_NODE) ++ cntNode_;    // 创建链块     head_ = new Node;    head_ -> next = NULL;    Node *q = head_;    for (size_t i = 1; i < cntNode_; i ++) {        Node *p = new Node;        q -> next = p;        p -> next = NULL;        q = q -> next;    }      // 进行拷贝     size_t cnt = 0;    for (Node *p = head_; p; p = p -> next, cnt += 100) {        for (size_t i = 0; i < MAX_CHAR_IN_NODE; i ++) {            if (s[i + cnt] != '\0')                p->s[i] = s[i + cnt];            else {                p->s[i] = '\0';                break;            }        }    }}myString::~myString(void){    Node *p = head_;    for (Node *q = head_ -> next; q; p = q, q = q -> next) {        delete p;    }    delete p;}myString& myString::operator= (const myString& rhs){    if (this != &rhs) {        len_ = rhs.len_;        cntNode_ = rhs.cntNode_;        head_ = new Node;        head_ -> next = NULL;        Node *q = head_;        for (size_t i = 1; i < cntNode_; i ++) {            Node *p = new Node;            q -> next = p;            p -> next = NULL;            q = q -> next;        }        for (Node *p = head_, *q = rhs.head_; q; p = p -> next, q = q -> next) {            strcpy(p->s, q->s);        }    }    return *this;}myString& myString::operator+= (const myString& rhs){    if (rhs.len_ == 0) return *this;      // 计算参数     size_t loc = (len_) % MAX_CHAR_IN_NODE;    len_ = len_ + rhs.len_;    size_t preCntNode_ = cntNode_;    cntNode_ = (len_ + 1) / MAX_CHAR_IN_NODE;    if ((len_ + 1) % MAX_CHAR_IN_NODE) ++ cntNode_;    Node *p = head_;    for (Node *q = head_ -> next; q; p = q, q = q -> next) ; //空循环,寻找拷贝的位置     // 如果需要额外空间,申请之     Node *r = p;    for (size_t i = preCntNode_; i < cntNode_; i ++) {        Node *q = new Node;        q -> next = NULL;        p -> next = q;        p = p -> next;    }     // 进行拷贝     p = r;    for (Node *q = rhs.head_; q; q = q -> next) {        for (size_t i = 0; i < MAX_CHAR_IN_NODE; i ++) {            if (q->s[i] != '\0')                p->s[loc ++] = q->s[i];            else {                p->s[loc] = '\0';                break;            }             if (loc == MAX_CHAR_IN_NODE) {                loc = 0;                p = p -> next;            }        }    }     return *this;}char& myString::operator[] (size_t index){    if (index < len_) {        size_t block = index / MAX_CHAR_IN_NODE;        size_t loc = index % MAX_CHAR_IN_NODE;        size_t i = 0;        Node *p;        for (p = head_; i < block; p = p->next, ++ i) ;//空循环        return p -> s[loc];     } else {        // 越界返回第一个         return head_ -> s[0];    }}const char& myString::operator[] (size_t index) const{    if (index < len_) {        size_t block = index / MAX_CHAR_IN_NODE;        size_t loc = index % MAX_CHAR_IN_NODE;        size_t i = 0;        Node *p;        for (p = head_; i < block; p = p->next, ++ i) ;//空循环        return p -> s[loc];     } else {        return head_ -> s[0];    }}myString myString::operator() (size_t l, size_t r) const{    if (l >= 1 && r <= len_ && l <= r) {        char *s = new char[r - l + 2];        for (size_t i = 0; i < r - l + 1; i ++) {            s[i] = (*this)[l + i - 1];        }        s[r - l + 1] = '\0';        myString ret(s);        delete []s;        return ret;    } else {        return myString();    }}
#include <iostream>#include <string>#include "myString.h"using namespace std;/* run this program using the console pauser or add your own getch, system("pause") or input loop */int main(int argc, char** argv) {    myString s1;    cout << s1 << endl;    myString s2("hello");    cout << s2 << endl;    s1 += s2;    cout << s1 << endl;    cout << s1 + s2 << endl;    cout << s1[1] << endl;    cout << endl << endl;    cout << endl;    myString m("Software");    myString n(m),o;    o = m;    cout << n[4] << endl;    cout << n.len() << endl;    o = m + n;    cout << o << endl;     o = m(2,8);    cout << o << endl;    const myString s10(m);    cout << s10[4] << endl;     myString s("10110111011110111110111111011111110111111110111111111011111111110111111111110111111111111011111111111110");    cout << s[101] << endl;    cout << s.len() << endl;    cout << s << endl;    myString ss(s);    cout << ss << endl;    cout << ss + s << endl;    return 0;}

第二次实验报告
一、 题目分析
myString m(“Software”);
myString n(m),o;
o = m;
cout << n[4] << endl;
cout << n.len() << endl;
o = m + n;
cout << o << endl;
o = m(2,8);
cout << o << endl;

ppt上的代码已经很清楚的说明了这次实验的要求,显然,就算没有要求,一个类也应该提供默认构造函数、拷贝构造函数、=运算符重载以及析构函数。此外,由第一行可以得出,应该有一个参数为C风格字符串的构造函数。第四行说明应该重载下标运算符,第五行要求有一个成员len,可以返回字符串长度,第六行要求重载+运算符,第八行要求重载函数调用运算符,返回字符串的一个子串。

二、 主要流程
首先,定义了一个结构体Node,作为myString类中使用的链块,为了使myString类可以适应各类不同长度的字符串,myString类中使用链块作为数据结构存储字符串。

const size_t MAX_CHAR_IN_NODE = 100;
// 定义链块
struct Node {
char s[MAX_CHAR_IN_NODE];
Node *next;
};

接下来是三个构造函数:
myString(void);
myString(const char *s);
myString(const myString& ms);
构造函数之间并没有委托构造关系,myString(const myString& ms) 调用了strcpy函数。

析构函数:
~myString(void);
析构函数负责释放申请的链块的空间。

=运算符重载:
myString& operator= (const myString& rhs);
其同样调用了strcpy函数。

+、+=运算符重载:
myString& operator+= (const myString& rhs);
friend myString operator+ (const myString& lhs, const myString& rhs);
首先实现+=,在+中调用+=。

[]运算符重载:
const char& operator[] (size_t index) const;
char& operator[] (size_t index);
实现了常量版本和非常量版本,互相没有调用关系。

()运算符重载:
myString operator() (size_t l, size_t r) const;
调用了下表运算符函数。

三、 程序难点
1. 实现任意长度的myString类
这里借鉴了stl里string类的思想,使用了链块作为数据结构,当然这也加大了程序实现的难度,在构造、修改、析构的时候都需要考虑到各种情况。
2. +,[]的重载
由于实现方式是链块,在做加法运算时就要重新计算加法后字符串的长度,并基于此决定是否需要更多空间。由于使用了链块,本来容易的取下标操作也变得不那么简单了,需要定位到字符所在的链块,再将其中的某一空间返回。

四、 优点与缺点
1. 优点:
a) 实现了myString类的任意长度的要求
b) 按照要求实现了所有功能
c) 重载了<<运算符,便于输出和调试
2. 缺点:
a) 没有重载关系预算符
b) 由于用到了链块,降低了程序效率
c) 部分代码被多次重用,而没有将其抽象成私有方法

五、 收获
第一次写链块,成功的写出来了还是很开心的,更加深入的了解了stl中string的内部原理,一步一步将C风格字符串封装成了string类型并实现了部分功能。第一次尝试重载()运算符,对于仿函数有了更深入的了解

0 0
原创粉丝点击