Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » C sucks. More specifically, sprintf() sucks.

Credits go to ReyBrujo for helping out!
This thread is locked; no one can reply to it. rss feed Print
 1   2 
C sucks. More specifically, sprintf() sucks.
23yrold3yrold
Member #1,134
March 2001
avatar

Okay, I'm trying to decipher why Thomas Harte's racing game crashes on me when I compile it. It took me a bit of time to track down tonight, but I finally figured it out; DynamicObjectType::SetWidth() is the culprit. Okay, it's one line of math, straight numbers .... hmmmm, twice he's accessing the h member of BITMAP for an array of *BITMAPs called AllAngles[]. Could they be NULL .....

Glory be; they are! So I hunt down the initialization code ....

bool DynamicObjectType::Open(char *namebase)
{
  char InputName[256];
  int c = 48;
  while(c--)
  {
    sprintf(InputName, "%s%02x.bmp", namebase, c);
    if(!(AllAngles[c] = load_bmp(InputName, NULL)))
      return false;
  }

  return true;
}

Now, this is innocent enough; it's loading from a folder named "art" 48 files named "carXX.bmp" (where xx is 00 to 2f in hexidecimal; 48 files). The function is getting called with the argument "car" in main(), and when I added code to check to see if it was failing, sure enough, this function returns false.

  if(!Car.Open("car"))
  {
    allegro_message("sprintf() sucks!!\n");
    return 2;
  }

I have half a mind to rip all this C-string crap out and #include <string> for the win, but I'm curious why it's not working, mostly because I'm lazy and there's probably an easy solution. That %s%02x stuff makes my brain hurt though. And no, adding an "art\\" or an "art/" directory to the string didn't help.

Complete code is here, not hard to find the relevant bits. Also no disrespect to TH for what I'm sure is a fine engine if I can ever make it run. :)

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

ReyBrujo
Moderator
January 2001
avatar

First guess, the bitmaps aren't there.
Second guess, you are in a case sensitive environment and it fails with the a-f range. Try changing 02x with 02X

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

23yrold3yrold
Member #1,134
March 2001
avatar

Bitmaps are there, case didn't matter. Shouldn't the art directory be coded in there somewhere?

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

ReyBrujo
Moderator
January 2001
avatar

Are you compiling with MSVC (in example, putting the executable files in a Debug/ or Release/ directory)? Tried moving the executable to the same directory of the bitmaps? You can try hardcoding the full path to the stuff (sprintf(InputName, "C:/test/art/%s%02x.bmp", namebase, c);) to see if that works. If so, it is a problem with the relative location. Note that directories with spaces "may" break the loading function somehow.

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

23yrold3yrold
Member #1,134
March 2001
avatar

I'm compiling in MinGW and moving the executable to the correct directory after compiling. That's why I'm asking why "art" isn't there; the other directories and loading work fine ....

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

ReyBrujo
Moderator
January 2001
avatar

For sure the program works when you move all the files inside Audio, all the bitmaps, dat and config files in the root and the generated executable inside the art directory. So, yes, even if you add art/ when loading the bitmaps, you still need to add Audio/ to the similar function where the samples are loaded.

(Edited: Geez, broke the 10k mark today... reaching you, 23! :P)

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

23yrold3yrold
Member #1,134
March 2001
avatar

I'm just running it the way TH set it up; from the main directory. I tried adding art/ and it still failed. So ... I dunno. I think it's just my C ignorance at work and if I don't see some sort of explanation by tomorrow, I'm slapping <string> in there; I don't care if it doubles the executable size. ;) My left eye is twitching enough at all the hexadecimal ...

EDIT: Okay, added more checks. art/ worked; it's just crashing somewhere else now. :) I'll get on that tomorrow.

Quote:

(Edited: Geez, broke the 10k mark today... reaching you, 23! :P)

Spammer.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

A J
Member #3,025
December 2002
avatar

1. how about some more error checking, like checking namebase's length.
and if its NULL.

2. try using sNprintf

3. are the bitmaps in the correct colour depth

4. AllAngles[c] what is the size of this array ? i hope its not [48].

[edit]
5. char InputName[256]; why 256 ? either set it to 512 or MAX_PATH.

___________________________
The more you talk, the more AJ is right. - ML

Kitty Cat
Member #2,815
October 2002
avatar

Quote:

4. AllAngles[c] what is the size of this array ? i hope its not [48].

Why?

int c = 48;
while(c--) // checks if(48)
{ // c is now 47
...

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

Evert
Member #794
November 2000
avatar

Quote:

I have half a mind to rip all this C-string crap out and #include <string> for the win, but I'm curious why it's not working

I'm curious to know why you think it'd make any difference wether you used sprintf or not...?

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

I'm curious to know why you think it'd make any difference wether you used sprintf or not...?

Quote:

That %s%02x stuff makes my brain hurt though.

It's different because I actually understand the C++ version. :)

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Paul Pridham
Member #250
April 2000
avatar

So in other words: C doesn't suck... you do. ;)

Yea, try handling errors once in a while hey?

Richard Phipps
Member #1,632
November 2001
avatar

It looks like a relative path thing to me too. It's not a C issue.

Geoman
Member #6,873
February 2006

1. One shouldn't hardcode the number of bitmaps.
2. I never mix conditionals with executional code, like "while(c--)", because I think it is hard to tell what's happening here. I am curious, does this first subtract, and then check for 0 ? In that case, the 0-th bitmap will never be read and then, it'll remain undefined.

HoHo
Member #4,534
April 2004
avatar

Quote:

I am curious, does this first subtract, and then check for 0 ?

For that you should understand the difference between c++ and ++c. In case of while (c--), first there is the check for c==0 and then c gets reduced by one (assuming c is an integer). If there would be --c then subtraction would be before the check. It is all written in language standards.

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Carrus85
Member #2,633
August 2002
avatar

Um, no, that will check to see if c is zero, then subtract.

EDIT: BEATEN >:(

Geoman
Member #6,873
February 2006

Thanks.

Arthur Kalliokoski
Second in Command
February 2005
avatar

Back in the day, I traced the asm code for a cout on a 286, after 40 minutes, my eyes watered, my head hurt, I decided not to use C++ anymore. Now, once in awhile, I find some code to do something in C++ and I try to understand it. I can't imagine why ppl would think a constructor is better than some straightforward initialization on entry, my brain recoils in horror... Oh well, to each his own.

They all watch too much MSNBC... they get ideas.

Thomas Harte
Member #33
April 2000
avatar

ahem yes, the problems of not properly checking return results even where I've code leaf functions to at least partly cope.

There is also the problem of not properly supporting multiple platforms. The code as written expects all data files to be in the same directory as the executable on Windows/Linux because here in my OS X application bundle ghetto I didn't really put a lot of thought into it. My IDE copies all the data files into the Resources part of the bundle and Allegro autimatically switches there, so I've just been stupid not thinking about the unholy mess that will create on other OSs.

Beyond that, I have no idea why manually adding folder names into the source doesn't work.

In my defence, it is only a work in progress technology demo.

Quote:

One shouldn't hardcode the number of bitmaps.

In this case it is more acceptable than usual - the bitmaps are all different views of the same object, designed to allow the display a "3d" object using sprites, as in Doom or Mario Kart 64. I know that such an idea is very old fashioned and low tech, but it fits the mood.

Incidentally, I'm still slowly working on my game that will use this engine. Having abandoned a "realistic feel" as a time consuming dead end - even though it means admitting that almost everyone else was right and I was wrong - I've been working this week on a course editor. I haven't been posting because it is SDL based. It is SDL based because I consider a resizeable window (i.e. one where the user can drag expand it to their desired proportions) to be immeasurably useful for this sort of thing. In addition the event based structure of SDL makes it much easier to do very low processing cost and low FPS tools that don't become unresponsive. The editor limits itself to 10fps if possible, waking early if an input event occurs giving it about 3% CPU usage on my quite old machine. I'm imagining a scenario where it is used simultaneously with a running copy of the game for proper driving tests.

A couple of screenshots:

{"name":"Editor1.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/6\/66d3f5734d7fbbbf63ccf6941acb081a.png","w":688,"h":746,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/6\/66d3f5734d7fbbbf63ccf6941acb081a"}Editor1.png

This is the initial screen of the editor. I've gone for an Outrun style branching track (branches as I plan them are a quite trivial engine modification), and on this screen the editor selects which route they will edit. A quite boring first screen. Selected route is saved from one session to the next so you usually don't spend too long here.

{"name":"Editor2.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/d\/adeb486c44b0cf6ba4033b3f39439020.png","w":688,"h":746,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/d\/adeb486c44b0cf6ba4033b3f39439020"}Editor2.png

The main editor screen. Most of it is obvious. A tilemap has been adopted for the road surface so that lanes and lane sizes can dynamically change, etc. I've just chopped up 23's original textures to make the tiles, which hasn't worked too badly.

The main tile map section currently allows the map to be painted and objects to be placed. Corner editing will eventually go in there too, probably just through placing and rotating arrows as markers, with an eye on the not yet implemented 3d preview in the bottom right to get the curvature you want.

The "floor tiles" and "objects" bits are just palettes for selecting things to paint onto the main screen.

At the time of capture, the user is doing a copy/paste style operation. The bit highlighted in white is the copy source, the section being highlighted in purple is where that row will be duplicated.

At the top is the elevation editor. It uses quadratic Beziers much as before but now has a much more user friendly chop operation. The blue lines at the top match the blue lines in the tile area to help with orientation.

Development has been temporarily halted (about two days now) because I made a logical flaw in my planning. Of course with a tilemap it becomes important to preserve arc length, i.e. total road surface distance. I've decided to stick with Beziers and just implement that as a hard constraint, although I considered a more physical approach that would have made the elevation graph act a bit like a piece of string. I decided that would make it too hard to maintain continuity (in the mathematical sense) using the string idea and was too busy to code today.

I expect I'll be back on an art beg within a few weeks, but I want to put together a basic playable first stage even if quite art deficient as otherwise I can't see why people should believe that things have moved on since the last big thread.

EDIT:

Quote:

Back in the day, I traced the asm code for a cout on a 286, after 40 minutes, my eyes watered, my head hurt, I decided not to use C++ anymore. Now, once in awhile, I find some code to do something in C++ and I try to understand it. I can't imagine why ppl would think a constructor is better than some straightforward initialization on entry, my brain recoils in horror... Oh well, to each his own.

With my investigations of Aqua lately, I've become persuaded that Objective-C is actually a really good language, especially as it can be mixed with C and C++ in the same source files. The conceptual idea of messages rather than functions which is implemented through runtime binding to prevent messy overhead is cool, especially as it eliminates the fragile base class problem about 1,000,000 times more neatly than COM or any other method I've seen.

As for while(n--), it's just my favoured type of loop. In the olden days it was recommended as the most efficient loop as the compare to zero and hence the branch decision is obtained "for free". That won't make any odds any more, but it is just the thing I automatically reach for now.

Billybob
Member #3,136
January 2003

That's hot TH. I was thinking about your game the other day and wanted to post asking about it. Guess you saved me the troubled ;)

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

It looks like a relative path thing to me too. It's not a C issue.

That was the thing to be determined, yup. Those funky hieroglyphics give me a headache ....

Quote:

I expect I'll be back on an art beg within a few weeks

Yeah, I had assumed my main contributions would be art. :) I'm just playing with it to get back in the swing ... I envision myself making a lot of 3D cars and rendering them from 48 angles ....

And that reminds me, I gotta make a Super Mario Kart clone engine too. Too cool to pass up for the effort. 8-)

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

Those funky hieroglyphics give me a headache ....

And this doesn't?
cout << "FOOB " << setfill('0') << setw(40) << 100 << endl;

I'll tell you this now, I will always prefer the following over that:
printf("FOOB %040i\n", 100);

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

23yrold3yrold
Member #1,134
March 2001
avatar

The first may be longwinded, but at least you can read it with minimal effort. Hell, you barely need to know C++ to understand it, while your version I gotta hit the C reference site to figure out the codes. :)

Just trolling at this point ...

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Thomas Fjellstrom
Member #476
June 2000
avatar

What? You "Know C/C++" and can't read a printf format? :o

;)

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Evert
Member #794
November 2000
avatar

Quote:

The first may be longwinded, but at least you can read it with minimal effort. Hell, you barely need to know C++ to understand it

I know C, C++ and sevarl other languages and I had to look at the printf() statement to figure out what that line of C++ code was doing.
Interesting, isn't it, how what is intuitive and easy and what is not is almost solely determined by what you're used to?

 1   2 


Go to: