如何使用指针C ++将元素从2D数组复制到1D数组

时间:2018-09-11 18:23:16

标签: c++ pointers

我有一个功能

double* get_row(double *the_array, int row_num, int col_size)    

其中the_array是2D数组,row_num是2D数组上我要从中复制值的行号,而col_size是2D数组的列大小

功能实现

double* get_row(double *the_array, int row_num, int col_size) {

    double* row = new double[col_size];

    for (int i = 0; i < col_size; i++) {

        *row = *(*(the_array + row_num) + i);
        row++;
    }

    delete[] row;

    return row;
}

im试图将值从2D数组row_num的行the_array复制到1D数组row中,但是编译器在一行上给我一个错误 *row = *(*(the_array + row_num) + i);我曾经将元素从一个数组复制到另一个数组,完成此任务的正确方法是什么。

从Visual Studio得到的错误是:'*'的操作数必须是指针。

感谢您的帮助。

4 个答案:

答案 0 :(得分:1)

为了解决这个问题,我假设“ col_size”实际上是“列数”。并且数据按行优先顺序排列。

然后,第N行的开头位于the_array + row_num*col_size

我将从这个辅助函数开始:

inline double* view_row_n( double* array, int row, int num_cols ) {
  return array+row*num_cols;
}

然后我要写一个复制缓冲区:

 std::unique_ptr<double[]> copy_buffer( double const* in, int count ) {
   double* retval = new double[count];
   std::memcpy( retval, in, sizeof(double)*count );
   return std::unique_ptr<double[]>( retval );
 }

现在我将它们一起使用:

double* get_row( double* the_array, int row_num, int col_size) {
  auto retval = copy_buffer( view_row_n( the_array, row_num, col_size), col_size );
  return retval.release();
}

并完成它。

我还要更改:

double* get_row( double const* the_array, int row_num, int col_size) {

甚至:

std::unique_ptr<double[]> get_row( double const* the_array, int row_num, int col_size) {

但这超出了您的问题范围。

答案 1 :(得分:1)

如果get_row不需要您将新的内存分配回调用方,则解决方案将简单地是

double* get_row(double *the_array, int row_num, int col_size) 
{
    return the_array + (row_num * col_size);
}

如果希望调用者将新的内存分配给返回的行,则

double* get_row(double *the_array, int row_num, int col_size) 
{
    double* row = new double[col_size];
    for(int i = 0; i < col_size; i++)
        row[i] = *(the_array + (row_num * col_size) + i);
    return row;
}

会工作的。

在第一个解决方案中,想法是使用row_num * col_size到达正确的行,并简单地返回该地址位置作为结果。在第二个解决方案中,我们首先声明一个新行。然后使用i索引该行中的每个元素,并复制the_array所在行中的the_array + (row_num * col_size)的每个元素。

答案 2 :(得分:0)

这不是现代的C ++,显然您不应该删除返回值。

  

im试图从2D数组the_array的行row_num复制值   进入一维数组

首先,在这种情况下,the_array被定义为原始指针,并用于指针算术,是2D数组的1D表示形式-在我们的描述中最好是准确的

  

我得到[...]的错误是:'*'的操作数必须是一个指针

好,所以这一行:

*row = *(*(the_array + row_num) + i);

有点混乱。我想我知道您要使用它了,但是您正在取消引用(使用表达式左侧的*两次 ,哪个BTW会导致错误。还记得我们说过the_array原始指针,被视为一维数组。因此,您可以使用这种类型的指针算法,例如在括号内说,然后仅对其取消引用一次。上面的表达式使用结果地址(the_array + row_num),对其进行解引用以在数组的此单元格中获取double,然后将i 添加到double值中本身,然后尝试取消引用doubleint i的总和-这是类型为double临时变量,一个指针。这可能是您要针对的行:

*row = *(the_array + row_num * col_size + i);

由于2D数据在内存中具有传染性,连续逐行传播,因此您需要将行索引乘以这样的行大小(也就是列数,并且我认为col_size实际上就是这样,否则您将无法在行之间遍历)以“在行之间跳过” ,最后添加当前单元格索引i来获得行内的特定单元格。然后,就像我们说的那样,取消对整个事物的引用。

除了编译问题和地址计算之外,您还应至少保留row的地址,然后再在循环中递增它,以便可以返回它,而不是返回该行末尾的指针。 为了尽可能多地保留原始功能,您可以使用第二个指针来做到这一点:

double* get_row(double *the_array, int row_num, int col_size) {

    double* row = new double[col_size];
    double* rowPtr = row;

    for (int i = 0; i < col_size; i++) {
        *rowPtr = *(the_array + row_num * col_size + i);
        rowPtr++;
    }

    return row;
}

我正在尝试使其尽可能接近您的版本,因此您可以看到与您所做的不同。许多事情最好以不同的方式完成,例如,为什么不首先使用[]这样的row[i] = *(the_array + row_num * col_size + i);运算符,然后完全摆脱第二个指针?如果您原样遍历++,则实际上不需要在循环中第二行进行i 。另一个例子是您是否必须分配,还是可以将指针返回到现有数组,但是在正确的位置?

重要的是这里几乎没有提到,您真的不应该这样返回原始指针,因为它很容易导致代码中的意图不明确,例如谁拥有分配(并最终负责删除分配),并提出了在异常情况下如何防止内存泄漏的问题?首选的解决方案是使用智能指针such as std::unique_ptr,该实例的一个实例包装原始指针并使之指向原始指针,因此如果您只想扔掉那部分内存,则必须非常明确

答案 3 :(得分:0)

double* get_row(double *the_array, int row_num, int col_size) {
    double* row = new double[col_size];

    for (auto i = 0; i < col_size; ++i) {
        row[i] = the_array[row_num * col_size + i];
    }

    // If the return isn't assigned, the program will leak!
    return row;
}

void row_test() {
    double two_d[15];

    const auto row = get_row(two_d, 2, 5);

    // ...
    // Be sure to delete row afterwards
    delete[] row;
}