选择性迭代器 [英] Selective iterator

查看:182
本文介绍了选择性迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

供参考:无刺激,是的,它有这个,我的需要的推倒重来;)

有某种形式的C ++选择性迭代器(可能的)吗?我想是要分开这样的字符串:

 部分:文字{或其他
 

以这样的形式:

 部分:文字{或其他
 

我能做到这一点有两个回路和find_first_of(:)和({),但这似乎(非常)低效率的我。我想,也许会有一种方式来创建/定义/写一个迭代,将遍历用的for_each所有这些值。我担心这会对我写一个完整的定制方式太复杂的迭代器类为std :: string。

所以,我想,也许这会做的:

 的std ::矢量<为size_t>清单;
为size_t指数= mystring.find(:);
而(指数!=标准::字符串::非营利组织)
{
    list.push_back(指数);
    指数= mystring.find(:,list.back());
}
的std :: for_each的(list.begin(),list.end(),addSpaces(MyString的));
 

这看起来杂乱无章给我,我敢肯定这样做存在一个更优雅的方式。但我不认为它。任何人都有一个好主意?谢谢

PS:我没有测试code贴,只是一个快速写了什么,我会尝试

更新:以你的答案进去后,我想出了这个,和它的作品我都喜欢:)。这样做假设最后一个字符是换行符或东西,否则终止 {} 将不会得到处理。

 无效记号化(串放大器;行)
{
    焦炭oneBack ='';
    焦炭twoBack ='';
    烧焦电流='';
    为size_t长度= line.size();

    用于(为size_t指数= 0;指数<长度++指数)
    {
        twoBack = oneBack;
        oneBack =电流;
        电流= line.at(索引);
        如果(isSpecial(oneBack))
        {
            如果(!isspace为(twoBack))//前插入
            {
                line.insert(索引-1,);
                ++指数;
                ++长度;
            }
            如果(!isspace为(当前))//后插入
            {
                line.insert(索引,);
                ++指数;
                ++长度;
            }
        }
    }
 

评论,欢迎一如既往:)

解决方案

 的std ::字符串常量海峡=一些:字{或其他;

性病::字符串结果;
result.reserve(str.size());
对于(标准::字符串::常量性IT = str.begin(),结束= str.end();
     !它=结束; ++吧)
{
  如果(字符isalnum(*吧))
  {
    result.push_back(*吧);
  }
  其他
  {
    result.push_back(''); result.push_back(*吧); result.push_back('');
  }
}
 

插入版本加速

 的std ::字符串str =一些:字{或其他;

对于(标准::字符串:迭代它= str.begin(),结束= str.end(!);它=结束++吧)
{
  如果(!字符isalnum(*吧))
  {
    它= str.insert(它,'')+ 2;
    它= str.insert(它,'');
    结束= str.end();
  }
}
 

注意的std ::字符串::插入插入迭代器前通过,并返回一个迭代器新插入字符。分配是重要的,因为缓存器可以被重新配置在另一存储位置(迭代器被插入无效)。另外请注意,你不能让结束整个循环中,每次插入时,你需要重新计算它。

FYI: no boost, yes it has this, I want to reinvent the wheel ;)

Is there some form of a selective iterator (possible) in C++? What I want is to seperate strings like this:

some:word{or other

to a form like this:

some : word { or other

I can do that with two loops and find_first_of(":") and ("{") but this seems (very) inefficient to me. I thought that maybe there would be a way to create/define/write an iterator that would iterate over all these values with for_each. I fear this will have me writing a full-fledged custom way-too-complex iterator class for a std::string.

So I thought maybe this would do:

std::vector<size_t> list;
size_t index = mystring.find(":");
while( index != std::string::npos )
{
    list.push_back(index);
    index = mystring.find(":", list.back());
}
std::for_each(list.begin(), list.end(), addSpaces(mystring));

This looks messy to me, and I'm quite sure a more elegant way of doing this exists. But I can't think of it. Anyone have a bright idea? Thanks

PS: I did not test the code posted, just a quick write-up of what I would try

UPDATE: after taking all your answers into account, I came up with this, and it works to my liking :). this does assume the last char is a newline or something, otherwise an ending {,}, or : won't get processed.

void tokenize( string &line )
{
    char oneBack = ' ';
    char twoBack = ' ';
    char current = ' ';
    size_t length = line.size();

    for( size_t index = 0; index<length; ++index )
    {
        twoBack = oneBack;
        oneBack = current;
        current = line.at( index );
        if( isSpecial(oneBack) )
        {
            if( !isspace(twoBack) ) // insert before
            {
                line.insert(index-1, " ");
                ++index;
                ++length;
            }
            if( !isspace(current) ) // insert after
            {
                line.insert(index, " ");
                ++index;
                ++length;
            }
        }
    }

Comments are welcome as always :)

解决方案

std::string const str = "some:word{or other";

std::string result;
result.reserve(str.size());
for (std::string::const_iterator it = str.begin(), end = str.end();
     it != end; ++it)
{
  if (isalnum(*it))
  {
    result.push_back(*it);
  }
  else
  {
    result.push_back(' '); result.push_back(*it); result.push_back(' ');
  }
}

Insert version for speed-up

std::string str = "some:word{or other";

for (std::string::iterator it = str.begin(), end = str.end(); it != end; ++it)
{
  if (!isalnum(*it))
  {
    it = str.insert(it, ' ') + 2;
    it = str.insert(it, ' ');
    end = str.end();
  }
}

Note that std::string::insert inserts BEFORE the iterator passed and returns an iterator to the newly inserted character. Assigning is important since the buffer may have been reallocated at another memory location (the iterators are invalidated by the insertion). Also note that you can't keep end for the whole loop, each time you insert you need to recompute it.

这篇关于选择性迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆