web-dev-qa-db-ja.com

配列から新しい値に値をコピーするにはどうすればよいですか?

私はこれを1週間何度も繰り返し理解しようとしてきましたが、問題が発生し続けています。

私の目的:

整数配列にメモリを割り当てる関数を記述します。この関数は、引数として、整数ポインター、配列のサイズ、および割り当てられるnewSizeを取ります。この関数は、割り当てられたバッファへのポインタを返します。関数が最初に呼び出されたとき、サイズはゼロになり、新しい配列が作成されます。配列サイズがゼロより大きいときに関数が呼び出されると、新しい配列が作成され、古い配列の内容が新しい配列にコピーされます。インストラクターは、このプログラミングチャレンジのスターターコードとして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の値を入れたとき、2番目の部分でだまされたように感じます。以前の配列からデータを取得して新しい配列に配置することを理解していましたが、代わりにそれを作り直しました。 (したがって、この特定の値のセット[0のみ]でのみ機能します)。 2番目の部分をコーディングして、どのような値がスローされても普遍的に機能するようにする別の方法はありますか?

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!
}
4
Peter

少し努力したので。

整数配列にメモリを割り当てる関数を記述します。

この関数のプロトタイプが提供されました。

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

この関数は、引数として、整数ポインター、配列のサイズ、および割り当てられる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!
}
5
Chad

あなたはすでにここで答えを得ています:

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

しかし、その後、他にもいくつかの間違いを犯しています。主に、return temp ;ではなくreturn NULL ;にする必要があります

ただし、delete arr[] ;の後にループは必要ありません。

また、サイズがゼロの場合はdelete arr[]しないでください。

5
woolstar

最初の試みがうまくいかなかった理由を理解するのを助けるためだけに:

*arr = *temp;

これは、新しい配列から古い配列に値を割り当てています。それは逆です。

ただし、最初の値をターゲットにしているだけで、*arrは変更されません。 *tempをインクリメントしますが、*arrもインクリメントする必要があります。 (また、その恐ろしいとmemcopy()のような手動のポインター操作ははるかに優れています。しかしねえ、これは学習目的ですよね?)

また、そのループについて考えてみましょう。

for (int i = size; i < newSize; i++)

これは、newSizeがsizeよりも大きいことをビットごとに1回繰り返します。しかし、ここでは2つのことを行っています。 1)データをコピーし、2)新しいデータを初期化します。あなたが持っているそのforループは、新しいデータを調べるのに適していますが、あなたがすでに持っているデータをコピーするために必要なループではありません。それはゼロからサイズになりますよね?

完了したら、作成した配列のアドレスを返す必要があります。

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

これは単なるダミーのモックコードです。先生によるプレースホルダーです。これは、変更することになっているコードの一部です。

更新ごと:

「temp」に0の値を入れると、2番目の部分でだまされたように感じます

さて、あなたはそこに他に何を入れるつもりでしたか?古い配列データをコピーします。次に、配列を拡張します。新しい領域には何が入りますか?デフォルトとしてのゼロ値は完全に有効です。

2番目の部分をコーディングして、どのような値がスローされても普遍的に機能するようにする別の方法はありますか?

ええ、そうですが、実際に何かを投げる必要があります。 ArrayBuilder関数は、追加の引数 おそらく可変個引数関数として を受け取ることができるため、新しいフィールドに入力する値を認識しています。しかし、関数宣言にはそれがありません。配列を大きくするだけです。

また、最後の編集では、forループ内でiを反復する2つのwhileループがあります。これも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;
  }
}

また、他の誰かがあなたのためにあなたのコードを書いたように聞こえるようにするコメントも削除する必要があります。他の誰かがあなたのために宿題をしたからです。するのが最善です

最後に、THOU SHALT INDENT THY CODE!

1
Philip

割り当てを正しく理解していれば、関数は次のようになります。まず、関数宣言に置き換えます

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

これはひどく複雑なコードです。プログラミングとは、複雑さを減らすことです。

これを念頭に置いて、適切なC++ソリューションを次に示します。

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

それでおしまい。これが、車輪の再発明ではなく、標準ライブラリ(または他の適切なライブラリ)を使用する必要がある理由を示していることを願っています。あなたが投稿したコードから、あなたは恐ろしい本やコースからC++を学んだ(または学んでいる)と思います。それをゴミ箱に捨てて 適切な本を手に入れよう 。 C++はそれなりに複雑であり、不必要な複雑さを追加する必要はありません。

0
Konrad Rudolph

これを試して:

コード:

#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;
}