|
This thread is locked; no one can reply to it. |
1
2
|
Help with file I/O |
gary_ramsgate
Member #8,619
May 2007
|
I'm really struggling in loading a high score table. int blank_hiscores(void) int load_hiscores(void) |
X-G
Member #856
December 2000
|
You do realize you never actually set dummy1 to anything, right? -- |
bamccaig
Member #7,536
July 2006
|
X-G said: You do realize you never actually set dummy1 to anything, right? Since he's asking us why he's outputting garbage he probably doesn't. It's an honest mistake with identifiers dummy and dummy1. gary_ramsgate said:
getline (myfile,dummy); In other words, you mistakenly loaded the score into the string object instead of the integer. I haven't done C/C++, file I/O, nor Allegro programming in a while so I couldn't say if that's the only problem... Also, use [code]mycodehere[/code] tags and use descriptive variable identifiers. dummy and dummy1 are worse than a and b. For other BBCode syntax on Allegro.cc, check out the Help section (the Help button on the Post Reply toolbar). -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Timorg
Member #2,028
March 2002
|
I use this code for my games that need a high score table, it can load and save and sort names, its doesn't deal with getting names from user, and showing the high-score table, it just manages the table itself. Even if the code isn't much use, it will stick you on the right track. http://www.timorg.net/high_score.zip If you need an example of use, I will whack something together. -Tim ____________________________________________________________________________________________ |
spellcaster
Member #1,493
September 2001
|
I wrote a small "game template" for allegro games some time ago. It also contains high score routines. You might want to take a look at it to get some ideas. Please note that the main() routine is basically a showcase of the functions. 1#include <allegro.h>
2#include <stdio.h>
3#include <stdlib.h>
4
5
6enum {
7 HI_COLOR = -3,
8 TRUE_COLOR,
9 INDEXED_COLOR
10};
11
12enum {
13 MODE_FAILED,
14 WINDOWED,
15 FULLSCREEN,
16 WINDOWED_OR_FULLSCREEN,
17 FULLSCREEN_OR_WINDOWED
18};
19
20typedef struct {
21 int w, h, bpp;
22 int windowed;
23 int preferred_bpp;
24
25 BITMAP* buffer;
26} ScreenInfo;
27
28enum { HISCORE_COUNT = 10 };
29enum { HISCORE_NAME_LENGTH = 16 };
30
31
32typedef struct {
33 int score;
34 char name[HISCORE_NAME_LENGTH];
35 char new_entry;
36} HiscoreEntry;
37
38/* We need one element more than actually used by the game */
39HiscoreEntry hiscores[HISCORE_COUNT +1];
40ScreenInfo screen_info = { 0, 0, 0, 0, 0, NULL };
41
42
43/*
44 * Sets all hiscore table entries to a given name and value.
45 * name - the name to use. If longer than HISCORE_NAME_LENGTH, the name will be truncated.
46 * score - the score
47 */
48void hiscore_init(char *name, int score) {
49 int a;
50 for (a = 0; a < HISCORE_COUNT; ++a) {
51 snprintf(hiscores[a].name, HISCORE_NAME_LENGTH, name);
52 hiscores[a].score = score;
53 hiscores[a].new_entry = 0;
54 }
55}
56
57/*
58 * Compares two hiscore entries. Used by quicksort in the hiscore_add() method
59 */
60int hiscore_compare(const void *lhs, const void *rhs) {
61 return ((HiscoreEntry*) rhs)->score - ((HiscoreEntry*) lhs)->score;
62}
63
64
65/*
66 * Adds a new score to the table. After the call to this function
67 * you can recognize the new element in the table by the state of the
68 * new_entry flag - so if you want to display the latest entry to the table
69 * differently, just check the newly added flag.
70 */
71void hiscore_add(char *name, int score) {
72 int a;
73 for (a=0; a < HISCORE_COUNT; ++a) {
74 hiscores[a].new_entry = 0;
75 }
76
77 /* the table contains one element more than HISCORE_COUNT,
78 * allowing us to add new scores easily
79 */
80 snprintf(hiscores[HISCORE_COUNT].name, HISCORE_NAME_LENGTH, name);
81 hiscores[HISCORE_COUNT].score = score;
82 hiscores[a].new_entry = 1;
83
84 qsort(hiscores, HISCORE_COUNT+1, sizeof(HiscoreEntry), hiscore_compare);
85}
86
87int hiscore_save(const char* filename) {
88 int a;
89 PACKFILE *f = pack_fopen(filename, "w");
90
91 if (f != NULL) {
92 for (a = 0; a < HISCORE_COUNT; ++a) {
93 pack_fwrite(hiscores[a].name, HISCORE_NAME_LENGTH, f);
94 pack_iputw(hiscores[a].score, f);
95 }
96 pack_fclose(f);
97
98 return TRUE;
99 }
100 return FALSE;
101}
102
103int hiscore_load(const char* filename) {
104 int a;
105 PACKFILE *f = pack_fopen(filename, "r");
106
107 if (f != NULL) {
108 for (a = 0; a < HISCORE_COUNT; ++a) {
109 pack_fread(hiscores[a].name, HISCORE_NAME_LENGTH, f);
110 hiscores[a].score = pack_igetw(f);
111 }
112 pack_fclose(f);
113
114 return TRUE;
115 }
116 return FALSE;
117}
118
119
120/*
121 * Sets a gfx mode.
122 * If you pass a literal value for the colordepth (say 16) this
123 * routine will try to set the colordepth and return a failure if
124 * this depth could not be set. If you pass a mode constant the
125 * routine will try several fitting color depths if the preferred
126 * one could not be set.
127 * If you want to force a windowed mode, pass WINDOWED as windowed parameter
128 * If you want to force a fullscreen mode, pass FULLSCREEN as windowed.
129 * If you prefer windowed, but can live with fullscreen use WINDOWE_OR_FULLSCREEN.
130 * If you prefer fullscreen, but windowed is ok as well, pass FULLSCREEN_OR_WINDOWED
131 *
132 * width - screen width
133 * height - screen height
134 * colordepth - either HI_COLOR, TRUE_COLOR, INDEXED_COLOR or the bpp
135 * value you want to use (8, 16, etc..)
136 * windowed - either WINDOWED, FULLSCREEN, WINDOWED_OR_FULLSCREEN or
137 * FULLSCREEN_OR_WINDOWED
138 *
139 * returns TRUE if the mode was set, FALSE otherwise
140 */
141int init_graphics(int width, int height, int colordepth, int windowed) {
142
143 /*
144 * Not all cards support 16 bit color, some require 15
145 * even if they are listed as "HiColor".
146 * In order to set a fitting graphics mode, some
147 * alternatives are defined.
148 * The 24 bit color mode is always tried last, since
149 * the 3 byte alignement makes it a terribly slow mode to
150 * use.
151 */
152 static int hicolor[] = { 16, 15, 32, 24, 0 };
153 static int truecolor[] = { 32, 16, 15, 24, 0 };
154 int *depths = NULL;
155 int bpp = 0;
156 int a;
157 int mode = 0;
158 int result = -1;
159
160 /*
161 * depths is the array containing the bpp values.
162 * We'll iterate over that array (if it is != NULL)
163 * below and set the corresponding mode. If the
164 * array is NULL we'll try to set the colordepth
165 * stored in bpp (if bpp != 0)
166 */
167 switch (colordepth) {
168 case HI_COLOR:
169 depths = hicolor;
170 break;
171 case TRUE_COLOR:
172 depths = truecolor;
173 break;
174 case INDEXED_COLOR:
175 bpp = 8;
176 break;
177 default:
178 bpp = colordepth;
179 }
180
181 /* Set the first mode (windows or fullscreen) to try */
182 if (windowed == WINDOWED || windowed == WINDOWED_OR_FULLSCREEN) {
183 mode = GFX_AUTODETECT_WINDOWED;
184 } else {
185 mode = GFX_AUTODETECT_FULLSCREEN;
186 }
187
188 if (depths) {
189 /* While no mode is set and we have alternative modes */
190 while (result < 0 && windowed != MODE_FAILED) {
191 a = 0;
192 while (depths[a] != 0 && result < 0) {
193 set_color_depth(depths[a]);
194 result = set_gfx_mode(mode, width, height, 0, 0);
195 if (result >= 0) {
196 bpp = depths[a];
197 }
198 ++a;
199 }
200
201 if (result < 0) {
202 if (windowed == WINDOWED_OR_FULLSCREEN && mode == GFX_AUTODETECT_WINDOWED) {
203 mode = GFX_AUTODETECT_FULLSCREEN;
204 } else if (windowed == FULLSCREEN_OR_WINDOWED && mode == GFX_AUTODETECT_FULLSCREEN) {
205 mode = GFX_AUTODETECT_WINDOWED;
206 } else {
207 windowed = MODE_FAILED;
208 }
209 }
210 }
211 } else if (bpp != 0) {
212 /* User has requested a very specific color depth */
213 set_color_depth(bpp);
214 result = set_gfx_mode(mode, width, height, 0, 0);
215
216 if (result < 0) {
217 if (windowed == WINDOWED_OR_FULLSCREEN && mode == GFX_AUTODETECT_WINDOWED) {
218 mode = GFX_AUTODETECT_FULLSCREEN;
219 } else if (windowed == FULLSCREEN_OR_WINDOWED && mode == GFX_AUTODETECT_FULLSCREEN) {
220 mode = GFX_AUTODETECT_WINDOWED;
221 } else {
222 windowed = MODE_FAILED;
223 }
224
225 /* if there is a 2nd mode we can try, try it: */
226 if (windowed !=MODE_FAILED) {
227 result = set_gfx_mode(mode, width, height, 0, 0);
228 }
229 }
230 }
231
232 /* If a mode was set, result is equal to (or greater than) 0.
233 */
234 if (result >= 0) {
235
236 /* If this method was called to change the graphics mode,
237 * we'll try to maintain the contents of the screen
238 */
239 if (screen_info.w == width && screen_info.h == height) {
240 /* screensize was not changed, blit doublebuffer to screen */
241 blit(screen_info.buffer, screen, 0, 0, 0, 0, width, height);
242
243 if (screen_info.bpp != bpp) {
244 /* colordepth has changed, we need a new buffer.
245 * If we destroy the buffer here and set it to NULL,
246 * a new bufer will be created below
247 */
248 destroy_bitmap(screen_info.buffer);
249 screen_info.buffer = NULL;
250 }
251 }
252 screen_info.w = width;
253 screen_info.h = height;
254 screen_info.bpp = bpp;
255 screen_info.preferred_bpp = colordepth;
256 screen_info.windowed = (mode == GFX_AUTODETECT_WINDOWED);
257
258 /* create a doublebuffer if needed */
259 if (screen_info.buffer == NULL) {
260 screen_info.buffer = create_bitmap(width, height);
261 }
262
263 return TRUE;
264 } else {
265 return FALSE;
266 }
267}
268
269/*
270 * Allows you to toggle the fullscreen / windowed aspect of your game.
271 * windowed - set to TRUE if you want to switch to windowed mode,
272 * set to FALSE if you want to switch to fullscreen mode.
273 *
274 * returns TRUE if the switch worked, FALSE otherwise
275 */
276int set_window_mode(int windowed) {
277 if (screen_info.windowed != windowed) {
278 /* if your game uses video BITMAPs make sure to release them here,
279 * and recreate them after the call to init_graphics, kinda like this:
280 *
281 * int result = 0;
282 * unload_all_video_bitmaps();
283 * result = init_graphics(screen_info.w, screen_info.h, screen_info.preferred_bpp, windowed ? WINDOWED : FULLSCREEN);
284 * load_all_video_bitmaps();
285 * return result;
286 */
287 return init_graphics(screen_info.w, screen_info.h, screen_info.preferred_bpp, windowed ? WINDOWED : FULLSCREEN);
288 }
289 return TRUE;
290}
291
292
293void update_screen() {
294 blit(screen_info.buffer, screen, 0, 0, 0, 0, screen_info.w, screen_info.h);
295}
296
297
298int main(int argc, char* argv) {
299 int lastkey = 0;
300 int a;
301
302 FONT *colorFont;
303
304 allegro_init();
305 if (init_graphics(800, 600, HI_COLOR, WINDOWED_OR_FULLSCREEN)) {
306 install_keyboard();
307
308 text_mode(-1);
309
310 clear_keybuf();
311 clear(screen_info.buffer);
312 textprintf(screen_info.buffer, font, 10, 10, makecol(255,255,255), "%ix%ix%i", screen_info.w, screen_info.h, screen_info.bpp);
313
314 update_screen();
315
316 while (!key[KEY_ESC]) {
317
318 if (key[KEY_W] && lastkey != KEY_W) {
319 lastkey = KEY_W;
320 set_window_mode(TRUE);
321 } else if (key[KEY_F] && lastkey != KEY_F) {
322 lastkey = KEY_F;
323 set_window_mode(FALSE);
324 } else {
325 lastkey = 0;
326 }
327
328 rest(1);
329 }
330 }
331
332 hiscore_init("This string is way too long. Way too long", 10);
333 hiscore_add("foo", 20);
334 hiscore_add("bar", 30);
335 hiscore_add("baz", 15);
336 for (a=0; a < HISCORE_COUNT; ++a) {
337 printf("%2i %16s %i\n", (a+1), hiscores[a].name, hiscores[a].score);
338 }
339 hiscore_save("hiscores.bin");
340 hiscore_load("hiscores.bin");
341 for (a=0; a < HISCORE_COUNT; ++a) {
342 printf("%2i %16s %i\n", (a+1), hiscores[a].name, hiscores[a].score);
343 }
344}
345END_OF_MAIN()
-- |
gary_ramsgate
Member #8,619
May 2007
|
Many thanks for the code. |
ImLeftFooted
Member #3,935
October 2003
|
Thats a clever trick of using enums for named constants. |
X-G
Member #856
December 2000
|
Quote: Since he's asking us why he's outputting garbage he probably doesn't. It's a rhetorical device, you dimwit. -- |
CGamesPlay
Member #2,559
July 2002
|
Quote: Thats a clever trick of using enums for named constants. It's pretty standard for C++. It allows you to put constants in a namespace. -- Ryan Patterson - <http://cgamesplay.com/> |
spellcaster
Member #1,493
September 2001
|
Quote:
> Thats a clever trick of using enums for named constants. It's also pretty standard for C -- |
GullRaDriel
Member #3,861
September 2003
|
It was / is pretty standard for C before even C++ exists "Code is like shit - it only smells if it is not yours" |
CGamesPlay
Member #2,559
July 2002
|
Hmm, interesting. Why doesn't the grabber emit that sort of header then? -- Ryan Patterson - <http://cgamesplay.com/> |
GullRaDriel
Member #3,861
September 2003
|
Heh, because grabber is a secret build from allegro big 5 ;-) "Code is like shit - it only smells if it is not yours" |
spellcaster
Member #1,493
September 2001
|
Sometimes using the preprocessor can be the better option. Esp. if you use some of the more powerful features of the pp. Another point is that using the PP is IMO the better solution for the grabber headers. You're not working with actual constants. You are actually accessing an index. You just prefer to give that index a speaking name. So the mapping is value -> name. In the case above the mapping is vice versa. I have name and map it to a value. -- |
bamccaig
Member #7,536
July 2006
|
spellcaster said:
enum { HI_COLOR = -3, TRUE_COLOR, INDEXED_COLOR };
I'm not sure I understand the point of using enums instead of the preprocessor. It would help if I understood namespaces... And if you're not defining a namespace, spellcaster, wouldn't it be better to use the preprocessor? X-G said: It's a rhetorical device, you dimwit. X_G.PostCount+=2; -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
CGamesPlay
Member #2,559
July 2002
|
Quote: And if you're not defining a namespace, spellcaster, wouldn't it be better to use the preprocessor? It's never better to use the preprocessor. enum { NamedConstant = 2 }; void foo() { int NamedConstant = 3; NamedConstant = 4; } Obviously, this is an obvious example, since no one would create a variable named NamedConstant. However, this is totally valid code that compiles. But, had you used the preprocessor, you get this error message: test.cpp: In function 'void foo()': test.cpp:4: error: expected unqualified-id before numeric constant test.cpp:5: error: invalid lvalue in assignment Quite cryptic. For a more likely example, try this on for size: This sort of thing happens all the time. -- Ryan Patterson - <http://cgamesplay.com/> |
bamccaig
Member #7,536
July 2006
|
Name collision is just a fact of programming though. I don't think that's a valid flaw in #define'ing constants. I was told that by #define'ing your global constants you save memory (even though it wouldn't be much). Besides, considering how quickly the problem was detected in those threads returned by the search I would say that it's relatively easy to track down. You also probably don't want a local variable named the same as your constant to avoid logical errors (perhaps breaking somebody else's code) so I would still lean towards the preprocessor when possible. It's also easy to come up with a naming convention to separate preprocessor definitions from other entities. /* * For example, and this is not to be taken as real code... */ #define NAMED_CONSTANT 4 class NamedConstant { private: int mintNamedConstant; }; Anybody else have an opinion? -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
CGamesPlay
Member #2,559
July 2002
|
Quote: Name collision is just a fact of programming though. Sure, if you code like that. Using constants inside specific scopes completely eliminates the collision. You can select either constant: #include <iostream> using namespace std; enum { Bitmap = 3 }; int main(int argc, char* argv[]) { int Bitmap; Bitmap = ::Bitmap; cout << "Bitmap constant is " << ::Bitmap << endl; cout << "Bitmap variable is " << Bitmap << endl; return 0; }
Quote: I was told that by #define'ing your global constants you save memory (even though it wouldn't be much). Well, that's wrong, as the compiler will inline the constants anyways. [append] The problem is that you're using the preprocessor to do things the compiler should be doing. It's like running a sed script on your code before you compile it. The sed script doesn't know whether or not you mean the variable or the constant, it just does string replacement. The compiler can accomplish the same task, but more intelligently. Libraries that use the preprocessor have to prefix all of their symbols to avoid collision. Instead of doing that, use namespaces. Compare: // GfxLib.h #define MODE_SOLID 0x01 That uses the preprocessor to represent a flag passed to a function that draws shapes in a graphics library. // ColDetek.h #define MODE_SOLID 0x03 That uses the preprocessor to represent a flag passed to a function in a physics library. Now one can't use both libraries in the same file. To fix the problem, both libraries need to be made compliant. // GfxLib.h #define GFXLIB_MODE_SOLID 0x01
// ColDetek.h #define COLDETEK_MODE_SOLID 0x03 Now to use them we have to use GFXLIB_MODE_SOLID or COLDETEK_MODE_SOLID. How annoying. Instead, use enumerations and namespaces: // GfxLib.h namespace GfxLib { enum { MODE_SOLID = 1 }; } // ColDetek.h namespace ColDetek { enum { MODE_SOLID = 3 }; } Now, when you want to use ColDetek's constants, use ColDetek::MODE_SOLID. How does that help? using statements! void foo() { using namespace ColDetek; ColDetekFunction(data, MODE_SOLID); // Lots of other calls to ColDetek's functions // But we can still use GfxLib in this function GfxLib::DrawPoly(points, GfxLib::MODE_SOLID); } Namespace collisions are not a product of programming, they are a product of poor programming. -- Ryan Patterson - <http://cgamesplay.com/> |
bamccaig
Member #7,536
July 2006
|
Thanks. That's all very interesting. CGamesPlay said: Well, that's wrong, as the compiler will inline the constants anyways. What do you mean by inline the constants? And if there's no difference in memory usage between using the preprocessor instruction (#define) versus an enum or const definition then why do large commercial games #define constants? CGamesPlay said: // But we can still use GfxLib in this function However, wouldn't using the prefix make it more clear which namespace each constant belongs to? void foo() { ColDetekFunction(data, ColDetek::MODE_SOLID); // Lots of other calls to ColDetek's functions GfxLib::DrawPoly(points, GfxLib::MODE_SOLID); }
-- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
CGamesPlay
Member #2,559
July 2002
|
Quote: I'm curious how the std namespace is defined if it contains entities from different header files... Or am I misunderstanding the structure of the std namespace? Does anybody know where it's defined? Namespaces don't have to be declared all at once. This code is valid: namespace foo { enum { constant }; } namespace foo { void func(); }
Quote: Also, is there a way to switch between namespaces in the same scope (for example, use one, stop using it, use another one)? No, because you can't "stop" using a namespace. Quote: However, wouldn't using the prefix make it more clear which namespace each constant belongs to? Well, yeah, but it can also make it more convoluted. It gets to a point where you know you are passing ColDetek::MODE_SOLID to ColDetek::ColDetekFunction. [edit] -- Ryan Patterson - <http://cgamesplay.com/> |
bamccaig
Member #7,536
July 2006
|
CGamesPlay said: Namespaces don't have to be declared all at once.
CGamesPlay said: No, because you can't "stop" using a namespace. Good to know. Thanks! I deleted the question in his quote convinced that it was a stupid qustion... Apparently it wasn't... :-/ CGamesPlay said: Well, yeah, but it can also make it more convoluted. It gets to a point where you know you are passing ColDetek::MODE_SOLID to ColDetek::ColDetekFunction. True... -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
spellcaster
Member #1,493
September 2001
|
Quote: I'm not sure I understand the point of using enums instead of the preprocessor. It would help if I understood namespaces... And if you're not defining a namespace, spellcaster, wouldn't it be better to use the preprocessor? Define "better". Main reason I use enums is that the enum is known to the compiler, so it'll appear in compile errors, during debug sessions, etc. Besides that, it's mainly a question of style and lazyness. If I have a couple of constants with increasing numbers, using an enum is simply less typing. And adding a new constant in the middle is way less work. You can also do something like this: enum { MODE_1 = 0 MODE_2, MODE_3, MODE_GUARD }; int countModes = MODE_GUARD - MODE_1; // or for (int a=MODE_1; a < MODE_GUARD; ++a) { } That's nothing fancy. It's just practical and provides a bit of comfort. Oh, have I mentioned that it saves a couple of keystrokes as well? This will not make a big difference, but if you start using it, and you need to insert that extra constant in the middle, you'll just smile, do it and smile even broader. Guess that's why I'm using it. I like that warm feeling -- |
CGamesPlay
Member #2,559
July 2002
|
Quote: What do you mean by inline the constants? const int NamedConstant = 3; enum { NamedConstant = 3 }; Both of those create constant values. When you compile the program, the compiler doesn't actually add that value to the code as a variable. Instead, wherever you use the variable, the compiler places the literal value there directly. Quote: And if there's no difference in memory usage between using the preprocessor instruction (#define) versus an enum or const definition then why do large commercial games #define constants? In C there isn't much advantage to using the enums since you can't select the scoping you want anyways (in other words the function scope will always override the named constant and you can't change that behavior), and #defines are easier to type, I suppose (there might be an argument for "easier to read" also). The tradition probably carried over into C++, before people popularly realized the concrete benefits of enumerations. -- Ryan Patterson - <http://cgamesplay.com/> |
Jonatan Hedborg
Member #4,886
July 2004
|
In C++, this is also quite nice: enum WHATEVER { ENUM1, ENUM2, ENUM3 } void doSomething(WHATEVER w) { ... }
|
Kitty Cat
Member #2,815
October 2002
|
typedef enum WHATEVER { ENUM1, ENUM2, ENUM3 } WHATEVER; void doSomething(WHATEVER w) { ... } Works in C, too. Another thing I like about enums:
will generate a warning in GCC that 'VAL3' isn't handled in the switch statement. -- |
|
1
2
|