web-dev-qa-db-ja.com

C ++で配列内のすべての要素を同じ数に初期化する方法

すべてを-1に設定してint配列を初期化しようとしています。

以下を試しましたが動作しません。最初の値を-1に設定するだけです。

int directory[100] = {-1};

なぜうまくいかないのですか?

21
neuromancer

vectorを示唆するすべての回答に驚いています。彼らは同じものではありません!

std::fill を使用します(<algorithm>から):

int directory[100];
std::fill(directory, directory + 100, -1);

質問には直接関係しませんが、配列に関しては、Niceヘルパー関数が必要な場合があります。

template <typename T, size_t N>
T* end(T (&pX)[N])
{
    return pX + N;
}

与える:

int directory[100];
std::fill(directory, end(directory), -1);

したがって、サイズを2回リストする必要はありません。

36
GManNickG

_std::array_ の使用をお勧めします。 3つの理由があります。
1。配列は、添え字(つまり、_operator[]_)演算でインデックスの範囲外に対する実行時の安全性を提供します。
2。配列自動的にサイズを運ぶ個別に渡す必要なし
3。そして最も重要なこととして、配列はこの問題に必要なfill()メソッドを提供します

_#include <array>
#include <assert.h>

typedef std::array< int, 100 > DirectoryArray;

void test_fill( DirectoryArray const & x, int expected_value ) {
    for( size_t i = 0; i < x.size(); ++i ) {
        assert( x[ i ] == expected_value );
    }
}

int main() {
    DirectoryArray directory;
    directory.fill( -1 );
    test_fill( directory, -1 );
    return 0;
}
_

配列の使用には、コンパイルに「-std = c ++ 0x」の使用が必要です(上記のコードに適用)。

それが利用できない場合、またはそれがオプションでない場合は、std :: fill()( GMan で推奨)などのその他のオプション、またはfill()メソッドの手動コーディングを選択できます。

8
Arun

要素の数が少ない場合は、要素を順番に指定できます。配列の初期化は、各要素に適用される単一の値を指定するのではなく、各要素を指定することによって機能します。

_int x[3] = {-1, -1, -1 };
_

ベクトルを使用し、コンストラクタを使用してすべての値を初期化することもできます。 &v.front()を指定すると、後でraw配列バッファーにアクセスできます

_std::vector directory(100, -1);
_

memsetまたは他のさまざまな類似の関数を使用してCで行う方法もあります。 memsetは指定したバッファーの各文字に対して機能しますが、_0_のような値では正常に機能しますが、_-1_の負の数値の格納方法によっては機能しない場合があります。


STLで fill_n を使用して配列を初期化することもできます。 for_eachを使用して、各要素に対する汎用アクションを実行できます。

_fill_n(directory, 100, -1);
_

または、本当に不十分な方法で進みたい場合は、100回の反復でforループを実行し、_directory[i] = -1;_を実行できます

5
Brian R. Bondy

本当に配列が必要な場合は、ブースト array クラスを使用できます。これは、メンバーを割り当てます。

boost::array<int,N> array; // boost arrays are of fixed size!
array.assign(-1);
5
jopa

同じ質問があり、その方法を見つけました。ドキュメントには次の例が示されています。

std::array<int, 3> a1{ {1, 2, 3} }; // double-braces required in C++11 (not in C++14)

だから私は試してみました:

std::array<int, 3> a1{ {1} }; // double-braces required in C++11 (not in C++14)

そして、それはすべての要素が値として1を持っていることで動作します。 =演算子では機能しません。おそらくC++ 11の問題です。

3
Xavier Bigand

それは正しく機能します。イニシャライザへの期待が間違っています。本当にこのアプローチを採用したい場合は、イニシャライザに100個のコンマ区切りの-1が必要です。しかし、配列のサイズを増やすとどうなりますか?

3
Johnsyweb

u以下のようにforループを使用するだけです:

for (int i=0; i<100; i++)
{ 
a[i]= -1;
}

結果として、uはA [100] = {-1、-1、-1 ..........(100回)}を取得できます。

1
T. K. Sah

正しく機能しています。これがリスト初期化子の動作方法です。

C99標準の6.7.8.10はこれをカバーしていると思います:

自動保存期間を持つオブジェクトが明示的に初期化されていない場合、その値は不確定です。静的な保存期間を持つオブジェクトが明示的に初期化されていない場合は、次のようになります。

  • ポインタ型の場合は、nullポインタに初期化されます。
  • 算術型の場合、(正または符号なし)ゼロに初期化されます。
  • 集合体の場合、すべてのメンバーはこれらのルールに従って(再帰的に)初期化されます。
  • 共用体の場合、最初の名前付きメンバーは、これらのルールに従って(再帰的に)初期化されます。

配列内のすべての要素をゼロ以外の同じ値にする必要がある場合は、ループまたは memset を使用する必要があります。

また、何をしているのか本当にわかっていない限り、 C++の配列よりもベクターが推奨されます

コンテナーと配列の違いについて、以下の点を理解しておく必要があります。

  1. コンテナークラスは、プログラマーの生産性を高めます。そのため、周りの人がコンテナクラスを使用することをいとわない一方で配列を使用するように主張する場合は、実際よりも生産性が低くなります(実際よりも賢く、経験が豊富であっても!)。
  2. コンテナクラスを使用すると、プログラマはより堅牢なコードを記述できます。そのため、周りの人がコンテナクラスを使用しても構わないのに配列を使用する場合は、コードにバグよりも多くのバグがあります(より賢く、経験が豊富な場合でも)。
  3. コンテナクラスを使用できるのと同じくらい高速かつ安全に配列を使用できるほどスマートで経験が豊富である場合、他の誰かがおそらくコードを保守することになり、バグを引き起こす可能性があります。または、さらに悪いことに、コードを保守できるのはあなただけです。そのため、管理者は開発から離れて、常勤の保守の役割にあなたを移動させます。

リンクされた質問には他にもたくさんあります。それを読んでください。

1
Mark Rushakoff

配列の代わりにintのベクトルを使用してください。

vector<int> directory(100,-1);                       // 100 ints with value 1
1
Satbir

このループを使用してください。

for(int i =0 ; i < 100 ; i++) directory[i] =0;
0
Majid

全能のmemset()は、C/C++/C++ 11/C++ 14の配列およびstdコンテナーのジョブを実行します

0
MORTAL

fill_n()メソッドを使用するだけです。

_int n;
cin>>n;
int arr[n];
int value = 9;
fill_n(arr, n, value); // 9 9 9 9 9...
_

詳細 についてfill_n()

または

fill()メソッドを使用できます。

_int n;
cin>>n;
int arr[n];
int value = 9;
fill(arr, arr+n, value); // 9 9 9 9 9...
_

詳細fill()メソッドについて。

注:これらのメソッドはどちらもalgorithmライブラリ(_#include<algorithm>_)で使用できます。それを含めることを忘れないでください。

0
Genius

_int directory[100] = {-1}_が機能しない理由は、 配列の初期化 で何が起こるかです。

明示的に初期化されていないすべての配列要素は、静的ストレージ期間を持つオブジェクトと同じ方法で暗黙的に初期化されます。

intsは 暗黙的に初期化 です:

符号なしゼロに初期化されました

明示的に初期化されていないすべての配列要素は、静的ストレージ期間を持つオブジェクトと同じ方法で暗黙的に初期化されます。

C++ 11では、配列に特化した begin および end が導入されました。

これは、directoryのような配列(単なるポインタではない)を指定すると、いくつかの回答で示唆されているように fill を使用できることを意味します。

_fill(begin(directory), end(directory), -1)
_

このようなコードを記述したが、その実装方法を忘れてから機能を再利用することにしたが、directoryのサイズを60に変更することにしたとします。beginendを使用してコードを記述した場合、完了しました。
一方、これを実行した場合: fill(directory, directory + 100, -1) 次に、その100を60に変更することも忘れないでください。そうしないと、未定義の動作が発生します。

0
Jonathan Mee

未処理の配列を使用して実行しようとしていることを実行できません(初期化リストに100個すべての-1sを明示的にリストしない限り)、vectorを使用して実行できます。

vector<int> directory(100, -1);

さらに、前述のその他の方法のいずれかを使用して、配列を作成し、値を-1に設定できます。

0
Stephen

Std :: arrayの使用が許可されている場合は、以下を実行できます。

#include <iostream>
#include <algorithm>
#include <array>
using namespace std;

template <class Elem, Elem pattern, size_t S, size_t L>
struct S_internal {
    template <Elem... values>
    static array<Elem, S> init_array() {
        return S_internal<Elem, pattern, S, L - 1>::init_array<values..., pattern>();
    }
};

template <class Elem, Elem pattern, size_t S>
struct S_internal<Elem, pattern, S, 0> {
    template <Elem... values>
    static array<Elem, S> init_array() {
        static_assert(S == sizeof...(values), "");
        return array<Elem, S> {{values...}};
    }
};

template <class Elem, Elem pattern, size_t S>
struct init_array
{
    static array<Elem, S> get() {
        return S_internal<Elem, pattern, S, S>::init_array<>();
    }
};

void main()
{
    array<int, 5> ss = init_array<int, 77, 5>::get();
    copy(cbegin(ss), cend(ss), ostream_iterator<int>(cout, " "));
}

出力は次のとおりです。

77 77 77 77 77 77

0
Yola