1

サイズの異なる 2 つの C++ 配列の内容を (定義済みの C++ 関数を使用せずに) 交換できるかどうか疑問に思っています。私のコードは次のとおりです。

#include <iostream>
#include <string>

using namespace std;  

void swapNames(char a[], char b[])
{

    //can be done with one temp; using two for clarity purposes 
    char* temp = new char[80];
    char* temp2 = new char[80];
    int x = 0;

    while(*(b+x)!='\0')
    {
        *(temp+x) = *(b+x);
        x=x+1;
    }

    x=0;
    while(*(a+x)!='\0')
    {
        *(temp2+x) = *(a+x);
        x=x+1;
    }

    x=0;    
    while(*(temp2+x)!='\0')
    {
        *(b+x) = *(temp2+x);
        x=x+1;
    }

    x=0;
    while(*(temp+x)!='\0')
    {
        *(a+x) = *(temp+x);
        x=x+1;
    }
}

int main()
{
    char person1[] = "James";
    char person2[] = "Sarah";

    swapNames(person1, person2);

    cout << endl << "Swap names..." << endl;
    cout << endl << "Person1 is now called " << person1;

    cout << "Person2 is now called " << person2 << endl;;
}

私の最初のアイデアは、person1 と person2 自体への参照を渡し、データを一時変数に格納し、それらに割り当てられたメモリを削除し、スワップされたデータで新しく作成された配列にそれらをリンクすることでした。これにより、事前定義されたメモリ制限を回避できると考えました。ただし、参照 (&) を配列に渡すことはほとんど許可されていないようです。

person1 と person2 が同じサイズの場合、上記は正常に機能します。ただし、サイズの異なる名前を使用すると、問題が発生します。これは、最初に person1 と person2 を作成したときに割り当てたメモリ ブロックを変更できないためだと思います。

また、サイズを事前定義せずに C++ で新しい配列を作成することは可能ですか? IE は、サイズに制限を設けずに一時変数を作成する方法です。

4

3 に答える 3

5
char person1[] = "James";

は、次の省略形です。

char person1[6] = "James";

後で person1 に 6 文字を超えて保存することはできません。本当に必要なものがさまざまな長さの文字列である場合は、std::string標準ライブラリ型を優先して C スタイルの文字列を捨てることをお勧めします。

#include <string>
#include <algorithm>

std::string person1 = "James";
std::string person2 = "Sarah";

swap(person1, person2);

あなたの本が s の前に C スタイルの文字列を教えている場合は、新しい本を入手するstd::stringことを検討してください。

于 2012-10-14T14:25:48.440 に答える
1

配列が固定サイズである限り、配列への参照は許可されます。

あなたが考えているすべての複雑なことの代わりに、簡単な答えがあります。ベクトルを使用するだけです。

vector<char> a;
vector<char> b;
...
a.swap(b);

もっと簡単なことは何ですか?

また、ベクトルは、「サイズを事前定義せずに C++ で新しい配列を作成することは可能ですか?」という質問に対する答えでもあります。ベクトルを作成し、後でサイズを変更できます (これはほとんど同じことです)。

于 2012-10-14T14:35:19.620 に答える
0

生の配列よりもコンテナー クラスを優先する必要があります。ただし、絶対に配列を使用する必要がある場合は、一時配列を動的に割り当てることに頼ることなく確実にスワッピングを実行できます。テンプレートを使用して、swap 関数に渡される配列の型とサイズを静的に決定します。

#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>

template<typename T, size_t N>
void swap_arrays( T(&left)[N], T(&right)[N] )
{
  T temp[N];

  // copy left to temp
  std::copy( std::begin(left), std::end(left), std::begin(temp) );
  // copy right to left
  std::copy( std::begin(right), std::end(right), std::begin(left) );
  // copy temp to right
  std::copy( std::begin(temp), std::end(temp), std::begin(right) );
}

template<typename T, size_t N>
void swap_and_print( T(&left)[N], T(&right)[N] )
{
  std::cout << "\nBefore swapping: \n";

  std::cout << "  Left:";
  std::for_each( std::begin(left), std::end(left), 
                 []( T const& t ) { std::cout << " " << t; } );
  std::cout << "\n  Right:";
  std::for_each( std::begin(right), std::end(right), 
                 []( T const& t ) { std::cout << " " << t; } );

  swap_arrays( left, right );

  std::cout << "\nAfter swapping: \n";

  std::cout << "  Left:";
  std::for_each( std::begin(left), std::end(left), 
                 []( T const& t ) { std::cout << " " << t; } );
  std::cout << "\n  Right:";
  std::for_each( std::begin(right), std::end(right), 
                 []( T const& t ) { std::cout << " " << t; } );
}

int main()
{
  int foo1[] = {1,2,3,4,5};
  int bar1[] = {6,7,8,9,10};

  swap_and_print( foo1, bar1 );

  char foo2[] = "James";
  char bar2[] = "Sarah";

  swap_and_print( foo2, bar2 );
}

出力:

Before swapping: 
  Left: 1 2 3 4 5
  Right: 6 7 8 9 10
After swapping: 
  Left: 6 7 8 9 10
  Right: 1 2 3 4 5
Before swapping: 
  Left: J a m e s �
  Right: S a r a h �
After swapping: 
  Left: S a r a h �
  Right: J a m e s �

注: 2 番目の例の最後の奇妙な文字は、入力がchar終端の null 文字を含む配列であるためです。表示されているのはその視覚的表現です (コードが文字として出力しているため)。

于 2012-10-14T15:25:37.450 に答える