Я пытаюсь перебрать все элементы статического массива строк наилучшим образом. Я хочу иметь возможность объявлять его в одной строке и легко добавлять / удалять из него элементы без необходимости отслеживать номер. Звучит очень просто, не правда ли?
Возможные нерешения:
vector<string> v;
v.push_back("abc");
b.push_back("xyz");
for(int i = 0; i < v.size(); i++)
cout << v[i] << endl;
Problems - no way to create the vector on one line with a list of strings
Possible non-solution 2:
string list[] = {"abc", "xyz"};
Problems - no way to get the number of strings automatically (that I know of).
There must be an easy way of doing this.
Ответы:
C++ 11 added initialization lists to allow the following syntax:
std::vector<std::string> v = {"Hello", "World"};
Support for this C++ 11 feature was added in at least GCC 4.4 and only in Visual Studio 2013.
источник
You can concisely initialize a
vector<string>
from a statically-createdchar*
array:char* strarray[] = {"hey", "sup", "dogg"}; vector<string> strvector(strarray, strarray + 3);
This copies all the strings, by the way, so you use twice the memory. You can use Will Dean's suggestion to replace the magic number 3 here with arraysize(str_array) -- although I remember there being some special case in which that particular version of arraysize might do Something Bad (sorry I can't remember the details immediately). But it very often works correctly.
Also, if you're really gung-ho about the one line thingy, you can define a variadic macro so that a single line such as
DEFINE_STR_VEC(strvector, "hi", "there", "everyone");
works.источник
strarray
is in a header, won't it violate the one definition rule?There is a bog-standard way of doing this, which lots of people (including MS) define macros like
arraysize
for:#define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))
источник
template<typename T, size_t N> inline size_t arraysize(T (&ar)[N]) { return N; }
(Inline keyword not necessary, but used to document the function's intent. A modern compiler should theoretically be able to return the entire function, I believe.Declare an array of strings in C++ like this :
char array_of_strings[][]
For example :
char array_of_strings[200][8192];
will hold 200 strings, each string having the size 8kb or 8192 bytes.
use
strcpy(line[i],tempBuffer);
to put data in the array of strings.источник
array_of_strings
is in a header, won't it violate the one definition rule?One possiblity is to use a NULL pointer as a flag value:
const char *list[] = {"dog", "cat", NULL}; for (char **iList = list; *iList != NULL; ++iList) { cout << *iList; }
источник
char*
. In memory, this gets laid out as 3 pointers - one points to "dog", one points to "cat" and one is left NULL. I can take a pointer to that first pointer, and get achar**
- a pointer to pointer to char. When I increment that, I move the char** to point to the next item in the list - a pointer to the pointer that points to "cat", then I increment again, and get a pointer that points to the NULL pointer, and I know I'm done. (You can use the
begin
andend
functions from the Boost range library to easily find the ends of a primitive array, and unlike the macro solution, this will give a compile error instead of broken behaviour if you accidentally apply it to a pointer.const char* array[] = { "cat", "dog", "horse" }; vector<string> vec(begin(array), end(array));
источник
The case where it doesn't work is when the "array" is really just a pointer, not an actual array. Also, because of the way arrays are passed to functions (converted to a pointer to the first element), it doesn't work across function calls even if the signature looks like an array —
some_function(string parameter[])
is reallysome_function(string *parameter)
.источник
Here's an example:
#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")); }
источник
Instead of that macro, might I suggest this one:
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) We want to use a macro to make it a compile-time constant; the function call's result is not a compile-time constant.
2) However, we don't want to use a macro because the macro could be accidentally used on a pointer. The function can only be used on compile-time arrays.
So, we use the defined-ness of the function to make the macro "safe"; if the function exists (i.e. it has non-zero size) then we use the macro as above. If the function does not exist we return a bad value.
источник
#include <boost/foreach.hpp> const char* list[] = {"abc", "xyz"}; BOOST_FOREACH(const char* str, list) { cout << str << endl; }
источник
#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" ) ); }
источник
You can directly declare an array of strings like
string s[100];
. Then if you want to access specific elements, you can get it directly likes[2][90]
. For iteration purposes, take the size of string using thes[i].size()
function.источник