代码之家  ›  专栏  ›  技术社区  ›  J. Polfer

std::list迭代器:获取下一个元素

  •  9
  • J. Polfer  · 技术社区  · 14 年前

    我正在尝试使用存储在std::list中的数据元素构建一个字符串,我只希望在元素之间放置逗号(即,如果元素在list中为a、b、c、d,则结果字符串应为“a、b、c、d”。

    此代码不起作用:

    typedef std::list< shared_ptr<EventDataItem> > DataItemList;
    // ...
    std::string Compose(DataItemList& dilList)
    {
        std::stringstream ssDataSegment;
        for(iterItems = dilList.begin();
            iterItems != dilList.end(); 
            iterItems++)
        {
            // Lookahead in list to see if next element is end
            if((iterItems + 1) == dilList.end())  
            {
                ssDataSegment << (*iterItems)->ToString();
            }
            else
            {
                ssDataSegment << (*iterItems)->ToString() << ",";
            }
        }
        return ssDataSegment.str();
    }
    

    如何使用迭代器获取std::list中的“下一项”?我希望它是一个链接列表,为什么我不能在下一个项目?

    6 回复  |  直到 10 年前
        1
  •  15
  •   Johannes Schaub - litb    14 年前

    你做不到 it + N 因为您没有对列表迭代器的随机访问。对于列表迭代器(这些是双向迭代器),一次只能执行一个步骤。

    你可以使用 boost::next boost::prior

    // Lookahead in list to see if next element is end
    if(boost::next(iterItems) == dilList.end())  
    {
    

    也可以在以下时间之前打印逗号:

    std::string Compose(DataItemList& dilList)
    {
        std::stringstream ssDataSegment;
        for(iterItems = dilList.begin();
            iterItems != dilList.end(); 
            ++iterItems)
        {
            if(iterItems != diList.begin())
                ssDataSegment << ",";
            ssDataSegment << (*iterItems)->ToString();
        }
        return ssDataSegment.str();
    }
    
        2
  •  12
  •   Zan Lynx    14 年前

    我相信列表迭代器是双向的,但不是随机访问。这意味着你可以做+和--对它,但不能加或减。

    要获取下一个迭代器,请制作一个副本并递增。

        3
  •  6
  •   Fred Larson    14 年前

    另一种解决方案是让第一个条目是特殊情况,而不是最后一个条目:

    std::string Compose(DataItemList& dilList)
    {
        std::stringstream ssDataSegment;
        for(iterItems = dilList.begin();
            iterItems != dilList.end(); 
            ++iterItems)
        {
            // See if current element is the first
            if(iterItems == dilList.begin())  
            {
                ssDataSegment << (*iterItems)->ToString();
            }
            else
            {
                ssDataSegment << "," << (*iterItems)->ToString();
            }
        }
        return ssDataSegment.str();
    }
    
        4
  •  2
  •   DevSolar    14 年前

    您可以使用以下方法完全避免此问题:

    std::string Compose(DataItemList& dilList)
    {
        std::stringstream ssDataSegment;
        for(iterItems = dilList.begin(); iterItems != dilList.end(); iterItems++)
        {
            ssDataSegment << (*iterItems)->ToString() << ","; // always write ","
        }
        std::string result = ssDataSegment.str();
        return result.substr(0, result.length()-1); // skip the last ","
    }
    

    首先为所有元素(甚至最后一个元素)编写“,”。比以后,你去掉不需要的最后一个“,”用 substr . 这还导致代码更加清晰。

        5
  •  1
  •   Jerry Coffin    14 年前

    还有一种可能性:

    #include "infix_iterator.h"
    #include <sstream>
    
    typedef std::list<shared_ptr<EventDataItem> > DataItemList;
    
    std::string Compose(DataItemList const &diList) {
        std::ostringstream ret;
        infix_ostream_iterator out(ret, ",");
    
        for (item = diList.begin(); item != diList.end(); ++item)
            *out++ = (*item)->ToString();
        return ret.str();
    }
    

    你可以得到 infix_iterator.h 来自谷歌的Usenet档案(或各种网站)。

        6
  •  1
  •   user1823890    10 年前

    注意:由于C++ 11,你可以使用 性病:下一个 性病:: .