2013-01-08 14 views
12

Qual è il modo corretto in C++ per creare una tabella statica globale di stringhe &?Tabella letterale stringa statica?

Per "globale", intendo: utilizzabile da qualsiasi file che include l'intestazione. Ma non fa parte di alcuni obiettivi di runtime creati singelton objcet.

Per "statico", intendo: poiché è possibile impostare un tempo di esecuzione minimo. Dati in pagine di memoria di sola lettura. Solo 1 istanza di dati per app.

Per "stringa", intendo: array di caratteri terminato da null va bene. std :: string sarebbe bello, ma non credo che si possa fare in termini di quanto sopra. Corretta?

Per "tabella", intendo: intendo un array indicizzabile. Quindi immagino non un tavolo per sé. Ma sono flessibile su questo punto. Aperto alle idee.

Con "C++", voglio dire: C++ non C. (Aggiornamento: C++ 98, non C++ 11)

+1

Cosa intendi per tabella? – Pubby

+0

Array globale? 'const char * table [SIZE];' –

+0

Non credo che _C_ vs _C++ _ farebbe molta differenza qui dato che 'std :: string' è fuori questione ... –

risposta

6

Utilizzare un std::array di stringhe letterali. Non ha costruttore quindi verrà caricato staticamente nella sezione .rodata come un array C, ma ha un'interfaccia di libreria C++ standard. (Iteratori, dimensioni, ecc)

A.h:

#include <array> 

extern std::array<const char*, 3> A; 

A.cpp:

std::array<const char*, 3> A = { "foo", "bar", "baz" }; 

http://en.cppreference.com/w/cpp/container/array

+0

È un peccato che ciò richieda la ripetizione del conteggio degli elementi, ma ne vale la pena per la gradevolezza di std :: array. –

+0

Un 'char const *' non è troppo carino (in termini di interfaccia). A seconda del C++ 11-ness del compilatore, credo che sarebbe possibile costruire una classe con il costruttore 'constexpr' sul modello di' array_ref' come [proposto qui] (http: //www.open- std.org/jtc1/sc22/wg21/docs/papers/2012/n3334.html). –

+0

C'è un modo C++ 98 per fare questo? (A parte ciò che suggerito da @WhozCraig) – nonot1

9

strings.h

extern const char* table[]; 

strings.cpp

const char* table[] = { 
    "Stack", 
    "Overflow", 
} 

Un'altra assumere questa, usando codici di errore per una tabella di ricerca:

err.h

#define ERR_NOT_FOUND 0x1004 
#define ERR_INVALID  0x1005 

bool get_err_msg(int code, const char* &msg); 

err.cpp

typedef struct { 
    int errcode; 
    const char* msg; 
} errmsg_t; 

static errmsg_t errmsg_table[] = { 
    {ERR_NOT_FOUND, "Not found"}, 
    {ERR_INVALID, "Invalid"} 
}; 

#define ERRMSG_TABLE_LEN sizeof(errmsg_table)/sizeof(errmsg_table[0]) 

bool get_err_msg(int code, const char* &msg){ 
    msg = NULL; 
    for (int i=0; i<ERRMSG_TABLE_LEN; i++) { 
     if (errmsg_table[i].errcode == code) { 
      msg = errmsg_table[i].msg; 
      return true; 
     } 
    } 
    return false; 
} 

main.cpp

#include <stdio.h> 
#include "err.h" 

int main(int argc, char** argv) { 
    const char* msg; 
    int code = ERR_INVALID; 
    if (get_err_msg(code, msg)) { 
     printf("%d: %s\n", code, msg); 
    } 
    return 0; 
} 

Sono sicuro che c'è un altro modo C++ di fare questo, ma sono davvero un programmatore C.

+0

Perché l'esterno? – Pubby

+2

Perché sarà incluso in altri file C? –

3

Il table_n fornito rigorosamente per assicurarsi di avere almeno un indizio quanto è grande:

Tabella.h

// header file 
extern const size_t table_n; 
extern const char* table[]; 

Table.cpp

// c/cpp file 
const char *table[] = 
{ 
    "one", 
    "two", 
    "there" 
}; 

const size_t table_n = sizeof(table)/sizeof(table[0]); 

O qualcosa del genere.

4

mi piace modo Jonathon Reinhart, faccio sempre in questo modo, soprattutto se abbiamo una struttura di elementi,

tuttavia, richiede un ciclo per trovare gli elementi (non indicizzato), quindi se vi piace un miglioramento, specialmente per lo stile dei sistemi embedded.

enum ERR_INDEX{ 
ERR_NOT_FOUND=0, 
ERR_INVALID, 
ERR_BAD_LENGTH, 
ERR_MORE_ERR1, 
ERR_MORE_ERR2, 
ERR_MORE_ERR3, 
}; 

static const char * errmsg_table[] = { 
    "Not found", 
    "Invalid", 
    "bad message length", 
    "error 1", 
    "error 2", 
    "error 3", 
}; 

int main(int argc, char** argv) { 
    int code = ERR_INVALID; 
    printf("%d: %s\n", code, errmsg_table[code]); 
    printf("%d: %s\n", code, errmsg_table[ERR_BAD_LENGTH]); 

return 0; 
} 
+2

questo è utile per i codici di errore che iniziano da 0 e incrementano di uno. – aah134

+2

E * solo * per i codici di errore come quello. –

+2

se si ha un altro codice di errore che non è in sequenza, è possibile avere un dizionario che traduce il codice di errore in elenco sequenziale, o semplicemente un dizionario che ha il codice di errore come chiave e un messaggio di errore come stringa :) – aah134

Problemi correlati