Estoy tratando de iterar sobre todos los elementos de una matriz estática de cadenas de la mejor manera posible. Quiero poder declararlo en una línea y agregar / eliminar elementos fácilmente sin tener que realizar un seguimiento del número. Suena muy simple, ¿no?
Posibles no soluciones:
vector<string> v;
v.push_back("abc");
b.push_back("xyz");
for(int i = 0; i < v.size(); i++)
cout << v[i] << endl;
Problemas: no hay forma de crear el vector en una línea con una lista de cadenas
Posible no solución 2:
string list[] = {"abc", "xyz"};
Problemas: no hay forma de obtener la cantidad de cadenas automáticamente (que yo sepa).
Debe haber una manera fácil de hacer esto.
Respuestas:
C ++ 11 agregó listas de inicialización para permitir la siguiente sintaxis:
std::vector<std::string> v = {"Hello", "World"};
Se agregó soporte para esta característica de C ++ 11 en al menos GCC 4.4 y solo en Visual Studio 2013 .
fuente
Puede inicializar de forma concisa a
vector<string>
desde unachar*
matriz creada estáticamente :char* strarray[] = {"hey", "sup", "dogg"}; vector<string> strvector(strarray, strarray + 3);
Esto copia todas las cadenas, por cierto, por lo que usa el doble de memoria. Puede usar la sugerencia de Will Dean para reemplazar el número mágico 3 aquí con arraysize (str_array), aunque recuerdo que hubo un caso especial en el que esa versión particular de arraysize podría hacer algo malo (lo siento, no puedo recordar los detalles de inmediato) . Pero muy a menudo funciona correctamente.
Además, si está realmente entusiasmado con la cosa de una línea, puede definir una macro variadic para que una sola línea como
DEFINE_STR_VEC(strvector, "hi", "there", "everyone");
funcione.fuente
strarray
está en un encabezado, ¿no violará la regla de una definición?Hay una forma estándar de pantano de hacer esto, que muchas personas (incluida MS) definen macros como
arraysize
para:#define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))
fuente
template<typename T, size_t N> inline size_t arraysize(T (&ar)[N]) { return N; }
(La palabra clave en línea no es necesaria, pero se usa para documentar la intención de la función. En teoría, un compilador moderno debería poder devolver la función completa, creo.Declare una matriz de cadenas en C ++ como esta:
char array_of_strings[][]
Por ejemplo :
char array_of_strings[200][8192];
contendrá 200 cadenas, cada una de las cuales tendrá un tamaño de 8 kb u 8192 bytes.
se usa
strcpy(line[i],tempBuffer);
para poner datos en la matriz de cadenas.fuente
array_of_strings
está en un encabezado, ¿no violará la regla de una definición?Una posibilidad es utilizar un puntero NULL como valor de marca:
const char *list[] = {"dog", "cat", NULL}; for (char **iList = list; *iList != NULL; ++iList) { cout << *iList; }
fuente
char*
. En la memoria, esto se presenta como 3 punteros: uno apunta a "perro", uno apunta a "gato" y el otro se deja NULL. Puedo tomar un puntero a ese primer puntero y obtenerchar**
un puntero a un puntero a char. Cuando incremento eso, muevo el carácter ** para que apunte al siguiente elemento de la lista: un puntero al puntero que apunta a "gato", luego lo vuelvo a incrementar y obtengo un puntero que apunta al puntero NULL, y Sé que he terminado. (Puede usar las funciones
begin
yend
de la biblioteca de rango de Boost para encontrar fácilmente los extremos de una matriz primitiva y, a diferencia de la solución macro, esto dará un error de compilación en lugar de un comportamiento roto si lo aplica accidentalmente a un puntero.const char* array[] = { "cat", "dog", "horse" }; vector<string> vec(begin(array), end(array));
fuente
El caso en el que no funciona es cuando la "matriz" es en realidad solo un puntero, no una matriz real. También, debido a la forma en que las matrices son pasados a las funciones (convertido a un puntero al primer elemento), que no funciona a través de llamadas a funciones, incluso si las miradas de la firma como una matriz -
some_function(string parameter[])
es realmentesome_function(string *parameter)
.fuente
He aquí un ejemplo:
#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")); }
fuente
En lugar de esa macro, podría sugerir esta:
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) Queremos usar una macro para convertirla en una constante en tiempo de compilación; El resultado de la llamada a la función no es una constante en tiempo de compilación.
2) Sin embargo, no queremos usar una macro porque la macro podría usarse accidentalmente en un puntero. La función solo se puede utilizar en matrices en tiempo de compilación.
Entonces, usamos la definición de la función para hacer que la macro sea "segura"; si la función existe (es decir, tiene un tamaño distinto de cero), usamos la macro como se indicó anteriormente. Si la función no existe devolvemos un valor incorrecto.
fuente
#include <boost/foreach.hpp> const char* list[] = {"abc", "xyz"}; BOOST_FOREACH(const char* str, list) { cout << str << endl; }
fuente
#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" ) ); }
fuente
Puede declarar directamente una matriz de cadenas como
string s[100];
. Luego, si desea acceder a elementos específicos, puede obtenerlo directamente comos[2][90]
. Para propósitos de iteración, tome el tamaño de la cadena usando las[i].size()
función.fuente