Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In my current code project, there is an awful lot of constant strings I use to print out error messages.

Hardcoding such strings is generally considered to be bad practice. Now I'm searching for a "clean way" to include these strings in my program. Therefore I've written a "constants.h" and "constants.cpp" which looks something like

#ifndef CONSTANTS_H_
#define CONSTANTS_H_

extern std::string error_message_1;

#endif

and the 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 ;-)"

So you might see the problem I have with this: due to a lot of error messages, the variable name itself is fairly long. The error message is even longer, so it crashes the standard 80 characters in one line of code.

Obviously I want my code nice and clean. I don't like going far beyond the 80 charactes per line of code. I don't like somthing like the following either:

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

Storing the strings in an external file which one would read in at the start of the program does not seem to be optimal too since the compiler cannot warn about missing strings. Basically this would be a mess to maintain.

So what do you do about it? Is there such a nice thing as "Resources", which I know of Android (or is it Java in general?) development?

Note: Please do NOT tell me that my naming convention is bad. The above is just an example. It's not what it looks like ;-)

share|improve this question
    
Why aren't those objects marked const? –  Klaim May 20 '12 at 11:09
    
because it seems to be not relevant to this question. Or does this change anything about code style? –  stefan May 20 '12 at 11:11
    
Yes, those are not constants until you mark them const. No optimizations can happen here. That's not related to the question though, it's just that you talk about constant, but they are not (in a C++ way). –  Klaim May 20 '12 at 11:19
    
I think you might also have a problem if you access those string constants before the corresponding module has been initialized. I was using a similar technique and when I was reading the strings from another .cpp file they were all empty because the code using the constants was executed before the object module in which they were defined was initialized. At least, this is my explanation for that. –  Giorgio May 20 '12 at 11:27
    
well then it seems that I will switch to const char[], but that still leaves an unbearable mess of code. I just want to have my beloved compiler warnings and errors in combination with nice string storage.. –  stefan May 20 '12 at 11:39

3 Answers 3

up vote 1 down vote accepted

Hardcoding such strings is generally considered to be bad practice.

Not sure I agree with that.

String literals are easy to read rather than the name of a string. If you want the same text for multiple locations then encapsulate the text into a function and call the single function to display the message.

If you want to centralize the text into a single file. Then what you are looking for is: strings as resources not manually moving all your string literals to string variables.

Checkout the following packages (normally used in localization but will work here).

* gettext

Basically what this package does is allow you to leave the 'English' version of the message in the code. But it will use the 'English' text as a key into a resource table to get the corrct version of the string for a particular local.

So code that looked like this:

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.."));

You do not need to go through the hassel of extracting all your constant strings into another package.

See here for full details. http://www.gnu.org/software/gettext/

Personally I use the above in combination with boost format libraries for localization.

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."
share|improve this answer

Hardcoding such strings is generally considered to be bad practice

Do you realize that having a file that contains literals is still hardcoding? It seems you're confusing hardcoding with magic numbers. Strings, in general, aren't magical and so you don't need to give them a name. Moving them to a constant is only necessary to avoid duplication. If you're only using a string once (as in the case of most error messages) then it's pointless to move them into another file, unless for some reason you're doing it as compile-time configure file.

If it's crucial for the user to be able to change the error messages then move them to a configuration file (not a .hpp).

If you need it for translation then use something like gettext which allows you to provide translation files and still keep your source clean.

Also, don't use std::string for string constant expressions - use const char[] instead.

share|improve this answer
    
Yes, I do realize it's not really avoiding "hardcoding", but I don't see a cleaner way to still get compiler warnings if a string is missing. Some messages are present in multiple cpp-files, so storing them elswhere seems to be a good idea. Why are you suggesting the use of const char[]? Why should this be better? –  stefan May 20 '12 at 11:25
2  
Maybe because const char is initialized at compile time while std::string is initialized when the containing module is loaded. Then you might have an error if modules are not loaded in the order you expect. At least this is what I suspect can explain some bugs I had lately. If someone can comment on this theory I would be glad to learn more. –  Giorgio May 20 '12 at 11:31
2  
@stefan const char is more efficient. std::string has quite a bit of overhead and requires dynamic initialization. It's not a huge issue, but I still recommend using const char[] if possible. –  Pubby May 20 '12 at 11:33
    
@Pubby: I recently had the problem that I accessed some const std::string variables from a different .cpp file and they were "" (probably not initialized yet). So I would say that using const char[] is definitely better because it avoids this kind of problems too. –  Giorgio May 20 '12 at 11:37
1  
-1 for the last paragraph. The std::string class does NOT add a bunch of extra overhead when used in this manner, has a well defined and determined end that is a pre-calculated aspect of the instance's state (unlike C strings), retains consistency by not using one API for some strings and another for others,...etc...I could go on and on. This is really bad advice in an otherwise decent answer. –  Crazy Eddie May 20 '12 at 16:51

Hardcoding strings is fine as long as the values never need to change. I have seen them stored as static consts and referred to be an associated enum many times.

You could wrap it in a class if you wanted to make the interface easier.

However, there are not really things built into the language to do this - this would be something you did using the language.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.