Как я могу разделить строку на куски по 1024 с помощью итератора и string_view

#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() занимает место для 1 std::string_view объекта на 1024 char секунды content . До 1024 char с = 1 std::string_view , до 2048 chars = 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 будет введено в него.