#c
Вопрос:
Я хочу разделить строку на куски по 1024 точно так же, как это.
std::string content;
std::vector<std::string_view>
data{_iterator<std::string>{content, 1024},
_iterator<std::string>{}};
Это изящно и эффективно, но я понятия не имею, что делать.
Комментарии:
1. Почему вы должны использовать итераторы? Почему бы не использовать строку непосредственно
content.data()
content.data() 1023
для первого просмотра?2. @Someprogrammerdude просто подумал, что это будет интуитивно понятно
3. и еще больше в стиле c
4. Начиная с C 20
std::string_view
может принимать итераторы для построения, аstd::string
итераторы являются итераторами с произвольным доступом,std::begin(content)
чтобыstd::begin(content) 1024
? Конечно, необходимо позаботиться о том, чтобыstd::end(content)
это не было передано (но это также необходимо учитывать при использовании указателей).
Ответ №1:
Возможно, не так элегантно, как вам хочется, но попробуйте что-нибудь вроде этого:
std::string content = ...;
std::vector<std::string_view> data;
if (!content.empty())
{
data.reserve((content.size() 1023) / 1024);
std::string_view content_view = content;
size_t i = 0;
do
{
data.push_back(content_view.substr(i, 1024));
i = data.back().size();
}
while (i < content.size());
}
Альтернативно:
std::string content = ...;
std::vector<std::string_view> data;
if (!content.emoty())
{
data.reserve((content.size() 1023) / 1024);
const char* ptr = content.c_str();
size_t size = content.size();
for(size_t i = 0; i < size; i = 1024) {
data.emplace_back(ptr i, std::min(size-i, 1024));
}
}
Если вы действительно хотите инициализировать vector
итераторы размером с фрагмент, вам придется написать собственный класс итератора с нуля, чтобы справиться с этим. Не существует стандартного класса итераторов, который выполнял бы итерацию строки (или любого другого контейнера) в блоках из N элементов.
Комментарии:
1. cppreference говорит
Returns a view of the substring [pos, pos rcount), where rcount is the smaller of count and size() - pos.
, что, я полагаю, вам не нужно резервировать?2. @hxb
reserve()
предварительно выделяетvector
внутренний массив, поэтому ему не нужно перераспределять массив, покаstd::string_view
в него помещаются объекты. Это не имеет никакого отношения к тому, как создаются отдельныеstd::string_view
объекты. Кодreserve()
занимает место для 1std::string_view
объекта на 1024char
секундыcontent
. До 1024char
с = 1std::string_view
, до 2048chars
= 2 std::string_view и так далее…
Ответ №2:
Самый элегантный способ, который я сейчас могу придумать.
std::string_view data = content;
std::vector<std::string_view> chunks;
for (int i = 0; i < data.size(); i = 1024)
chunks.push_back(data.substr(i, 1024));
Комментарии:
1. Вы должны
reserve()
vector
это сделать перед входом в цикл, так как вы можете легко заранее рассчитать, сколькоstring_view
s будет введено в него.