如何在 C++ 中迭代充满字符串的 std::map

发布于 2024-07-26 09:47:35 字数 1084 浏览 5 评论 0原文

我遇到以下与迭代使用 std::map 定义的关联字符串数组相关的问题。

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

在构造函数中,我使用与字符串数据关联的字符串键对填充表。 在其他地方,我有一个方法 toString 返回一个字符串对象,其中包含表对象中包含的所有键和关联数据(作为 key=data 格式)。

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::字符串对象。 我的情况也有类似的情况吗?

I have the following issue related to iterating over an associative array of strings defined using 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 toString that returns a string object that contains all the keys and associated data contained in the table object(as key=data format).

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_map where the user has to define a hashing function to be able to use hash_map with std::string objects. Could be something similar also in my case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

╰つ倒转 2024-08-02 09:47:35

您的主要问题是您在迭代器中调用名为 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) {
    ...
}

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:

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

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

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

for (auto& item: table) {
    ...
}
浅笑轻吟梦一曲 2024-08-02 09:47:35
  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);
};
  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_iterator over iterator. That way, if you accidently try and change the values, the compiler will warn you.

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.

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);
};
心头的小情儿 2024-08-02 09:47:35

将追加调用更改为

...append(iter->first)

and

... append(iter->second)

另外,该行在

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

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

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

std::string strToReturn("");

并将“append”调用更改为使用引用语法...

strToReturn.append(...)

而不是

strToReturn->append(...)

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

Change your append calls to say

...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*.

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 copy it into the return variable. This has performance implications.

夜雨飘雪 2024-08-02 09:47:35

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

更改:

iter->first()

iter->first

iter->second 相同

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

Change:

iter->first()

to

iter->first

Ditto with iter->second.

咽泪装欢 2024-08-02 09:47:35

iter->firstiter->second 是变量,您尝试将它们作为方法调用。

iter->first and iter->second are variables, you are attempting to call them as methods.

玩心态 2024-08-02 09:47:35

使用:

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

代替:

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

Use:

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

instead:

std::map<std::string, std::string>::iterator
猫七 2024-08-02 09:47:35

另一个值得优化的是 STL string 类的 c_str ( ) 成员,它返回一个不可变的以 null 结尾的字符串,可以作为 LPCTSTR 传递>,例如,需要 LPCTSTR 的自定义函数。 尽管我没有通过析构函数进行追踪来确认这一点,但我怀疑字符串类会照顾它在其中创建副本的内存。

Another worthy optimization is the c_str ( ) member of the STL string classes, 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.

还在原地等你 2024-08-02 09:47:35

在 c++11 中你可以使用:

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

In c++11 you can use:

for ( auto iter : table ) {
     key=iter->first;
     value=iter->second;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文