Bagaimana cara mendeklarasikan array string di C ++?

89

Saya mencoba untuk mengulangi semua elemen dari string statis dengan cara terbaik. Saya ingin dapat mendeklarasikannya dalam satu baris dan dengan mudah menambahkan / menghapus elemen darinya tanpa harus melacak jumlahnya. Kedengarannya sangat sederhana, bukan?

Kemungkinan non-solusi:

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

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

Masalah - tidak ada cara untuk membuat vektor pada satu baris dengan daftar string

Kemungkinan non-solusi 2:

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

Masalah - tidak ada cara untuk mendapatkan jumlah string secara otomatis (yang saya ketahui).

Pasti ada cara mudah untuk melakukan ini.

naumcho
sumber
The perpustakaan dorongan menetapkan tampaknya menjadi apa yang Anda cari. Itu membuat penetapan konstanta ke container lebih mudah dari sebelumnya.
Craig H

Jawaban:

108

C ++ 11 menambahkan daftar inisialisasi untuk memungkinkan sintaks berikut:

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

Dukungan untuk fitur C ++ 11 ini telah ditambahkan di setidaknya GCC 4.4 dan hanya di Visual Studio 2013 .

Anthony Cramp
sumber
2018. Baru memulai C ++ dan melakukan beberapa riset tentang array fleksibel. Akhirnya hanya menggunakan vektor ...
Robert Molina
37

Anda dapat secara ringkas menginisialisasi vector<string>dari char*larik yang dibuat secara statis :

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

Ini menyalin semua string, jadi Anda menggunakan memori dua kali. Anda dapat menggunakan saran Will Dean untuk mengganti angka ajaib 3 di sini dengan arraysize (str_array) - meskipun saya ingat ada beberapa kasus khusus di mana versi ukuran array itu mungkin melakukan Sesuatu yang Buruk (maaf saya tidak dapat mengingat detailnya segera) . Tetapi seringkali ini bekerja dengan benar.

Juga, jika Anda benar-benar bersemangat tentang hal satu baris, Anda dapat menentukan makro variadic sehingga satu baris seperti DEFINE_STR_VEC(strvector, "hi", "there", "everyone");berfungsi.

Tyler
sumber
Karena strarrayada di header, bukankah itu melanggar aturan satu definisi?
jww
22

Masalah - tidak ada cara untuk mendapatkan jumlah string secara otomatis (yang saya ketahui).

Ada cara standar untuk melakukan ini, yang oleh banyak orang (termasuk MS) mendefinisikan makro seperti arraysizeuntuk:

#define arraysize(ar)  (sizeof(ar) / sizeof(ar[0]))
Will Dean
sumber
1
Sebagai alternatif, seseorang dapat menggunakan sesuatu seperti ini: template<typename T, size_t N> inline size_t arraysize(T (&ar)[N]) { return N; } (Kata kunci inline tidak diperlukan, tetapi digunakan untuk mendokumentasikan maksud fungsi. Saya yakin kompiler modern secara teoritis dapat mengembalikan seluruh fungsi.
Justin Time - Reinstate Monica
1
Ini gagal untuk petunjuk. Menghitung elemen array harus dilakukan dengan cara yang berbeda di C ++.
jww
8

Deklarasikan array string dalam C ++ seperti ini: char array_of_strings[][]

Sebagai contoh : char array_of_strings[200][8192];

akan menampung 200 string, setiap string memiliki ukuran 8kb atau 8192 byte.

digunakan strcpy(line[i],tempBuffer); untuk meletakkan data dalam larik string.


sumber
FYI, char array_of_strings [] [] tidak dapat menerima string C ++, pastikan untuk mengonversi ke char * terlebih dahulu. cplusplus.com/reference/string/string/c_str
Luqmaan
Karena array_of_stringsada di header, bukankah itu melanggar aturan satu definisi?
jww
7

Satu kemungkinan adalah menggunakan pointer NULL sebagai nilai flag:

const char *list[] = {"dog", "cat", NULL};
for (char **iList = list; *iList != NULL; ++iList)
{
    cout << *iList;
}
Gerhana
sumber
Apa sebenarnya arti char **? Di java, apakah itu daftar string?
IAmGroot
1
@ Doomsknight: Dalam kasus ini, ya. Pada baris pertama saya mendefinisikan sebuah array char*. Dalam memori, ini ditata sebagai 3 petunjuk - satu menunjuk ke "anjing", satu menunjuk ke "kucing" dan satu lagi ditinggalkan NULL. Saya bisa mengambil pointer ke pointer pertama, dan mendapatkan char**- pointer ke pointer ke char. Saat saya menaikkannya, saya memindahkan karakter ** untuk menunjuk ke item berikutnya dalam daftar - penunjuk ke penunjuk yang menunjuk ke "cat", lalu saya menambah lagi, dan mendapatkan penunjuk yang menunjuk ke penunjuk NULL, dan Saya tahu saya sudah selesai. (
Eclipse
4

Anda dapat menggunakan fungsi begindan enddari pustaka rentang Boost untuk dengan mudah menemukan ujung larik primitif, dan tidak seperti solusi makro, ini akan memberikan kesalahan kompilasi alih-alih perilaku rusak jika Anda tidak sengaja menerapkannya ke penunjuk.

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

Anda dapat menggunakan saran Will Dean [ #define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))] untuk mengganti angka ajaib 3 di sini dengan arraysize (str_array) - meskipun saya ingat ada beberapa kasus khusus di mana versi ukuran array itu mungkin melakukan Sesuatu yang Buruk (maaf saya tidak dapat mengingat detailnya segera). Tetapi seringkali ini bekerja dengan benar.

Kasus di mana itu tidak berfungsi adalah ketika "array" sebenarnya hanyalah sebuah pointer, bukan array yang sebenarnya. Juga, karena cara array diteruskan ke fungsi (diubah menjadi pointer ke elemen pertama), ini tidak berfungsi di seluruh pemanggilan fungsi meskipun tanda tangannya terlihat seperti array - some_function(string parameter[])benar-benar some_function(string *parameter).

Matthew Crumley
sumber
3

Berikut contohnya:

#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"));
}
Bayangan2531
sumber
2

Daripada makro itu, mungkin saya menyarankan yang ini:

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) Kami ingin menggunakan makro untuk menjadikannya konstanta waktu kompilasi; hasil pemanggilan fungsi bukanlah konstanta waktu kompilasi.

2) Namun, kami tidak ingin menggunakan makro karena makro dapat digunakan secara tidak sengaja pada penunjuk. Fungsi ini hanya dapat digunakan pada array waktu kompilasi.

Jadi, kami menggunakan definisi fungsi untuk membuat makro "aman"; jika fungsinya ada (yaitu memiliki ukuran bukan nol) maka kami menggunakan makro seperti di atas. Jika fungsinya tidak ada, kami mengembalikan nilai buruk.

DrPizza
sumber
2
#include <boost/foreach.hpp>

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

sumber
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" ) );
}
Dominic.wig
sumber
1

Anda bisa langsung mendeklarasikan array string seperti string s[100];. Kemudian jika Anda ingin mengakses elemen tertentu, Anda bisa mendapatkannya langsung seperti s[2][90]. Untuk tujuan iterasi, ambil ukuran string menggunakan s[i].size()fungsi tersebut.

kajol jain
sumber