如何在 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
How to iterate over a std::map full of strings in C++
提问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 toString
that 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_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?
有人可以向我解释缺少什么,我做错了什么?hash_map
在用户必须定义散列函数才能hash_map
与std::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 new
to 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
Don't write a
toString()
method. This is not Java. Implement the stream operator for your class.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.If you must use a loop, but don't intend to change the data, prefer
const_iterator
overiterator
. That way, if you accidently try and change the values, the compiler will warn you.
不要写
toString()
方法。这不是Java。为您的类实现流运算符。更喜欢使用标准算法而不是编写自己的循环。在这种情况下,
std::for_each()
为您想要做的事情提供了一个很好的界面。如果你必须使用一个循环,但不打算更改数据,更喜欢
const_iterator
过iterator
。这样,如果您不小心尝试更改值,编译器会警告您。
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.
回答by Nick Lewis
iter->first
and iter->second
are variables, you are attempting to call them as methods.
iter->first
和iter->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的自定义函数。虽然我还没有通过析构函数进行追踪以确认它,但我怀疑字符串类会照顾它创建副本的内存。