станд.:: итератор списка: получите следующий элемент

Я пытаюсь создать строку с помощью элементов данных, сохраненных в станд.:: список, где я хочу запятые, помещенные только между элементами (т.е., если элементы {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();
}

Как делают я достигаю "the-next-item" в станд.:: список с помощью итератора? Я ожидал бы, что это - связанный список, почему я не могу достигнуть следующий объект?

9
задан J. Polfer 23 April 2010 в 16:09
поделиться

5 ответов

Вы не можете выполнить 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();
}
15
ответ дан 4 December 2019 в 06:29
поделиться

Я считаю, что итератор списка является двунаправленным, но не произвольным доступом. Это означает, что вы можете использовать ++ и -, но не прибавлять или вычитать.

Чтобы получить следующий итератор, сделайте копию и увеличьте ее.

12
ответ дан 4 December 2019 в 06:29
поделиться

Еще одна возможность:

#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 из архива Google Usenet (или различных веб-сайтов).

1
ответ дан 4 December 2019 в 06:29
поделиться

Другое решение состоит в том, чтобы первая запись была особым случаем , вместо последней записи:

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();
}
6
ответ дан 4 December 2019 в 06:29
поделиться

Вы можете полностью избежать этой проблемы, используя:

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 . Это дополнительно приводит к более четкому коду.

2
ответ дан 4 December 2019 в 06:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: