come usare bene la costante std :: string in c ++

5

Nel mio attuale progetto di codice, c'è un sacco di stringhe costanti che uso per stampare i messaggi di errore.

Hardcoding tali stringhe è generalmente considerato una cattiva pratica. Ora sto cercando un "modo pulito" per includere queste stringhe nel mio programma. Pertanto ho scritto un "constants.h" e "constants.cpp" che assomiglia a

#ifndef CONSTANTS_H_
#define CONSTANTS_H_

extern std::string error_message_1;

#endif

e constants.cpp:

#include "constants.h"

std::string error_message_1 = "this is just a sample, not my actual naming convention. move on the the question ;-)"

Quindi potresti vedere il problema che ho con questo: a causa di molti messaggi di errore, il nome della variabile stesso è abbastanza lungo. Il messaggio di errore è ancora più lungo, quindi blocca gli 80 caratteri standard in una riga di codice.

Ovviamente voglio che il mio codice sia bello e pulito. Non mi piace andare oltre gli 80 caratteri per riga di codice. Neanche a me piace qualcosa come:

std::string error_message_1 = "this is just a sample about how to"
                              " have one string across many lines"
                              " in the source code. this is not "
                              "very pretty too..";
std::string msg = "and suddenly there's one line which is good..";
std::string error_message_with_longer_name = "and it's even "
                                             "uglier with not "
                                             "equally long "
                                             "variable names";

Memorizzare le stringhe in un file esterno che si dovrebbe leggere all'inizio del programma non sembra essere ottimale poiché il compilatore non può avvertire le stringhe mancanti. Fondamentalmente questo sarebbe un disastro da mantenere.

Quindi cosa fai a riguardo? C'è una cosa così carina come "Risorse", che io conosco di sviluppo di Android (o è Java in generale?)?

Nota: per favore NON dirmi che la mia convenzione di denominazione è cattiva. Quanto sopra è solo un esempio. Non è quello che sembra; -)

    
posta stefan 20.05.2012 - 12:55
fonte

4 risposte

7

Hardcoding such strings is generally considered to be bad practice.

Non sono sicuro che sia d'accordo.

Le stringhe letterali sono facili da leggere piuttosto che il nome di una stringa. Se si desidera lo stesso testo per più posizioni, incapsulare il testo in una funzione e chiamare la singola funzione per visualizzare il messaggio.

Se vuoi centralizzare il testo in un singolo file. Quindi quello che stai cercando è: stringhe come risorse che non spostano manualmente tutti i tuoi valori letterali di stringa in variabili di stringa.

Controlla i seguenti pacchetti (normalmente usati nella localizzazione ma funzioneranno qui).

* gettext

Fondamentalmente ciò che questo pacchetto fa ti permette di lasciare la versione "inglese" del messaggio nel codice. Ma userà il testo "inglese" come chiave in una tabella di risorse per ottenere la versione corrente della stringa per un determinato locale.

Quindi il codice che assomigliava a questo:

printf ("and suddenly there's one line which is good..");

// Now looks like this:

printf (gettext ("and suddenly there's one line which is good.."));

Non è necessario passare attraverso il hassel di estrarre tutte le stringhe costanti in un altro pacchetto.

Vedi qui per tutti i dettagli. link

Personalmente uso il sopra in combinazione con le formattazione boost delle librerie per la localizzazione.

std::cout << boost::formt("The time is %1 in %2.") % time % country;

becomes:

std::cout << boost::formt(gettext("The time is %1 in %2.")) % time % country;

English Resource File:      "The time is %1 in %2."
Azerbaijani Resource File:  "Saat %2 saat %1 deyil."
    
risposta data 20.05.2012 - 19:28
fonte
5

Hardcoding such strings is generally considered to be bad practice

Ti rendi conto che avere un file che contiene letterali è ancora hardcoding? Sembra che tu stia confondendo hardcoding con numeri magici. Le stringhe, in generale, non sono magiche e quindi non è necessario dare loro un nome. Spostarli su una costante è necessario solo per evitare duplicazioni. Se stai usando una stringa solo una volta (come nel caso della maggior parte dei messaggi di errore), allora è inutile spostarli in un altro file, a meno che per qualche motivo lo stai facendo come file di configurazione in fase di compilazione.

Se è fondamentale che l'utente sia in grado di modificare i messaggi di errore, spostali in un file di configurazione (non in un .hpp).

Se ti serve per la traduzione, usa qualcosa come gettext che ti consente di fornire file di traduzione e mantenere la tua fonte pulito.

Inoltre, non utilizzare std::string per le espressioni costanti stringa - usa const char[] invece.

    
risposta data 20.05.2012 - 13:19
fonte
0

Le stringhe di hardcoding vanno bene fintanto che i valori non devono mai cambiare. Li ho visti immagazzinati come stati statici e si riferivano a un enum associato molte volte.

Potresti avvolgerlo in una classe se volessi rendere l'interfaccia più semplice.

Tuttavia, non ci sono cose realmente incorporate nella lingua per farlo - questo sarebbe qualcosa che hai fatto usando la lingua.

    
risposta data 23.05.2012 - 17:50
fonte
-2

Quello che sto facendo è mantenere la maggior parte delle stringhe in un file resources.h dove sto formattandolo come segue

#include <string>
#include <vector>

struct Class1_Res
{
   const std::wstring string1 = std::wstring(L"string 1");
      ----------------
}

struct Class2_Res
{
   const std::wstring string1 = std::wstring(L"string 1");
      ----------------
}

struct StatusGeneric_Res
{
const std::wstring MESSAGE_SUCCESS                  = std::wstring(L"Success");
const std::wstring MESSAGE_FAILURE                  = std::wstring(L"Failure");
const std::wstring MESSAGE_BAD_PARAM                = std::wstring(L"Bad Parameter");
const std::wstring MESSAGE_BAD_INPUT                = std::wstring(L"Bad Input");
const std::wstring MESSAGE_BAD_FILE                 = std::wstring(L"Bad File");
const std::wstring MESSAGE_MISSING_FILE             = std::wstring(L"Missing File");
const std::wstring MESSAGE_CONTAINER_NOITEM         = std::wstring(L"No item present");
const std::wstring MESSAGE_CONTAINER_ITEM_DUP       = std::wstring(L"Duplicate item");
const std::wstring MESSAGE_CONTAINER_EMPTY          = std::wstring(L"Empty Container");
const std::wstring MESSAGE_MEMORY_ALLOC_FAIL        = std::wstring(L"Memory Allocation Failure");
const std::wstring MESSAGE_UNIMPLEMENTED            = std::wstring(L"Not implemented");
const std::wstring MESSAGE_UNKNOWN_FAILURE          = std::wstring(L"Unknown Failure");
};

Posso quindi includere queste struct in Class1 o Class2 o dirette chiamarle come

Class1_Res().string1

Il salvataggio in wstring mi aiuta ad ottenere una stringa di stile c come e quando ne ho bisogno. Non c'è alcuna roba di allocazione disordinata da fare poiché utilizzo il wstring nella maggior parte dei luoghi. Ciò mi consentirà di sostituire queste stringhe in base alla definizione Hash specifica della lingua, se necessario.

StatusGeneric_Res è lì per riunire errori generici in un unico posto senza conservarlo in tutti i file. Posso associarlo con il nome della funzione per localizzare il riferimento.

Se Class1_Res diventa troppo grande, posso dividerlo in due parti eliminando le stringhe di errore

struct Class1_Err
{
    // .............
}

Tale divisione mi aiuta a mantenere tutte le stringhe in un unico posto ea volte le utilizzo in più punti quando dico che Class1 è chiamato da qualche parte e ho bisogno di stampare un errore relativo ad esso. Il costo complessivo di mantenere i dati in const wstring o const char [] non dovrebbe essere troppo diverso sapendo quanto STL sia ossessionato dall'efficienza.

    
risposta data 12.03.2015 - 16:35
fonte

Leggi altre domande sui tag