2013-01-08 29 views
12

Jaki jest poprawny sposób w C++, aby utworzyć globalną tabelę strun o stałej wartości &?Statyczny ciąg literału?

Przez "globalny" mam na myśli: Możliwość użycia z dowolnego pliku zawierającego nagłówek. Ale nie jest częścią jakiegoś czasu stworzonego przez singltona.

Przez "statyczny", mam na myśli: Jak mało czasu pracy można skonfigurować. Dane na stronach pamięci tylko do odczytu. Tylko 1 wystąpienie danych na aplikację.

Przez "ciąg" mam na myśli: Null zakończona tablica znaków jest w porządku. std :: string byłoby fajne, ale nie sądzę, żeby można to było zrobić w sensie powyższym. Poprawny?

Przez "tabelę" mam na myśli: tablicę indeksowalną. Więc nie wydaje mi się, żeby był to stół per se. Ale jestem elastyczny w tym punkcie. Otwarty na pomysły.

Przez "C++", to znaczy: C++ nie C. (Aktualizacja: C++ 98, a nie w C++ 11)

+1

Co masz na myśli przez tabelę? – Pubby

+0

Globalna tablica? 'const char * table [SIZE];' –

+0

Nie sądzę, że _C_ vs _C++ _ zrobiłoby wielką różnicę, biorąc pod uwagę, że 'std :: string' nie wchodzi w grę ... –

Odpowiedz

6

Użyj std::array z napisowych. Nie ma konstruktora, więc będzie ładowany statycznie w sekcji .rodata jak tablica C, ale ma standardowy interfejs biblioteki C++. (Iteratory, wielkość, itp)

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

Szkoda, że ​​wymaga to powtórzenia liczby elementów, ale warto o tym pomyśleć dla zasady std :: array. –

+0

'char const *' nie jest jednak zbyt miły (pod względem interfejsu). W zależności od C++ 11-tego kompilatora, wierzę, że byłoby możliwe zbudowanie klasy z konstruktorem 'constexpr' na modelu' array_ref' takim jak [proponowane tutaj] (http: //www.open- std.org/jtc1/sc22/wg21/docs/papers/2012/n3334.html). –

+0

Czy istnieje sposób C++ 98, aby to zrobić? (Poza tym, co zasugerował @WhozCraig) – nonot1

9

strings.h

extern const char* table[]; 

strings.cpp

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

Innym podjąć w tej sprawie, wykorzystując kody błędów na tablicy przeglądowej:

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; 
} 

Jestem pewien, że jest bardziej C++ sposób to zrobić, ale jestem naprawdę programista C.

+0

Dlaczego "extern"? – Pubby

+2

Ponieważ będzie on dołączony do innych plików C? –

3

table_n warunkiem ściśle w celu zapewnienia przynajmniej mieć wskazówkę, jak duże to jest:

Table.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]); 

Albo coś w tym stylu.

4

Lubię Jonathon Reinhart drogę, zawsze zrobić to w ten sposób, zwłaszcza jeśli mamy strukturę elementów

jednak wymaga on pętlę, aby znaleźć elementy (nie indeksowane), więc jeśli lubisz ulepszenie, szczególnie w stylu systemów wbudowanych.

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

jest to dobre dla kodów błędów, które zaczynają się od 0 i zwiększają się o jeden. – aah134

+2

I * tylko * w przypadku takich kodów błędów. –

+2

Jeśli masz więcej kodu błędu, który nie jest w sekwencji, możesz mieć słownik, który tłumaczy kod błędu na listę sekwencyjną lub po prostu słownik, który ma kod błędu jako klucz, i komunikat o błędzie jako ciąg znaków :) – aah134

Powiązane problemy