Переберите вектор и скопируйте элементы в массив C

0

Для проекта, над которым я работаю, требуется куча перевода из концепций C++ в C. В этом случае, вызывающий отвечает за управление буфером памяти. Затем он вызывает функцию и предоставляет массив типа double и объем памяти, который он выделял. Затем функция заполняет свой буфер массива всеми удвоениями в векторе. Это мой первый выстрел в функцию, но я не уверен, что это правильно. Поскольку я не очень хорошо знаком с C, я уверен, что есть ошибки. Правильно ли я это делаю? А как насчет добавления нулевого завершения \0 в конце?

void getMoments(uint32_t & bufferSize,
                double * moments)
{
  if ( bufferSize < (vec.size() * sizeof(double)) + 1 )
  {
    // set error: bufferSize is not large enough to copy elements of vector.
  }

  typedef std::vector<double>::const_iterator it_type;

  for (it_type it = vec.begin(); it != vec.end(); ++it) 
  {
    double e = *it;
    std::memcpy(moments, &e, sizeof(double));
  }

  // How do I add the null terminating \0?
}

Кстати, bufferSize передается по ссылке, потому что FORTRAN - это один клиент, и язык требует, чтобы все передавалось по ссылке.

Что смущает меня в массивах C - это понятие (или отсутствие понятия) указателя. Как узнать, где мы находимся в массиве C? Другими словами, каждый раз, когда я вызываю memcpy, должен ли он писать, начиная с начала массива, таким образом перезаписывая мои ранее записанные байты?

  • 0
    указатели в C не сильно отличаются от C ++. Возможно, вам следует сначала прочитать об этом, прежде чем пытаться это сделать.
  • 0
    А? C? Это C ++. Это функция, которую вы собираетесь перевести на C, или ваша попытка сделать это? Непонятно, что вы пытаетесь сделать.
Показать ещё 4 комментария
Теги:
arrays

3 ответа

3
Лучший ответ

Указатель может использоваться как выходной итератор:

if (bufferSize < vec.size() * sizeof(double))
{
  // error: buffer too small
  return;
}

std::copy(vec.begin(), vec.end(), moments);

Примечание: если вы передаете указатель на двойной, я бы добавил размер буфера/массива с точки зрения удвоений, а не символов (байтов).

  • 0
    Интересно! Можете ли вы объяснить, почему double можно использовать в качестве OutputIterator?
  • 1
    @jakeliquorblues Это указатель на двойной. Он может быть разыменован, то, на что он указывает, может быть назначен, и он может быть увеличен / уменьшен. Указатель на элемент массива является итератором.
Показать ещё 1 комментарий
1

Я понятия не имею, почему вам когда-либо понадобится исключить массив двойников, поэтому я удалил его.

Полный код:

void getMoments(uint32_t & bufferSize, double * moments)
{
    if ( bufferSize < (vec.size() * sizeof(double)) )
    {
        // set error: bufferSize is not large enough to copy elements of vector.
    }

    typedef std::vector<double>::const_iterator it_type;

    for (it_type it = vec.begin(); it != vec.end(); ++it) 
    {
        *moments++ = *it;
    }
}
  • 0
    О да! Нулевое окончание \0 для строк C! Не двойные массивы. Мое отсутствие основ показывает, что :(
1

Одно из возможных решений:

#include <vector>
#include <algorithm>
...

int getMoments(uint32_t* bufferSize,
                double * moments)
{
    std::vector<double> vec = ...
    if (*bufferSize/sizeof(double) < vec.size())
        return -1;
    std::copy(vec.begin(), vec.end(), moments);
    return 0;
}

См. Также std :: copy

Примечание: "ссылка" недоступна в C. Таким образом, ваш C API должен передать параметр bufferSize в качестве указателя.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню