簡體   English   中英

如何在 C++ 中遍歷一個充滿字符串的 std::map

[英]How to iterate over a std::map full of strings in C++

我有以下與迭代使用std::map定義的關聯字符串數組相關的問題。

-- snip --
class something 
{
//...
   private:
      std::map<std::string, std::string> table;
//...
}

在構造函數中,我用與字符串數據關聯的字符串鍵對填充表。 在其他地方,我有一個方法toString返回一個字符串對象,該對象包含表對象中包含的所有鍵和關聯數據(作為鍵=數據格式)。

std::string something::toString() 
{
        std::map<std::string, std::string>::iterator iter;
        std::string* strToReturn = new std::string("");

        for (iter = table.begin(); iter != table.end(); iter++) {
           strToReturn->append(iter->first());
           strToReturn->append('=');
           strToRetunr->append(iter->second());
           //....
        }
       //...
}

當我嘗試編譯時,出現以下錯誤:

error: "error: no match for call to ‘(std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >) ()’".

有人可以向我解釋缺少什么,我做錯了什么? 我只在hash_map的情況下發現了一些關於類似問題的討論,其中用戶必須定義​​一個散列函數才能將hash_mapstd::string對象一起使用。 在我的情況下也可能有類似的東西嗎?

您的主要問題是您在迭代器中調用了一個名為first()的方法。 您要做的是使用名為first的屬性:

...append(iter->first) rather than ...append(iter->first())

就風格而言,您不應該使用new來創建該字符串。

std::string something::toString() 
{
        std::map<std::string, std::string>::iterator iter;
        std::string strToReturn; //This is no longer on the heap

        for (iter = table.begin(); iter != table.end(); ++iter) {
           strToReturn.append(iter->first); //Not a method call
           strToReturn.append("=");
           strToReturn.append(iter->second);
           //....
           // Make sure you don't modify table here or the iterators will not work as you expect
        }
        //...
        return strToReturn;
}

編輯: facildelembrar 指出(在評論中)在現代 C++ 中,您現在可以重寫循環

for (auto& item: table) {
    ...
}
  1. 不要編寫toString()方法。 這不是Java。 為您的類實現流運算符。

  2. 更喜歡使用標准算法而不是編寫自己的循環。 在這種情況下, std::for_each()為您想要做的事情提供了一個很好的接口。

  3. 如果您必須使用循環,但不打算更改數據,則更喜歡const_iterator不是iterator 這樣,如果您不小心嘗試更改值,編譯器會警告您。

然后:

std::ostream& operator<<(std::ostream& str,something const& data)
{
    data.print(str)
    return str;
}

void something::print(std::ostream& str) const
{
    std::for_each(table.begin(),table.end(),PrintData(str));
}

然后當你想打印它時,只需流式傳輸對象:

int main()
{
    something    bob;
    std::cout << bob;
}

如果您確實需要對象的字符串表示形式,則可以使用lexical_cast

int main()
{
    something    bob;

    std::string  rope = boost::lexical_cast<std::string>(bob);
}

需要填寫的詳細信息。

class somthing
{
    typedef std::map<std::string,std::string>    DataMap;
    struct PrintData
    {
         PrintData(std::ostream& str): m_str(str) {}
         void operator()(DataMap::value_type const& data) const
         {
             m_str << data.first << "=" << data.second << "\n";
         }
         private:  std::ostream& m_str;
    };
    DataMap    table;
    public:
        void something::print(std::ostream& str);
};

更改您的 append 調用以說

...append(iter->first)

... append(iter->second)

此外,該行

std::string* strToReturn = new std::string("");

在堆上分配一個字符串。 如果您打算實際返回指向此動態分配字符串的指針,則返回值應更改為 std::string*。

或者,如果您不想擔心在堆上管理該對象,請將本地聲明更改為

std::string strToReturn("");

並更改“追加”調用以使用參考語法...

strToReturn.append(...)

代替

strToReturn->append(...)

請注意,這將在堆棧上構造字符串,然后復制到返回變量中。 這對性能有影響。

iter->firstiter->second是變量,您試圖將它們作為方法調用。

請注意,取消引用 std::map::iterator 的結果是std::pair firstsecond的值不是函數,它們是變量。

改變:

iter->first()

iter->first

同上iter->second

采用:

std::map<std::string, std::string>::const_iterator

反而:

std::map<std::string, std::string>::iterator

在 C++11 中,您可以使用:

for ( auto iter : table ) {
     key=iter->first;
     value=iter->second;
}

另一個有價值的優化是 STL字符串類的c_str ( )成員,它返回一個不可變的空終止字符串,該字符串可以作為LPCTSTR傳遞,例如,傳遞給需要LPCTSTR的自定義函數。 雖然我還沒有通過析構函數進行追蹤以確認它,但我懷疑字符串類會照顧它創建副本的內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM