数据结构开发(7):典型问题分析(Bugfix)

0.目录

1.创建异常对象时的空指针问题

6.StLib 是否有必要增加多维数组类?

1.创建异常对象时的空指针问题

ISSUE 1——创建异常对象时的空指针问题:

改进Exception.cpp:
在init函数中改进strdup的赋值方法

void Exception::init(const char* message, const char* file, int line)
{
    /* message指向的字符串有可能在栈上,有可能在堆空间,还有可能在全局数据区
     * strdup()将字符串复制一份到堆空间中
     * file:发生异常的文件名
     * line:发生异常的行号
     * m_location的长度加2,一个给":",一个给"\0"
     */
    m_message = (message ? strdup(message) : NULL);

    if( file != NULL )
    {
        char sl[16] = {0};

        itoa(line, sl, 10);

        m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));

        if( m_location != NULL )
        {
            m_location = strcpy(m_location, file);
            m_location = strcat(m_location, ":");
            m_location = strcat(m_location, sl);
        }
    }
    else
    {
        m_location = NULL;
    }
}

ISSUE 2——LinkList 中的数据元素删除:

单链表的实现没有考虑异常安全性!
改进LinkList.h中的remove函数和clear函数:

    bool remove(int i)
    {
        bool ret = ((0 <= i) && (i < m_length));

        if( ret )
        {
            Node* current = position(i);
            Node* toDel = current->next;

            current->next = toDel->next;

            m_length--;
            
            destroy(toDel);
        }

        return ret;
    }

    void clear()
    {
        while ( m_header.next )
        {
            Node* toDel = m_header.next;

            m_header.next = toDel->next;
            
            m_length--;

            destroy(toDel);
        }
    }

ISSUE 3——LinkList 中遍历操作与删除操作的混合使用:

混合使用导致了m_current指向了已经被删除的结点,于是程序出错。
改进LinkList.h中的remove函数:

    bool remove(int i)
    {
        bool ret = ((0 <= i) && (i < m_length));

        if( ret )
        {
            Node* current = position(i);
            Node* toDel = current->next;

            if( m_current == toDel )
            {
                m_current = toDel->next;
            }

            current->next = toDel->next;

            m_length--;

            destroy(toDel);
        }

        return ret;
    }

main.cpp测试

#include <iostream>
#include "LinkList.h"

using namespace std;
using namespace StLib;

int main()
{
    LinkList<int> list;

    for(int i=0; i<5; i++)
    {
        list.insert(i);
    }

    for(list.move(0); !list.end(); list.next())
    {
        if( list.current() == 3 )
        {
            list.remove(list.find(list.current()));

            cout << list.current() << endl;
        }
    }

    for(int i=0; i<list.length(); i++)
    {
        cout << list.get(i) << endl;
    }

    return 0;
}

运行结果为:

4
0
1
2
4

ISSUE 4——StaticLinkList 中数据元素删除时的效率问题:

改进LinkList.h中的destroy函数:

    void destroy(Node* pn)
    {
        SNode* space = reinterpret_cast<SNode*>(m_space);
        SNode* psn = dynamic_cast<SNode*>(pn);

        for(int i=0; i<N; i++)
        {
            if( psn == (space + i) )
            {
                m_used[i] = 0;
                psn->~SNode();
                break;
            }
        }
    }

main.cpp测试

#include <iostream>
#include "StaticLinkList.h"

using namespace std;
using namespace StLib;

int main()
{
    StaticLinkList<int, 10> list;

    for(int i=0; i<5; i++)
    {
        list.insert(i);
    }

    list.remove(3);

    for(int i=0; i<list.length(); i++)
    {
        cout << list.get(i) << endl;
    }

    return 0;
}

运行结果为:

0
1
2
4

ISSUE 5——StaticLinkList 是否需要提供析构函数?:

构造函数与析构函数不会发生多态,于是调用的是父类的析构函数!
改进StaticLinkList.h:
在子类StaticLinkList中实现析构函数:

    ~StaticLinkList()
    {
        this->clear();
    }

6.StLib 是否有必要增加多维数组类?

ISSUE 6——StLib 是否有必要增加多维数组类?
多维数组的本质:数组的数组!

不需要定义多维数组!

使用DynamicArray创建多维数组:

#include <iostream>
#include "DynamicArray.h"

using namespace std;
using namespace StLib;

int main()
{
    DynamicArray< DynamicArray<int> > d;

    d.resize(3);

    for(int i=0; i<d.length(); i++)
    {
        d[i].resize(i + 1);
    }

    for(int i=0; i<d.length(); i++)
    {
        for(int j=0; j<d[i].length(); j++)
        {
            d[i][j] = i * j;
        }
    }

    for(int i=0; i<d.length(); i++)
    {
        for(int j=0; j<d[i].length(); j++)
        {
            cout << d[i][j] << " ";
        }

        cout << endl;
    }

    return 0;
}

运行结果为:

0 
0 1 
0 2 4 

实践经验:

  • 是软件就有bug因此需要不停的迭代升级,解决问题。库是一种特殊的软件产品也会存在各种bug,也需要迭代升级,解决问题。
posted @ 2018-12-15 15:19  PyLearn  阅读(378)  评论(0编辑  收藏  举报