Come dichiarare un array di stringhe in C ++?


89

Sto cercando di iterare su tutti gli elementi di un array statico di stringhe nel miglior modo possibile. Voglio essere in grado di dichiararlo su una riga e aggiungere / rimuovere facilmente elementi da esso senza dover tenere traccia del numero. Sembra davvero semplice, non è vero?

Possibili non soluzioni:

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

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

Problemi: non è possibile creare il vettore su una riga con un elenco di stringhe

Possibile mancata soluzione 2:

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

Problemi: nessun modo per ottenere automaticamente il numero di stringhe (che io sappia).

Ci deve essere un modo semplice per farlo.


La libreria di assegnazione boost sembra essere esattamente quello che stai cercando. Rende l'assegnazione di costanti ai contenitori più semplice che mai.
Craig H

Risposte:


108

C ++ 11 ha aggiunto elenchi di inizializzazione per consentire la seguente sintassi:

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

Il supporto per questa funzionalità C ++ 11 è stato aggiunto almeno in GCC 4.4 e solo in Visual Studio 2013 .


2018. Ho appena avviato C ++ e ho svolto alcune ricerche sugli array flessibili. Ho finito per usare solo i vettori ...
Robert Molina

37

Puoi inizializzare in modo conciso un vector<string>da un char*array creato staticamente :

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

Questo copia tutte le stringhe, a proposito, quindi usi il doppio della memoria. Puoi usare il suggerimento di Will Dean per sostituire il numero magico 3 qui con arraysize (str_array) - anche se ricordo che c'era qualche caso speciale in cui quella particolare versione di arraysize potrebbe fare qualcosa di brutto (scusa non ricordo immediatamente i dettagli) . Ma molto spesso funziona correttamente.

Inoltre, se sei davvero entusiasta della cosa su una riga, puoi definire una macro variadica in modo che una singola riga funzioni DEFINE_STR_VEC(strvector, "hi", "there", "everyone");.


Poiché si strarraytrova in un'intestazione, non violerà la regola dell'unica definizione?
jww

22

Problemi: nessun modo per ottenere automaticamente il numero di stringhe (che io sappia).

Esiste un modo standard per farlo, che molte persone (incluso MS) definiscono macro come arraysizeper:

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

1
In alternativa, si potrebbe usare qualcosa del genere: template<typename T, size_t N> inline size_t arraysize(T (&ar)[N]) { return N; } (La parola chiave inline non è necessaria, ma utilizzata per documentare l'intento della funzione. Un compilatore moderno dovrebbe teoricamente essere in grado di restituire l'intera funzione, credo.
Justin Time - Reinstate Monica

1
Questo non riesce per i puntatori. Il conteggio degli elementi dell'array dovrebbe essere fatto in modo diverso in C ++.
jww

8

Dichiara un array di stringhe in C ++ in questo modo: char array_of_strings[][]

Per esempio : char array_of_strings[200][8192];

conterrà 200 stringhe, ciascuna delle quali ha la dimensione di 8kb o 8192 byte.

utilizzare strcpy(line[i],tempBuffer); per inserire dati nell'array di stringhe.


Cordiali saluti, char array_of_strings [] [] non può accettare stringhe C ++, assicurati di convertire prima in char *. cplusplus.com/reference/string/string/c_str
Luqmaan

Poiché si array_of_stringstrova in un'intestazione, non violerà la regola dell'unica definizione?
jww

7

Una possibilità è usare un puntatore NULL come valore di flag:

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

Che cosa significa effettivamente char **? In Java, sarebbe un elenco di stringhe?
IAmGroot

1
@ Doomsknight: In questo caso, sì. Nella prima riga definisco un array di char*. In memoria, questo viene strutturato come 3 puntatori: uno punta a "cane", uno a "gatto" e uno rimane NULL. Posso prendere un puntatore a quel primo puntatore e ottenere char**un puntatore a un puntatore a char. Quando lo incremento, sposto il carattere ** in modo che punti all'elemento successivo nell'elenco - un puntatore al puntatore che punta a "gatto", quindi incremento di nuovo e ottengo un puntatore che punta al puntatore NULL, e So di aver finito. (
Eclipse

4

È possibile utilizzare le funzioni begine enddalla libreria degli intervalli Boost per trovare facilmente le estremità di un array primitivo e, a differenza della soluzione macro, questo darà un errore di compilazione invece di un comportamento interrotto se lo si applica accidentalmente a un puntatore.

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

3

Puoi usare il suggerimento di Will Dean [ #define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))] per sostituire il numero magico 3 qui con arraysize (str_array) - anche se ricordo che ci sono stati casi speciali in cui quella particolare versione di arraysize potrebbe fare qualcosa di brutto (scusa non ricordo i dettagli subito). Ma molto spesso funziona correttamente.

Il caso in cui non funziona è quando l '"array" è in realtà solo un puntatore, non un array effettivo. Inoltre, a causa del modo in cui gli array vengono passati alle funzioni (convertiti in un puntatore al primo elemento), non funziona tra le chiamate di funzione anche se la firma sembra un array - lo some_function(string parameter[])è davvero some_function(string *parameter).


3

Ecco un esempio:

#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

Invece di quella macro, potrei suggerire questa:

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) Vogliamo usare una macro per renderla una costante del tempo di compilazione; il risultato della chiamata di funzione non è una costante del tempo di compilazione.

2) Tuttavia, non vogliamo utilizzare una macro perché la macro potrebbe essere utilizzata accidentalmente su un puntatore. La funzione può essere utilizzata solo su array in fase di compilazione.

Quindi, usiamo la definizione della funzione per rendere la macro "sicura"; se la funzione esiste (cioè ha una dimensione diversa da zero) allora usiamo la macro come sopra. Se la funzione non esiste restituiamo un valore errato.


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

Puoi dichiarare direttamente un array di stringhe come string s[100];. Quindi se vuoi accedere a elementi specifici, puoi ottenerlo direttamente come s[2][90]. Per scopi di iterazione, prendi la dimensione della stringa usando la s[i].size()funzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.