yinjun66的博客

努力学习

用C++的STL部分实现Python中的list(列表)

本来准备来实现一个简单的python的shell交互器,现在只完成了python中几个数据结构的实现,目前正在啃编译原理,等编译原理啃完了再继续回来实现pytyon的shell。
写的有点乱哈~~
Github有详细的代码:achievePythonShell
实现的思想:
Python中的列表是个神奇的数据结构,也是Python中最学用的一个数据结构(个人认为),它能存放各个类型的数据,lst1=[1,2,2.3,”string”];它的数据元素还能是列表,lst2=[1,2,2.3,”string”,[2,3,’sdf’]],这个也是我在实现的时候最难的一点,因为它能放列表,列表的列表,列表的列表的列表……
所以我先定义了一个Type类,把列表中的元素都放到Type类中,这样列表就可以用vector来进行操作。

class Type
{
    public:
    float value;//用来存放int或float类型的数据
    string val_str;//用来存放字符串类型数据
    int type;//用来表示数据的类型,因为python中没有类型,0代表整形,1代表浮点型,2代表字符串类型
     Type(float v=0,string vs="", int t=0) :value(v), type(t) {//在python中把字符串都加上‘’,在构造函数里实现
        if (t == STRING)
        {
            vs = "'" + vs + "'";
            val_str = vs;
        }
}

那如果元素要是一个列表,即[1,2,[3,4]]中的[3,4]用什么来表示呢?想了很久 ,最后把这个[3,4]看成是一个字符串”[3,4]”存放在Type中的val_str里,同时type的值为2(字符串类型)+括号的层数。
比如:元素[3,4]可以表达为Type(0,”[3,4]”,2+1),其中type=2+1;
元素[[3,4],5]可以表达为Type(0,”[[3,4],3]”,2+2),其中type=2+2;
如果要访问里的元素怎么办呢?要访问上面的
Type(0,”[[3,4],3]”,4);中的元素3怎么访问呢?我的解决方法就在Type里面重载operatro[]访问“[[3,4],3]”里面的元素.

Type Type::operator[](int index)//不能返回引用
{
    if (type < 2)//int float and string has no operator[]
    {
        cout << "\tthis type has no attritute" << endl;
        exit(-1);
    }
    if (type == 2)
    {
        string temp_s = "";
        temp_s = "'" + val_str[index];
        temp_s += "'";
        Type ty = Type(0.0, temp_s, STRING);
        ty.plast = &val_str;
    }
    //type>=3时,val_str不为空
    vector<char>bracket;//括号栈,当括号栈为空时索引才加1
    int i = 1;//从第一个中括号开始
    bool flag = true;//判断是否有语法错误
    int cur_index = -1;//当前索引
    string ele = "";//记录当前的元素
    int bracket_maxnum = 0;//括号层数
    while (flag&&i < val_str.size() && cur_index<index)
    {
        char ch = val_str[i];
        if (i == val_str.size() - 1)
            ch = ',';
        switch (ch)
        {
        case '[':
            bracket.push_back('[');
            if (bracket.size() > bracket_maxnum)
                bracket_maxnum = bracket.size();
            ele += '[';
            break;
        case ']':
            if (!bracket.empty() && bracket.back() == '[')
                bracket.pop_back();
            else
                flag = false;
            ele += ']';
            break;
        case ',':
            if (ele == "")
            {
                flag = false;
                break;
            }
            if (bracket.empty())
            {
                cur_index++;
                if (cur_index < index)
                {
                    bracket_maxnum = 0;
                    ele = "";
                }
            }
            else
                ele += ',';
            break;
        default:
            ele += ch;
            break;
        }
        i++;
    }
    if (!flag)//出现语法错误
    {
        cout << "\terror syntax!" << endl;
        exit(-1);
    }
    else if (cur_index == index)//找到指定索引元素
    {
        Type temp_t;
        temp_t.plast = &val_str;
        if (judgeValueType(ele) == INTEGER || judgeValueType(ele) == FLOAT)
        {
            stringstream ss(ele);
            ss >> temp_t.value;
            temp_t.type = judgeValueType(ele);
        }
        else if (judgeValueType(ele) == STRING)
        {
            //removeSymbol(ele,"\"");
            //removeSymbol(ele,"'");
            temp_t.val_str = ele;
            temp_t.type = STRING;
        }
        else
        {
            temp_t.val_str = ele;
            temp_t.type = OFFSET + bracket_maxnum;
        }
        return temp_t;
    }
    else
    {
        cout << "\terror index!" << endl;
        exit(-1);
    }
}

里面用到了judgeValueType()函数,这个函数是自己定义的判断数据类型的函数,因为Python中的数据类型要自己判断
这样:Type ty=Type(0,”[[3,4],3]”);我就能通过ty[1]来访问其中的元素3了。
接下来又有个问题,我重写的operator[]只是单纯返回了一个值,没有返回引用!就实现不了ty[1]=3;来改变值了,那怎么解决呢?
因为整个列表元素在一个字符串类型,而要改变可能要改变它的字串,改变字串的同时还要改变整个列表中对应的元素。于是我在Type类中添加了一个成员,是保存上原来Type中的val_str的指针,通过它就能有返回引用的效果了。

class Type//Python中的所有函数都用这个类型
{
private:
    string *plast;//用在operator[]中达到引用的效果,指向父串的内存;是opertor[]返回则非空,否则返回空
public:
    string val_str;//存放string类型 
    float value;//存放float和int类型
    int type;
    Type(float v=0,string vs="", int t=0) :value(v), type(t) {//在python中把字符串都加上‘’,在构造函数里实现
        if (t == STRING)
        {
            vs = "'" + vs + "'";
            val_str = vs;
        }
        plast = NULL;
    }
    }
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yinjun66/article/details/70890412
个人分类: C++
上一篇C++内存存储区域:堆区栈区以及new delete
下一篇系统调用fork()函数
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭