C ++で文字列の配列を宣言する方法は?


89

私は可能な限り最良の方法で文字列の静的配列のすべての要素を反復処理しようとしています。それを1行で宣言し、番号を追跡しなくても簡単に要素を追加/削除できるようにしたいと考えています。とてもシンプルに聞こえますね。

考えられる非解決策:

vector<string> v;
v.push_back("abc");
b.push_back("xyz");

for(int i = 0; i < v.size(); i++)
    cout << v[i] << endl;

問題-文字列のリストで1行にベクトルを作成する方法がない

考えられる非解決策2:

string list[] = {"abc", "xyz"};

問題-(私が知っている)文字列の数を自動的に取得する方法はありません。

これを行う簡単な方法があるはずです。


ブーストアサインライブラリは、あなたが探している正確に何のようです。これにより、コンテナへの定数の割り当てがこれまで以上に簡単になります。
クレイグH

回答:


108

C ++ 11では、次の構文を許可する初期化リストが追加されました。

std::vector<std::string> v = {"Hello", "World"};

このC ++ 11機能のサポートは、少なくともGCC 4.4で、Visual Studio 2013でのみ追加されました。


2018. C ++を始めたばかりで、柔軟な配列に関するかなりの調査を行いました。最終的にはベクターのみを使用しました...
Robert Molina

37

vector<string>静的に作成されたchar*配列からを簡潔に初期化できます。

char* strarray[] = {"hey", "sup", "dogg"};
vector<string> strvector(strarray, strarray + 3);

ちなみにこれはすべての文字列をコピーするため、メモリを2倍に使用します。ウィルディーンの提案を使用して、ここでマジックナンバー3をarraysize(str_array)に置き換えることができます-その特定のバージョンのarraysizeが何か悪いことをする特別なケースがあることを覚えています(申し訳ありませんが、詳細はすぐには思い出せません) 。しかし、それは非常に頻繁に正しく動作します。

また、1行のものに本当に夢中になっている場合は、可変長マクロを定義して、などの1行が機能するようにすることができますDEFINE_STR_VEC(strvector, "hi", "there", "everyone");


strarrayはヘッダー内にあるため、1つの定義ルールに違反しませんか?
jww

22

問題-(私が知っている)文字列の数を自動的に取得する方法はありません。

これを行うための沼地の標準的な方法があり、多くの人(MSを含む)が次のようなマクロを定義しますarraysize

#define arraysize(ar)  (sizeof(ar) / sizeof(ar[0]))

1
あるいは、このような使用することができますtemplate<typename T, size_t N> inline size_t arraysize(T (&ar)[N]) { return N; } 。(インラインキーワードではない、必要なのが、関数の意図を文書化するために使用さ現代のコンパイラは、理論的に全体の機能を返すことができるはず、私は信じています。
ジャスティン時間-復活モニカ

1
これはポインタでは失敗します。配列要素のカウントは、C ++では別の方法で行う必要があります。
jww

8

次のようにC ++で文字列の配列を宣言します。 char array_of_strings[][]

例えば ​​: char array_of_strings[200][8192];

200文字列を保持します。各文字列のサイズは8kbまたは8192バイトです。

strcpy(line[i],tempBuffer); 文字列の配列にデータを配置するために使用します。


参考までに、char array_of_strings [] []はC ++文字列を受け入れることができません。必ず最初にchar *に変換してください。cplusplus.com/reference/string/string/c_str
Luqmaan

array_of_stringsはヘッダー内にあるため、1つの定義ルールに違反しませんか?
jww

7

1つの可能性は、フラグ値としてNULLポインターを使用することです。

const char *list[] = {"dog", "cat", NULL};
for (char **iList = list; *iList != NULL; ++iList)
{
    cout << *iList;
}

char **は実際にはどういう意味ですか?Javaでは、それは文字列のリストでしょうか?
IAmGroot 2012年

1
@Doomsknight:この場合、はい。最初の行では、の配列を定義していますchar*。メモリでは、これは3つのポインタとして配置されます。1つは「犬」を指し、1つは「猫」を指し、1つはNULLのままです。その最初char**のポインターへのポインターを取得し、-charへのポインターへのポインターを取得できます。それをインクリメントするとき、char **を移動して、リスト内の次の項目を指すようにします。 "cat"を指すポインターへのポインター、次に再びインクリメントして、NULLポインターを指すポインターを取得します。私は終わったと知っています。(
Eclipse

4

Boost範囲ライブラリのbeginend関数を使用して、プリミティブ配列の終わりを簡単に見つけることができます。マクロソリューションとは異なり、これを誤ってポインターに適用すると、動作が壊れる代わりにコンパイルエラーが発生します。

const char* array[] = { "cat", "dog", "horse" };
vector<string> vec(begin(array), end(array));

3

ウィルディーンの提案[ #define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))]を使用して、ここでマジックナンバー3をarraysize(str_array)に置き換えることができます-その特定のバージョンのarraysizeが何か悪いことをする特別なケースがあることを覚えています(申し訳ありませんが、詳細を覚えられません)すぐに)。しかし、それは非常に頻繁に正しく動作します。

これが機能しないのは、「配列」が実際の配列ではなく、単なるポインタの場合です。また、配列が関数に渡される方法(最初の要素へのポインターに変換される)のため、シグニチャーが配列のように見えても、関数呼び出し全体では機能しませsome_function(string parameter[])some_function(string *parameter)


3

次に例を示します。

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

int main() {
    const char* const list[] = {"zip", "zam", "bam"};
    const size_t len = sizeof(list) / sizeof(list[0]);

    for (size_t i = 0; i < len; ++i)
        std::cout << list[i] << "\n";

    const std::vector<string> v(list, list + len);
    std::copy(v.begin(), v.end(), std::ostream_iterator<string>(std::cout, "\n"));
}

2

そのマクロの代わりに、これをお勧めします:

template<typename T, int N>
inline size_t array_size(T(&)[N])
{
    return N;
}

#define ARRAY_SIZE(X)   (sizeof(array_size(X)) ? (sizeof(X) / sizeof((X)[0])) : -1)

1)マクロを使用して、それをコンパイル時の定数にします。関数呼び出しの結果はコンパイル時の定数ではありません。

2)ただし、マクロがポインターで誤って使用される可能性があるため、マクロを使用したくありません。この関数はコンパイル時配列でのみ使用できます。

そのため、関数の定義済み性を使用して、マクロを「安全」にします。関数が存在する(つまり、サイズがゼロでない)場合は、上記のようにマクロを使用します。関数が存在しない場合は、不正な値を返します。


2
#include <boost/foreach.hpp>

const char* list[] = {"abc", "xyz"};
BOOST_FOREACH(const char* str, list)
{
    cout << str << endl;
}

1
#include <iostream>
#include <string>
#include <vector>
#include <boost/assign/list_of.hpp>

int main()
{
    const std::vector< std::string > v = boost::assign::list_of( "abc" )( "xyz" );
    std::copy(
        v.begin(),
        v.end(),
        std::ostream_iterator< std::string >( std::cout, "\n" ) );
}

1

のような文字列の配列を直接宣言できますstring s[100];。その後、特定の要素にアクセスしたい場合は、のように直接取得できますs[2][90]。反復のために、s[i].size()関数を使用して文字列のサイズを取得し ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.