【问题标题】:How can I iterate through a string and also know the index (current position)?如何遍历字符串并知道索引(当前位置)?
【发布时间】:2010-11-21 20:25:17
【问题描述】:

通常在遍历字符串(或任何可枚举对象)时,我们不仅对当前值感兴趣,而且对位置(索引)感兴趣。要通过使用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-style':

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++ 中迭代可枚举对象并跟踪当前索引的最佳做法是什么?

【问题讨论】:

  • 注意第二个代码块! str.length() 是 std::string::size_type 类型,所以你需要用 std::string::size_type 声明变量 i 否则编译器会给你不必要的警告。

标签: c++ string iterator


【解决方案1】:

像这样:


    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;

【讨论】:

    【解决方案2】:

    我从未听说过针对这个特定问题的最佳做法。但是,一般来说,一种最佳实践是使用解决问题的最简单的解决方案。在这种情况下,数组样式访问(或 c 样式,如果你想这样称呼它)是在索引值可用的情况下进行迭代的最简单方法。所以我当然会推荐这种方式。

    【讨论】:

    • 举个例子就好了:P
    • @NickHall 他以OP问题中的第二个代码块为例。
    【解决方案3】:

    您可以使用前面提到的标准 STL 函数距离

    index = std::distance(s.begin(), it);
    

    此外,您可以使用类 c 接口访问字符串和其他一些容器:

    for (i=0;i<string1.length();i++) string1[i];
    

    【讨论】:

    • 顺便说一句,在我的实现中,索引的工作速度比迭代器(5 倍或更多)快得多
    【解决方案4】:

    一个好的做法是基于可读性,例如:

    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;
    

    等等。对你来说最简单、最干净的东西。

    尚不清楚是否有任何一种最佳做法,因为您需要在某处使用计数器变量。问题似乎是您在哪里定义它以及如何增加它是否适合您。

    【讨论】:

    【解决方案5】:

    对于字符串,您可以使用string.c_str(),它会返回一个const char*,可以将其视为一个数组,例如:

    const char* strdata = str.c_str();
    
    for (int i = 0; i < str.length(); ++i)
        cout << i << strdata[i];
    

    【讨论】:

    • 这个问题和我的问题差不多,所以我想在这里问一下,stardata[i] 的值如何与“”进行比较?有没有办法把它转换成char?
    【解决方案6】:

    我会使用它-str.begin() 在这种特殊情况下, std::distance 和 operator- 是相同的。但是如果容器将更改为没有随机访问的东西,std::distance 将增加第一个参数直到它达到第二个,从而给出线性时间和 operator- 将不会编译。 就我个人而言,我更喜欢第二种行为 - 当你的算法从 O(n) 变为 O(n^2) 时,最好得到通知......

    【讨论】:

      【解决方案7】:

      由于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;
      }
      

      【讨论】:

        猜你喜欢
        • 2012-09-11
        • 1970-01-01
        • 1970-01-01
        • 2015-03-30
        • 1970-01-01
        • 2016-01-09
        • 1970-01-01
        • 1970-01-01
        • 2021-02-04
        相关资源
        最近更新 更多