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.
Jawaban:
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 .
sumber
Anda dapat secara ringkas menginisialisasi
vector<string>
darichar*
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.sumber
strarray
ada di header, bukankah itu melanggar aturan satu definisi?Ada cara standar untuk melakukan ini, yang oleh banyak orang (termasuk MS) mendefinisikan makro seperti
arraysize
untuk:#define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))
sumber
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.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
array_of_strings
ada di header, bukankah itu melanggar aturan satu definisi?Satu kemungkinan adalah menggunakan pointer NULL sebagai nilai flag:
const char *list[] = {"dog", "cat", NULL}; for (char **iList = list; *iList != NULL; ++iList) { cout << *iList; }
sumber
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 mendapatkanchar**
- 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. (Anda dapat menggunakan fungsi
begin
danend
dari 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));
sumber
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-benarsome_function(string *parameter)
.sumber
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")); }
sumber
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.
sumber
#include <boost/foreach.hpp> const char* list[] = {"abc", "xyz"}; BOOST_FOREACH(const char* str, list) { cout << str << endl; }
sumber
#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" ) ); }
sumber
Anda bisa langsung mendeklarasikan array string seperti
string s[100];
. Kemudian jika Anda ingin mengakses elemen tertentu, Anda bisa mendapatkannya langsung sepertis[2][90]
. Untuk tujuan iterasi, ambil ukuran string menggunakans[i].size()
fungsi tersebut.sumber