通常在迭代字符串(或任何可枚举对象)时,我们不仅对当前值感兴趣,还对位置(索引)感兴趣。要使用string::iterator
来实现这一点,我们必须维护一个单独的索引:
string str ("Test string");
string::iterator it;
int index = 0;
for ( it = str.begin() ; it < str.end(); it++ ,index++)
{
cout << index << *it;
}
上面显示的风格似乎并不比'c风格'优越:
string str ("Test string");
for ( int i = 0 ; i < str.length(); i++)
{
cout << i << str[i] ;
}
在Ruby中,我们可以优雅地获取内容和索引:
"hello".split("").each_with_index {|c, i| puts "#{i} , #{c}" }
那么,C ++中迭代可枚举对象并跟踪当前索引的最佳实践是什么?
答案 0 :(得分:47)
像这样:
std::string s("Test string");
std::string::iterator it = s.begin();
//Use the iterator...
++it;
//...
std::cout << "index is: " << std::distance(s.begin(), it) << std::endl;
答案 1 :(得分:43)
我从来没有听说过这个具体问题的最佳实践。但是,一般的最佳实践是使用解决问题的最简单的解决方案。在这种情况下,数组样式访问(或c样式,如果你想称之为)是最简单的迭代方式,同时索引值可用。所以我肯定会这样推荐。
答案 2 :(得分:20)
您可以使用前面提到的标准STL功能距离
index = std::distance(s.begin(), it);
此外,您可以使用类似c的界面访问字符串和其他一些容器:
for (i=0;i<string1.length();i++) string1[i];
答案 3 :(得分:9)
一个好的做法是基于可读性,例如:
string str ("Test string");
for (int index = 0, auto it = str.begin(); it < str.end(); ++it)
cout << index++ << *it;
或者:
string str ("Test string");
for (int index = 0, auto it = str.begin(); it < str.end(); ++it, ++index)
cout << index << *it;
或者你原来的:
string str ("Test string");
int index = 0;
for (auto it = str.begin() ; it < str.end(); ++it, ++index)
cout << index << *it;
等。无论对你来说最简单,最干净。
目前尚不清楚是否存在任何一种最佳实践,因为您需要在某处使用计数器变量。问题似乎在于你定义它的位置以及增量如何适合你。
答案 4 :(得分:3)
我会用它-str.begin() 在这种特殊情况下,std :: distance和operator-是相同的。但是如果容器将更改为没有随机访问的东西,std :: distance将递增第一个参数,直到它达到第二个,从而给出线性时间和操作符 - 不会编译。 我个人更喜欢第二种行为 - 当O(n)的算法变成O(n ^ 2)时,最好收到通知......
答案 5 :(得分:1)
由于std::distance
只是随机访问迭代器的常量时间,我可能更喜欢显式迭代器算法。
此外,由于我们在这里编写C ++代码,我相信更多的C ++惯用解决方案比C风格的方法更可取。
string str{"Test string"};
auto begin = str.begin();
for (auto it = str.begin(), end = str.end(); it != end; ++it)
{
cout << it - begin << *it;
}
答案 6 :(得分:0)
对于字符串,你可以使用string.c_str()
来返回一个const char *,它可以被视为一个数组,例如:
const char* strdata = str.c_str();
for (int i = 0; i < str.length(); ++i)
cout << i << strdata[i];