c++ - 选择性迭代器

标签 c++ algorithm stl iterator find

仅供引用:没有提升,是的,它有这个,我重新发明轮子;)

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

some:word{or other

像这样的形式:

some : word { or other

我可以用两个循环和 find_first_of(":") 和 ("{") 来做到这一点,但这对我来说似乎(非常)低效。我认为也许会有一种方法来创建/定义/编写一个迭代器,该迭代器将使用 for_each 迭代所有这些值。我担心这会让我为 std::string 编写一个完整的自定义方式过于复杂的迭代器类。

所以我想也许这样可以:

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));

这对我来说看起来很乱,而且我很确定存在一种更优雅的方式来做到这一点。但是我想不出来。有人有好主意吗?谢谢

PS:我没有测试发布的代码,只是快速写下我会尝试什么

更新:在考虑了您的所有答案后,我想到了这个,而且它很合我意:)。这确实假设最后一个字符是换行符或其他字符,否则结尾的 {}: 将不会被处理。

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

一如既往地欢迎评论:)

最佳答案

使用 std::istream_iterator 相对容易。

您需要做的是定义您自己的类(比如 Term)。然后定义如何使用运算符 >> 从流中读取单个“单词”(术语)。

我不知道你对一个词的确切定义是什么,所以我使用以下定义:

  • 任何连续的字母数字字符序列都是一个术语
  • 任何非字母数字的非空白字符都是单词。

试试这个:

#include <string>
#include <sstream>
#include <iostream>
#include <iterator>
#include <algorithm>

class Term
{
    public:

        // This cast operator is not required but makes it easy to use
        // a Term anywhere that a string can normally be used.
        operator std::string const&() const {return value;}

    private:
        // A term is just a string
        // And we friend the operator >> to make sure we can read it.
        friend std::istream& operator>>(std::istream& inStr,Term& dst);
        std::string     value;
};

现在我们所要做的就是定义一个运算符>>,它根据规则读取一个单词:

// This function could be a lot neater using some boost regular expressions.
// I just do it manually to show it can be done without boost (as requested)
std::istream& operator>>(std::istream& inStr,Term& dst)
{
   // Note the >> operator drops all proceeding white space.
   // So we get the first non white space
   char first;
   inStr >> first;

   // If the stream is in any bad state the stop processing.
   if (inStr)
   {
       if(std::isalnum(first))
       {
           // Alpha Numeric so read a sequence of characters
           dst.value = first;

           // This is ugly. And needs re-factoring.
           while((first = insStr.get(), inStr) && std::isalnum(first))
           {
               dst.value += first;
           }

           // Take into account the special case of EOF.
           // And bad stream states.
           if (!inStr)
           {
               if (!inStr.eof())
               {
                   // The last letter read was not EOF and and not part of the word
                   // So put it back for use by the next call to read from the stream.
                   inStr.putback(first);
               }
               // We know that we have a word so clear any errors to make sure it
               // is used. Let the next attempt to read a word (term) fail at the outer if.
               inStr.clear();
           }
       }
       else
       {
           // It was not alpha numeric so it is a one character word.
           dst.value   = first;
       }
  }
  return inStr;
}

所以现在我们可以通过使用 istream_iterator 在标准算法中使用它

int main()
{
    std::string         data    = "some:word{or other";
    std::stringstream   dataStream(data);


    std::copy(  // Read the stream one Term at a time.
                std::istream_iterator<Term>(dataStream),
                std::istream_iterator<Term>(),

                // Note the ostream_iterator is using a std::string
                // This works because a Term can be converted into a string.
                std::ostream_iterator<std::string>(std::cout, "\n")
             );

}

输出:

> ./a.exe
some
:
word
{
or
other

关于c++ - 选择性迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3046747/

相关文章:

c++ - 为什么 GCC 在编译时不评估 constexpr?

c++ - 使用opencv和c++进行稀疏编码和字典学习

c# - 如何在不在代码中自己指定数组长度的情况下用用户输入填充数组

algorithm - 如何计算大数的组合

c++ - 如何遍历 C++ 中的对象列表?

c++ - 想使用 VOLUME_DISK_EXTENTS 结构

c++ - 我想解析一个 txt 文件并将其放入一个结构中

algorithm - 连接点的最小线数

c++ - 我可以在 C++ 中使用具有值语义的多态容器吗?

c++ - 如何使用 STL 将结构 vector 转换为映射