tags:

views:

186

answers:

7

I simply want to build an RPG and make it as neat as possible, I wish to define a pile of strings which I may want to edit later, so I tried something like this:

enum {MSG_INIT = "Welcome to ...", MSG_FOO = "bar"};

But I just get errors, such as that MSG_INIT is not an integer! Why must it not be a string, are that what enums are only for?

What do you think is the best way to define a pile of strings? In a struct called msg or something? I'm kinda new to all this so I'd really appreciate small examples.

A: 

enums are for groups of related numeric constants that you want to manipulate efficiently in memory.

Instead, you can just use C string constants:

char const *const MSG_INIT = "Welcome to ...";
char const *const MSG_FOO = "bar";

You can make them public fields if you choose.

E.g.

struct SomeClass
{
    static char const *const MSG_INIT;
    static char const *const MSG_FOO;
};

char const *const SomeClass::MSG_INIT = "Welcome to ...";
char const *const SomeClass::MSG_FOO = "bar";
Matthew Flaschen
I'm just thinking in larger games, they just got large files full of strings and stuff, wondering what I should implement that was like that (as i'm just learning), namespaces look a bit odd but they look like they'll work well.
John
Yeah it should work, class instead of namespace i'll get an excuse to add things to the object and work on it later, thanks.
John
or use `struct { static const string BLA; }`, then you can save the `public:` modifier
knittl
The problem with this is that the messages will be required in most project source files and you will end up with a lot of unecessary duplicate string values. If you take this approach I would use `const char * const` values for the strings, as then only pointers will be duplicated.
anon
You should use namespaces instead of a class
Nikko
Good point, @Neil.
Matthew Flaschen
+5  A: 

If you want them to be grouped use a namespace.

namespace Messages 
{
    const string INIT = "Welcome to ...";
};
dacwe
A: 

enums is short for enumerated numbers, they attach names to the integers. You can use classes to group strings.

Xolve
Prefer using namespaces over classes (unless you plan on doing metaprogramming) when it comes to grouping related items together... that's what namespaces where created for!
Matthieu M.
+1  A: 

Enums in C++ have an integral value - they are to be enumerated (so TUESDAY == MONDAY + 1), rather than being an unrelated pile.

What structure you should use to store your strings depends rather on what you are planning to do with them. If you want to use a different string based on a combination of values, putting them into a map or array may be more suitable than just defining constants.

Or you could use a separate file which you read on start-up if you want to vary the strings at runtime - depending whether the 'later' you want to edit them is before or after you compile the code.

You also might try and think more in terms of keeping data and operations together in objects rather than having a large string collection.

Pete Kirkham
A: 

enum is used to define an enumerated type.

For instance you could have

enum {CLUBS, DIAMONDS, HEARTS, SPADES};

So writing CLUBS would be the same as writing 0, DIAMONDS would be the same as 1 and so on. You can also assign specific values to each member of the enum.

That said, to build a list of strings you may want to use the corresponding C++ type, that is a list <string>.

See for instance http://www.cplusplus.com/reference/stl/list/list/ http://www.cplusplus.com/reference/string/string/

nico
No, you definitely don't want a `list`. It's the last resort container and is only useful for its iterator invalidation guarantees.
Matthieu M.
@Matthieu M.: so a `list <string>` is not useful to store a list of strings?
nico
It depends on the operations you wish to do on it. If you don't know which container to choose, pick `deque`, if you need uniqueness, use `set` or `unordered_set`, if you need C-Compatibility, use `vector`. The only interest of `list` is the guarantee that insertion and removal will not invalidate references to elements already present.
Matthieu M.
@Matthieu M.: OK thanks.
nico
+14  A: 

Many RPGs would store the messages not in a C++ source file but in a text file, something like this:

1, Welcome...
2, The $obj cannot be moved.
3, Score is %d

These are loaded at run-time, rather than being compiled at compile time, and then accessed by their numeric key, the advantage being that you can change messages without having to recompile the game engine. If you want this kind of structure, then you probably want something like a std::map<int,std::string> to hold the messages once loaded.

anon
I would store these in a resource file such as a .txt file as well, makes it possible to change without recompiling the code as well.
Cobusve
@Cobusve Makes it non portable too, unfortunately.
anon
+1, plus I'd use `std::map<std::string, std::string>` because it provides greater flexibility, IMO, if you want scripting support in the game.
Nick D
+1  A: 

If you wish to directly include the strings in the software, you could make use of the extern keyword:

// someHeader.h
namespace messages
{
  extern const std::string WelcomeOnBoard;                // declaration
}

// someHeader.cpp
#include "myproject/someHeader.h"

namespace messages
{
  const std::string WelcomeOnBoard = "Welcome on Board!"; // definition
}

The main advantage of namespaces is that you can split your messages into different files, to group them depending on some zone etc.

However, you usually don't do this like that.

Harcoding strings in the software causes issues of maintenance and internationalization.

  • You wish to remove a comma or correct a mistake ? Recompile
  • You wish to translate the game into Sweden because this girl your really want to impress is not very good in English ? Ouch... good luck.

Therefore, you usually use identifiers within the software, that are mapped to strings thanks to a framework. One famous such framework is gettext

The messages are tucked into a .po file with a nice GUI to edit them and referred to with identifiers that are themselves sentences from within the software. For example:

printf (gettext ("The amount is %0" PRId64 "\n"), number);

The GUIs include ways to search for already existing messages and also include fuzzy translations features.

Matthieu M.