如何将数组中的值复制到一个新数组中?

4

我已尝试了解这个问题,不断遇到问题。

目标:

编写一个函数来为整数数组分配内存。该函数以整数指针、数组大小和要分配的新大小作为参数。函数返回一个指向已分配缓冲区的指针。当第一次调用函数时,大小将为零,并创建一个新数组。如果在数组大小大于零时调用函数,则会创建一个新数组,并将旧数组的内容复制到新数组中。你的教师已提供arrayBuilder.cpp作为此编程挑战的起始代码。此外,Lab9_1.exe是可执行文件,您可以测试它。

代码:

#include <iostream>
using namespace std;

int * arrayBuilder(int * arr, int size, int newSize);
void showArray(int * arr, int size);

int main()
{
int * theArray = 0;
int i;

cout << "This program demonstrates an array builder function." << endl << endl;

// create the initial array.  The initial size is zero and the requested size is 5.
theArray = arrayBuilder(theArray, 0, 5);

// show the array before values are added
cout << "theArray after first call to builder: " << endl;
showArray(theArray, 5);

// add some values to the array
for(int i = 0; i < 5; i++)
{
    theArray[i] = i + 100;
}

// show the array with added values
cout << endl << "Some values stored in the array: " << endl;
showArray(theArray, 5);

// expand the size of the array.  size is not the original size.  newSize
// must be greater than size.
theArray = arrayBuilder(theArray, 5, 10);

// show the new array with the new size
cout << endl << "The new array: " << endl;
showArray(theArray, 10);

cout << endl;

delete [] theArray; // be sure to do this a1t the end of your program!

system("pause");

return 0;
}

/*
FUNCTION: arrayBuilder
INPUTS Pointer to an array.  Size of the array. If size is zero, arr can be    NULL.
      Size of the new array.
OUTPUTS:  Returns a pointer to allocated memory.  If newSize is greater than size,
      an array of newSize is allocated and the old array is copied into the new
      array. Memory pointed to by the old array is deleted.  All new elements
      are initialized to zero.
*/


int * arrayBuilder(int * arr, int size, int newSize)
{
// TODO: Your code goes here


return NULL; // default return value.  No memory allocated!
}

/*
FUNCTION: showArray
INPUTS: Pointer to an array.  Size of the array. If size is zero, arr can be  NULL.
OUTPUTS:  Prints the contents of the array to the console.
*/


void showArray(int * arr, int size)
{
cout << "arr = ";

for(int i = 0; i < size; i++)
{
    cout << arr[i] << "  ";
}

cout << endl;

}

我的问题:我无法弄清如何交换“arr”和临时数组的值。

int * arrayBuilder(int * arr, int size, int newSize)
{
// TODO: Your code goes here
    int * temp = new int [newSize];

for (int i = size; i < newSize; i++)
{
        *arr = *temp;
        temp++;
}

return NULL; // default return value.  No memory allocated!
}

在寻找答案时,尝试的另一种方法:

int * arrayBuilder(int * arr, int size, int newSize)
{
// TODO: Your code goes here
int * temp = new int [newSize];
memcpy (temp, arr, size *sizeof(int));
// HINT: Design the function before writing it.
delete[]  arr;

for (int i = size; i < newSize; i++)
{
    temp[i] = i;
}

return NULL; // default return value.  No memory allocated!
}

基本上我的最终目标是让答案看起来像这样:
This program demonstrates an array builder function.

theArray after first call to the builder:
arr = 0 0 0 0 0

some values stored in the array:
arr = 100 101 102 103 104

the new array:
arr = 100 101 102 103 104 0 0 0 0 0

进展顺利!它不再崩溃了 :-) 目前的情况如下:

This program demonstrates an array builder function.

theArray after first call to builder:
arr = -842150451  0  0  0  0

Some values stored in the array:
arr = 100  101  102  103  104

The new array:
arr = -842150451  -842150451  -842150451  -842150451  -842150451  -842150451  -8
42150451  -842150451  -842150451  -842150451

Press any key to continue . . .

我会不断尝试,如果遇到问题就告诉大家!再次感谢大家!

好的!终于成功让它正确地显示了:

This program demonstrates an array builder function.

theArray after first call to the builder:
arr = 0 0 0 0 0

some values stored in the array:
arr = 100 101 102 103 104

the new array:
arr = 100 101 102 103 104 0 0 0 0 0

这是我的做法。我觉得在第二部分中当我为“temp”放入0值时,可能有些作弊。我的理解是我要将上一个数组的数据放入新数组中,但实际上我只是重新创建了它。(因此,它只适用于这个特定的值集[仅为0])。有没有其他方法可以编写第二部分,使其能普遍适用于任何值?

int * arrayBuilder(int * arr, int size, int newSize)
{
int i = size;
int * temp = new int [newSize];
// What if the size is 0?
if (size <= 0)
{
    while (i < newSize)
    {
        temp[i] = 0;
        i++;
    }
}
// Assuming the size _isn't_ 0
else 
{
// "a new array will be created"  (good)

for (i = 0; i < newSize; i++)
{
    // The contents of the "old" array (arr) will be
    // copied into the "new" array (temp)
    while (i < size)
    {
        temp[i] = arr[i];
        i++;
    }
    while (i >= size && i < newSize)
    {
        temp[i] = 0;
        i++;
    }
    // as a hint, you can address the elements in 
    // both arrays using the [] operator:
    // arr[i]
    // temp[i]

}
}

// "The function returns a pointer to the allocated buffer."
// So, NULL is wrong, what buffer did you allocate?
return temp; // default return value.  No memory allocated!
}
6个回答

5

既然你已经付出了一些努力。

编写一个分配整数数组内存的函数。

该函数的原型已经为您提供:

int * arrayBuilder(int * arr, int size, int newSize);

该函数以整数指针、数组大小和要分配的新大小作为参数。该函数返回指向已分配缓冲区的指针。它并未对“旧”(传入的)数组进行任何操作,因此我们应该假设需要将其保持不变。当首次调用该函数时,大小将为零,并将创建一个新数组。在给定上下文情况下,以上文本是毫无意义的。如果大小为零,如何知道要分配多少个元素?如果在数组大小大于零时调用该函数,则会创建一个新数组,并将旧数组的内容复制到新数组中。现在你已经接近成功了。
int * arrayBuilder(int * arr, int size, int newSize)
{
    // What if the size is 0?

    // Assuming the size _isn't_ 0
    // "a new array will be created"  (good)
    int * temp = new int [newSize];

    for (int i = size; i < newSize; i++)
    {
        // The contents of the "old" array (arr) will be
        // copied into the "new" array (temp)

        // as a hint, you can address the elements in 
        // both arrays using the [] operator:
        // arr[i]
        // temp[i]

        // something is wrong here...
        *arr = *temp;

        // you definitely _don't_ want to do this
        temp++;
    }

    // "The function returns a pointer to the allocated buffer."
    // So, NULL is wrong, what buffer did you allocate?
    return NULL; // default return value.  No memory allocated!
}

2
+1 很棒的答案,因为它有助于理解,但不是复制粘贴完成的模板。 - Till
嗯,是的,将注释添加到代码中比试图用英语拼写出来更适合逐行审查。 - Philip
+1 好答案。虽然可以使用memcpy,但出于教学目的,这样更明确。 - Chad Befus
哇!太感谢了,我要花点时间消化这个。我会尽快回来告诉你我弄明白了。如果不行,我会再次回来寻求你或其他人的帮助。再次感谢! - Peter
我是新来的,不确定编辑我的帖子是否会通知您或其他任何人,但希望这样做。无论如何,我非常感谢您的帮助,如果您不介意看一下我的更新帖子,我将永远感激不尽。 - Peter

5

你已经在这里得到了答案:

memcpy (temp, arr, size *sizeof(int));

但是在此之后,您还犯了其他几个错误。主要的是,您需要返回temp;而不是返回NULL;

但在delete arr[];之后,您不需要循环。

如果大小为零,请不要delete arr[];


1
删除空指针是可以的,同样删除大小为0的new数组也是可以的。 - Pete Becker
2
另一种可能性是将 memcpy 替换为 std::copy - Pete Becker

1

这是非常复杂的代码。编程的核心在于降低复杂度。

考虑到这一点,这里提供一个合适的 C++ 解决方案:

std::vector<int> arr = {1, 2, 3, 4, 5};
std::vector<int> copy = arr;

就是这样。我希望这个例子能够说明为什么你应该使用标准库(或其他适当的库),而不是重新发明轮子。从你发布的代码中,我猜测你正在学习或已经学习了一本糟糕的C++书籍或课程。把它扔掉,找一本合适的书。C++已经足够复杂了,没有必要增加不必要的复杂性。


1
看起来这是一个编程作业,他们必须通过艰苦的方式学会自己做。 - woolstar
@woolstar 哎呀。在我辩护一下,这个作业太糟糕了。不是因为它本身不好,而是因为学生们显然还没有学会写正确的C++代码,所以这个作业来得太早了。 - Konrad Rudolph
使用STL并不是“正确”的做法。有许多例子表明,你不应该使用STL。例如,正如大多数专业人士所知道的那样,STL不是线程安全的,不能在多线程编程中使用。人们应该在适当的时候使用STL,而不是将其作为救命稻草。学习复制基本数组仍然是正确的做法。 - Chad Befus
@user2705235,当然知道如何复制数组并不是不恰当的。我从未暗示过这一点。然而,在深入了解机器内部之前,了解如何使用高级结构将是有益的。程序员经常忽略这一点,但这是错误的,任何值得尊敬的专业教师都会告诉你。 - Konrad Rudolph
@KonradRudolph:这并不荒谬。像英特尔这样的公司提供库来替换STL以进行多线程编程是有充分理由的。--编辑以去掉我自己的居高临下。 - Chad Befus
显示剩余3条评论

1

为了帮助您理解第一次尝试失败的原因:

*arr = *temp;

这是将新数组的值赋给旧数组,方向相反了。
但它只针对第一个值,*arr不会改变。你增加了*temp,但也需要增加*arr。(此外,手动指针操作和memcopy()相比更好。但嘿,这是为了学习目的,对吧?)
另外,考虑一下那个循环:
for (int i = size; i < newSize; i++)

那是为每个newSize比size大的位迭代一次。但你正在做两件事情。1)复制数据和2)初始化新数据。你现在有的for循环适用于遍历新数据,但不适用于复制已有数据的循环。这应该从零到size,对吧?完成后,您需要返回构建的数组的地址。
return NULL; // default return value.  No memory allocated!

这只是一些虚拟的模拟代码。它是老师提供的占位符,是你应该更改的代码的一部分。

根据您的更新:

我觉得在第二部分中当我为“temp”放入0值时,可能作弊了。

那你还能放什么呢?你确实复制了旧数组数据。然后你扩展了数组。新的领域里放什么?默认值为零是完全有效的。

有没有一种不同的方式可以编写第二部分,使其普适于任何值?

好吧,但你必须实际上有东西可以使用。你的ArrayBuilder函数可以接受额外的参数可能作为变参函数,这样它就知道要将什么值放入新字段中。但你的函数声明没有这个。它只是让数组变得更大。

此外,在您最后一次编辑中,您有两个while循环迭代i,而这两个while循环是在一个for循环内迭代i的。这样做可以工作,但要知道它有点不雅观。当事情变得更加复杂时,这种做法可能会让您陷入麻烦。
相反,您可以这样做:
for (i = 0; i < newSize; i++)
{
  if(i < size)
  {
    temp[i] = arr[i];
  }
  else // if(i >= size && i < newSize) //Wait a sec, this "if" is superfluous. It's conditions are enforced the the first if and the loop condition.
  {
    temp[i] = 0;
  }
}

你最好删除那些让人觉得是别人为你写代码的评论。因为确实有人替你完成了作业。最好的做法是

最后,你应该缩进你的代码!


0
如果我正确理解了任务,该函数应该如下所示。 首先,我会替换函数声明。
int * arrayBuilder(int * arr, int size, int newSize);

for

int * arrayBuilder( const int *arr, size_t size, size_t newSize );

这是它的定义

int * arrayBuilder( int * arr, int size, int newSize)
{
   int *tmp = 0;

   if ( newSize >= 0 )
   {
      tmp = new int[newSize] {};

      int copy_size = std::min( size, newSize );

      if ( copy_size > 0 ) std::copy( arr, arr + copy_size, tmp );
   }

   delete []arr;

   return tmp;
}

0
尝试这个:
代码:
#include <iostream>

using namespace std;

int a[3] = 
{
    1,
    2,
    3
};

int b[3];

int main ()
{
    cout << endl;
    cout << "Array #1 elements: " << endl;
    for(int i = 0; i < 3; ++i)
    {
        cout << a[i] << " ";
    }

    for(int i = 0; i < 3; ++i)
    {
        b[i] = a[i];
    }
    cout << endl << endl;
    cout << "Copying Array #1 elements to Array #2..." << endl;
    cout << endl;
    cout << "Array #2 elements: " << endl;
    for(int i = 0; i < 3; ++i)
    {
        cout << b[i] << " ";
    }
    cout << endl << endl;
    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接