下面的片段来自这个答案。
#include <string>
#include <vector>
void tokenize(std::string str, std::vector<string> &token_v){
size_t start = str.find_first_not_of(DELIMITER), end=start;
while (start != std::string::npos){
// Find next occurence of delimiter
end = str.find(DELIMITER, start);
// Push back the token found into vector
token_v.push_back(str.substr(start, end-start));
// Skip all occurences of the delimiter to find new start
start = str.find_first_not_of(DELIMITER, end);
}
}
对于这样的缓冲器:
std::array<char, 150> buffer;
我想有一个sting_view
(指向缓冲区),并将其传递给tokenizer函数,令牌应该通过out参数以std::string_view
s的形式返回(而不是向量),它还将返回提取的令牌的数量。
size_t tokenize( const std::string_view inputStr,
const std::span< std::string_view > foundTokens_OUT,
const size_t expectedTokenCount )
{
// implementation
}
int main( )
{
std::array<char, 150> buffer { " @a hgs -- " };
const std::string_view sv { buffer.data( ), buffer.size( ) };
const size_t expectedTokenCount { 4 };
std::array< std::string_view, expectedTokenCount > foundTokens; // the span for storing found tokens
const size_t num_of_found_tokens { tokenize( sv, foundTokens, expectedTokenCount ) };
if ( num_of_found_tokens == expectedTokenCount )
{
// do something
std::clog << "success\n" << num_of_found_tokens << '\n';
}
for ( size_t idx { }; idx < num_of_found_tokens; ++idx )
{
std::cout << std::quoted( foundTokens[ idx ] ) << '\n';
}
}
如果有人能实现一个类似的tokenize函数,但只针对基于空格和制表符拆分的string_view
,我将不胜感激。(不支持选项卡)。另外,我希望这个函数在inputStr
中找到的标记数超过expectedTokenCount
时停止工作并返回expectedTokenCount + 1
。这样显然效率更高。
下面是我的虚拟版本:
size_t tokenize( const std::string_view inputStr,
const std::span< std::string_view > foundTokens_OUT,
const size_t expectedTokenCount )
{
if ( inputStr.empty( ) )
{
return 0;
}
size_t start { inputStr.find_first_not_of( ' ' ) };
size_t end { start };
size_t foundTokensCount { };
while ( start != std::string_view::npos && foundTokensCount < expectedTokenCount )
{
end = inputStr.find( ' ', start );
foundTokens_OUT[ foundTokensCount++ ] = inputStr.substr( start, end - start );
start = inputStr.find_first_not_of( ' ', end );
}
return foundTokensCount;
}
注意:范围库还没有适当的支持(至少在GCC上),所以我试图避免这种情况。
2条答案
按热度按时间yfjy0ee71#
我试着自己写一个,但它没有像预期的那样工作(不支持标签)。
如果你想支持用空格和制表符拆分,那么你可以使用
find_first_not_of
的另一个重载:它将发现第一个字符不等于由
s
指向的字符串中的任何字符。因此,您的实现只需将
find_first_not_of(' ')
和find(' ')
更改为find_first_not_of(" \t")
和find_first_of(" \t")
。Demo
lvjbypge2#
这是我的实现(我之前写的),它可以处理以一个或多个分隔符开头、重复分隔符和以一个或多个分隔符结尾的输入:
它使用string_views来处理所有的事情,所以没有内存分配,但是要小心不要过早地丢弃输入字符串。string_views毕竟是非所有的。
在线演示:https://onlinegdb.com/tytGlOVnk