strncpy эквивалент std :: copy - PullRequest
3 голосов
/ 08 декабря 2011

STL предоставляет std :: copy , но его сложно использовать с выходными контейнерами с фиксированными размерами, так как нет проверки границ на выходном итераторе

Итак, я изобрел свое, что-то вроде ниже

template<class InputIterator , class OutputIterator>
void safecopy( InputIterator srcStart , InputIterator srcEnd , 
                    OutputIterator destStart , OutputIterator destEnd )
{
    while ( srcStart != srcEnd && destStart != destEnd )
    {
        *destStart = *srcStart;
        ++srcStart;
        ++destStart;
    }
}

int main()
{
    std::istream_iterator<char> begin(std::cin), end;       
    char buffer[3];

    safecopy( begin, end, buffer, buffer + 3 );     
    return 0;
}

Вопросы:

  1. Я изобретаю колесо здесь? Есть ли алгоритм STL, чтобы делать то, что я хочу.
  2. Есть ли недостатки в моей safecopy , она работает для всего, на что работает std :: copy?

Ответы [ 3 ]

5 голосов
/ 08 декабря 2011

Позвольте мне добавить свой комментарий к ответу, чтобы у меня было немного больше места.

Во-первых, ваша реализация выглядит хорошо.

Теперь, почему этого нет в стандарте?(Новый стандарт добавляет std::copy_n, но это тоже делает что-то другое. *)

Подумайте об этом так: strncopy на самом деле не «хорошая» идея;это просто не ужасная идея.Поскольку в C нет динамических структур данных, лучше всего сделать версию с проверкой длины.

Но в C ++ это не вписывается в общую идею динамических контейнеров: вам редко захочется перезаписать некоторые элементы, а вместо создать все элементы, которые вы делаете с помощью std::copy плюс std::inserter.strncpy - это костыль, который требует от вас предварительно распределить структуру данных назначения, но в C ++ мы можем сделать намного лучше, чем эта.С помощью динамических контейнеров, итераторов и вставок мы можем копировать что угодно , не беспокоясь о распределении.

Другими словами, любой абстрактный алгоритм, который вы можете себе представить, должен иметь лучший, более конкретный методполучения итераторов и диапазонов итераторов (например, удалить / стереть);редко бывает, чтобы конечная цель алгоритма состояла в том, чтобы создать только выходной диапазон, ограниченный каким-либо другим целевым диапазоном.

В итоге: да, вы можете сделать это,но вы, вероятно, можете сделать лучше.

*) Хотя copy_n плюс min исходного и конечного размера можно использовать для создания ограниченной копии.

1 голос
/ 08 декабря 2011

Я бы внес небольшую корректировку в вашу реализацию.Дайте ему возвращаемое значение.Либо конечный итератор вывода, либо целое число, указывающее количество скопированных элементов.

Основным вариантом использования, который я вижу для вашей функции, будет чтение фрагментов фиксированного размера из входного потока, и вы не знаете, когда это произойдет.закончится.Если это действительно заканчивается, вам нужен какой-то способ узнать это, и вам нужно знать, сколько элементов было скопировано до того, как это действительно закончилось.Если вы знаете, сколько элементов было скопировано, и оно не соответствует или не превышает размер выходного диапазона, то вы можете узнать, что оно закончилось.

0 голосов
/ 08 декабря 2011

Да.Вы заново изобретаете колесо!

Например, вы можете использовать std::copy как:

std::copy(s.begin(), s.begin() + 3 , buffer);

вместо этого,

safecopy(s.begin(), s.end() , buffer, buffer + 3);

Использованиеstd::copy таким образом НЕ менее безопасен, чем ваш safecopy.

Или даже лучше std::copy_n, который поставляется с C ++ 11:

std::copy_n(s.begin(), 3, buffer);

Это будет работать, даже если аргумент не является итератором произвольного доступа.


Что касается использования std::vector<char>, вы можете использовать его конструктор непосредственно как:

std::vector<char> v(s.begin(), s.end());

Нет необходимости даже std::copy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...