仅供引用:没有提升,是的,它有这个,我想重新发明轮子;)
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/