天天看點

Cocos2dx 小技巧(十六)再談visit(getDescription)

之前兩篇都是介紹與Value相關的,這篇我繼續這個話題吧,正好湊個“ Value三闆斧系列...”。

在很久很久以前,我用寫過一篇部落格,關于如何檢視CCArray與CCDictionary裡存放的元素: http://blog.csdn.net/star530/article/details/23877429

現在既然它倆已經都是過去式了,那麼之前的檢視方法肯定也是不能用了。而Value作為它們的替代者之一,自然也有它檢視元素的方法,那就是 getDescription()這個接口,下面我簡單舉個例子:

Value a(10);
std::string a_str = a.getDescription();
CCLOG("a = %s",a_str.c_str());//列印出 a 對應的值
           

下面看下程式運作結果,輸出如下資訊:

Cocos2dx 小技巧(十六)再談visit(getDescription)

看輸出好像沒什麼問題,但這裡有個疑問, 為什麼 a = 與 10沒有在同一行呢?

在getDescription()這個接口裡,到底發生了慘絕人寰的事?帶着疑問與好奇,我們到getDescription()的定義裡一探虛實。

std::string Value::getDescription()
{
    std::string ret("\n");//插入換行符
    ret += visit(*this, 0);
    return ret;
}
           

看完代碼才發現, 原來在傳回的字元串裡先插入一個 "\n" 換行符。

我們的故事本來到這裡應該結束了,但總有些強迫症的孩子心裡有點疙瘩,既然都看到這了,幹嘛不再看看 visit(*this, 0) 這個函數都做了些什麼呢?

好吧,既然你都這樣求我了,那...我們繼續往下看:

static std::string visit(const Value& v, int depth)
{
    std::stringstream ret;//建立一個字元串流
	
	//判斷Value内元素的類型
    switch (v.getType())
    {
        case Value::Type::NONE:
        case Value::Type::BYTE:
        case Value::Type::INTEGER:
        case Value::Type::FLOAT:
        case Value::Type::DOUBLE:
        case Value::Type::BOOLEAN:
        case Value::Type::STRING:
            ret << v.asString() << "\n";//如果是上面這幾種類型,那麼直接将其轉換成string型即可。
            break;
        case Value::Type::VECTOR:
            ret << visitVector(v.asValueVector(), depth);
            break;
        case Value::Type::MAP:
            ret << visitMap(v.asValueMap(), depth);
            break;
        case Value::Type::INT_KEY_MAP:
            ret << visitMap(v.asIntKeyMap(), depth);
            break;
        default:
            CCASSERT(false, "Invalid type!");
            break;
    }
    
    return ret.str();
}
           

上述代碼我沒有做過多的注釋,我們隻要注意兩點:

1、普通的資料類型,如int,string等,可以直接轉成string型(asString())後放入ret流中即可。而如果元素類型是Vector或者Map,則需要做進一步的處理;

2、visit(const Value& v, int depth) 這個函數的第二個參數 depth是個什麼玩意?眼尖的我發現進一步處理Vector類型的元素時,調用到visitMap(v.asValueMap(), depth)這個函數,而depth正好是該函數的第二個參數。

帶着疑惑,我們繼續:

static std::string visitVector(const ValueVector& v, int depth)
{
    std::stringstream ret;
    
    if (depth > 0)
        ret << "\n";
    
    ret << getTabs(depth) << "[\n";
    
    int i = 0;
    for (const auto& child : v)
    {
        ret << getTabs(depth+1) << i << ": " << visit(child, depth + 1);//在這裡讀取Vector中的元素
        ++i;
    }
    
    ret << getTabs(depth) << "]\n";
    
    return ret.str();
}
           

這函數乍看一下有點莫名其妙,其實我們隻要知道 getTabs(int depth)這個函數是怎麼回事就可以,其他自然迎刃而解。

static std::string getTabs(int depth)
{
    std::string tabWidth;
    
    for (int i = 0; i < depth; ++i)
    {
        tabWidth += "\t";//插入一個制表符
    }
    
    return tabWidth;
}
           

原來getTabs()的功能就是插入制表符啊(所謂制表符就是tab鍵),而傳入的參數depth是多少就添加多少個制表符。

好了,流程就是這樣子,我想很多人現在腦袋瓜子都還蒙蒙的,沒事,下面我舉個栗子,然後小夥伴們根據程式的輸出結果與上面提到的visit()、visitVector()的代碼參照下。

Value a(10);
Value b("star is so cool");
ValueVector star_vec;
star_vec.push_back(a);
star_vec.push_back(b);
//将ValueVector類型轉成Value類型才可調用getDescription()
std::string star_str = ( (Value)star_vec ).getDescription();
CCLOG("-----------------------");
CCLOG("%s",star_str.c_str());
CCLOG("-----------------------");
           

程式運作後,輸出結果如下:

Cocos2dx 小技巧(十六)再談visit(getDescription)

好了,就醬紫吧,能不能了解就看閣下的悟性了。

尊重原創,轉載請注明來源:http://blog.csdn.net/star530/article/details/38071517