Я пытаюсь выплюнуть строку в C++ следующим образом:
#include <bitset>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/timer.hpp>
using namespace std;
size_t const N = 10000000;
typedef string::const_iterator iter;
typedef boost::iterator_range<iter> string_view;
template<typename C>
void test_custom(string const& s, char const* d, C& ret)
{
C output;
bitset<255> delims;
while (*d)
{
unsigned char code = *d++;
delims[code] = true;
}
typedef string::const_iterator iter;
iter beg;
bool in_token = false;
bool go = false;
for (string::const_iterator it = s.begin(), end = s.end(); it != end; ++it)
{
if (delims[*it])
{
if (in_token)
{
output.push_back(typename C::value_type(beg, it));
in_token = false;
}
}
else if (!in_token)
{
beg = it;
in_token = true;
}
else
{
if (!go)
{
cout << typename C::value_type(beg, it);
//outputs the first character
go = true;
}
}
}
if (in_token)
output.push_back(typename C::value_type(beg, s.end()));
output.swap(ret);
}
vector<string_view> split_string(string in, const char* delim = " ")
{
vector<string_view> vsv;
test_custom(in, delim, vsv);
return vsv;
}
int split()
{
string text = "123 456";
vector<string_view> vsv = split_string(text);
for (int i = 0; i < vsv.size(); i++)
cout << endl << vsv.at(i) << "|" << endl;
return 0;
}
Проблема здесь в том, что первый символ стирается по одной причине... Возвращаемая строка: "23" и "456", но я хочу, чтобы они были "123" и "456",
Итак, первый символ - '', а не '1'
Я не знаком с boost::iterator_range
, но это, безусловно, похоже на пару итераторов.
Если это так, то в этом коде:
vector<string_view> split_string(string in, const char* delim = " ")
{
vector<string_view> vsv;
test_custom(in, delim, vsv);
return vsv;
}
вы возвращаете итераторы, ссылающиеся на локальную string
вызываемую in
, которая перестает существовать, когда функция возвращается.
Это неопределенное поведение.
Одним из исправлений будет передача этой строки по ссылке.
Кстати, один неэффективный, но простой и безопасный способ разбить строку на пробелы - использовать istringstream
:
istringstream stream( source_string );
string word;
while( stream >> word ) { cout << word; }
Отказ от ответственности: код не тронут руками компилятора.
Поскольку вы уже используете Boost, вы можете использовать это ("простой" способ: P):
#include <boost/algorithm/string.hpp>
std::string text = "this is sample string";
std::vector<std::string> tokens;
boost::split(tokens, text, boost::is_any_of("\t "));
Или используйте любой разделитель (ы), который вы хотите использовать в качестве третьего аргумента.
cout
в моем коде; там первый символ наtypename C::value_type(beg, it)
, но я не могу положить это вoutput