Я пытаюсь создать строку с помощью элементов данных, сохраненных в станд.:: список, где я хочу запятые, помещенные только между элементами (т.е., если элементы {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" в станд.:: список с помощью итератора? Я ожидал бы, что это - связанный список, почему я не могу достигнуть следующий объект?
Вы не можете выполнить 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();
}
Я считаю, что итератор списка является двунаправленным, но не произвольным доступом. Это означает, что вы можете использовать ++ и -, но не прибавлять или вычитать.
Чтобы получить следующий итератор, сделайте копию и увеличьте ее.
Еще одна возможность:
#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 (или различных веб-сайтов).
Другое решение состоит в том, чтобы первая запись была особым случаем , вместо последней записи:
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();
}
Вы можете полностью избежать этой проблемы, используя:
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
. Это дополнительно приводит к более четкому коду.