如何在 C++ 中遍历一个充满字符串的 std::map

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1066677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:39:49  来源:igfitidea点击:

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

c++dictionaryiteratorstdstdmap

提问by crazybyte

I have the following issue related to iterating over an associative array of strings defined using std::map.

我有以下与迭代使用std::map.

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

In the constructor I populate table with pairs of string keys associated to string data. Somewhere else I have a method toStringthat returns a string object that contains all the keys and associated data contained in the table object(as key=data format).

在构造函数中,我用与字符串数据关联的字符串键对填充表。在其他地方,我有一个方法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());
           //....
        }
       //...
}

When I'm trying to compile I get the following error:

当我尝试编译时,出现以下错误:

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

Could somebody explain to me what is missing, what I'm doing wrong? I only found some discussion about a similar issue in the case of hash_mapwhere the user has to define a hashing function to be able to use hash_mapwith std::stringobjects. Could be something similar also in my case?

有人可以向我解释缺少什么,我做错了什么?hash_map在用户必须定义​​散列函数才能hash_mapstd::string对象一起使用的情况下,我只发现了一些关于类似问题的讨论。在我的情况下也可能有类似的东西吗?

回答by Tom Leys

Your main problem is that you are calling a method called first()in the iterator. What you are meant to do is use the property called first:

您的主要问题是您正在调用first()迭代器中调用的方法。您要做的是使用名为 的属性first

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

As a matter of style, you shouldn't be using newto create that string.

作为风格问题,您不应该使用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;
}

edit:facildelembrar pointed out (in the comments) that in modern C++ you can now rewrite the loop

编辑:facildelembrar 指出(在评论中)在现代 C++ 中,您现在可以重写循环

for (auto& item: table) {
    ...
}

回答by Martin York

  1. Don't write a toString()method. This is not Java. Implement the stream operator for your class.

  2. Prefer using the standard algorithms over writing your own loop. In this situation, std::for_each()provides a nice interface to what you want to do.

  3. If you must use a loop, but don't intend to change the data, prefer const_iteratorover iterator. That way, if you accidently try and change the values, the compiler will warn you.

  1. 不要写toString()方法。这不是Java。为您的类实现流运算符。

  2. 更喜欢使用标准算法而不是编写自己的循环。在这种情况下,std::for_each()为您想要做的事情提供了一个很好的界面。

  3. 如果你必须使用一个循环,但不打算更改数据,更喜欢const_iteratoriterator。这样,如果您不小心尝试更改值,编译器会警告您。

Then:

然后:

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));
}

Then when you want to print it, just stream the object:

然后当你想打印它时,只需流式传输对象:

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

If you actually need a string representation of the object, you can then use lexical_cast.

如果您确实需要对象的字符串表示形式,则可以使用lexical_cast.

int main()
{
    something    bob;

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

The details that need to be filled in.

需要填写的详细信息。

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);
};

回答by Adam Holmberg

Change your append calls to say

更改您的 append 调用以说

...append(iter->first)

and

... append(iter->second)

Additionally, the line

此外,该行

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

allocates a string on the heap. If you intend to actually return a pointer to this dynamically allocated string, the return should be changed to std::string*.

在堆上分配一个字符串。如果您打算实际返回指向此动态分配字符串的指针,则返回值应更改为 std::string*。

Alternatively, if you don't want to worry about managing that object on the heap, change the local declaration to

或者,如果您不想担心在堆上管理该对象,请将本地声明更改为

std::string strToReturn("");

and change the 'append' calls to use reference syntax...

并更改“追加”调用以使用参考语法...

strToReturn.append(...)

instead of

代替

strToReturn->append(...)

Be aware that this will construct the string on the stack, then copyit into the return variable. This has performance implications.

请注意,这将在堆栈上构造字符串,然后复制到返回变量中。这对性能有影响。

回答by E.M.

Note that the result of dereferencing an std::map::iterator is an std::pair. The values of firstand secondare not functions, they are variables.

请注意,取消引用 std::map::iterator 的结果是std::pair。的价值观firstsecond不是函数,它们是变量。

Change:

改变:

iter->first()

to

iter->first

Ditto with iter->second.

同上iter->second

回答by Nick Lewis

iter->firstand iter->secondare variables, you are attempting to call them as methods.

iter->firstiter->second是变量,您试图将它们称为方法。

回答by Dzwiedziu-nkg

Use:

用:

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

instead:

反而:

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

回答by james

In c++11 you can use:

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

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

回答by David A. Gray

Another worthy optimization is the c_str ( )member of the STL stringclasses, which returns an immutable null terminated string that can be passed around as a LPCTSTR, e. g., to a custom function that expects a LPCTSTR. Although I haven't traced through the destructor to confirm it, I suspect that the string class looks after the memory in which it creates the copy.

另一个有价值的优化是STL字符串类的c_str ( )成员,它返回一个不可变的空终止字符串,该字符串可以作为LPCTSTR传递,例如,传递给需要LPCTSTR的自定义函数。虽然我还没有通过析构函数进行追踪以确认它,但我怀疑字符串类会照顾它创建副本的内存。