Re: NEWBIE: Code, C question. [Part 2]

From: Trey T. Morita (
Date: 05/13/96

On Mon, 13 May 1996, Fionn Colvin wrote:

> Hi all,
>        Ok, I changed my percent line to:
> percent = (100 * current) / total
> ass suggested by Jeremy. However now when I do a score, again with str: 17
> dex: 25 and con: 12 I get
> str: below average  dex: below average  con: below average.
> Con should be below average, but dex should be supreme and str good. Any 
> ideas?
> char *see_good(int current, int total)
> {
>   int percent;
>   static char word[256];
This is your problem. This allocates 256 bytes at address TOTALLY_BOGUS . .

>   sprintf(buf, "%s Str: %s/%d		      Dex: %s		   Con: %s\r\n",
>           buf, see_good(GET_STR(ch), 25), GET_ADD(ch), see_good(GET_DEX(ch), 25), see_good(GET_CON(ch), 25));
When you call see_good to get the strength string, it puts the string 
"good" in address TOTALLY_BOGUS and returns a (char *) to TOTALLY_BOGUS.
The dex call for see_good puts the string "supreme" in the same address
TOTALLY_BOGUS, and returns the same address, TOTALLY_BOGUS. 
Con call: puts the string "below average" into the address TOTALLY_BOGUS, and
returns that address. So you see, the return value from each call to 
see_good is the address TOTALLY_BOGUS, and when the program finishes 
processing the arguments to sprintf, it says, "Gee, now I have all the 
strings I need, now, I parse the 2nd arg . . . ok, what goes in %s? buf! 
Ok, now what goes in this %s? TOTALLY_BOGUS, which is . . "below 
average". OK, there's that %d, and then this %s, which is TOTALLY_BOGUS, 
"below average", and the last %s is . . TOTALLY_BOGUS, "below average"."
Nice run-on sentence there, oh well, I hope you catch my drift. Simply 
removing the static keyword will NOT fix your problem, it will leave you 
with a pointer to deallocated memory, which will probably segfault.

You might be able to save yourself some processor cycles and stack space 
by just using a macro for this . . something like 
#define PCT_WORD(value, max) ((((value*100)/max) >= 100) ? "supreme" : 
(((value*100)/max) >= 90) ? "very good" : ...etc...etc...  ))

You'd have to have a good grasp of the (expr) ? (blah) : (bleh) operator, 
though. I guess it would help if you made the calculation a macro too . .

#define PCT(value, max) ((value*100)/max)

#define PCT_WORD(value, max) ((PCT(value, max) >= 100) ? "supreme" :
((PCT(value, max) >= 90) ? "very good" : blehblebhleh ))

Dunno, looks messy as hell . . . would work though, if you could keep 
your parentheses straight through all that. If you try to macro-fy it, be 
careful about carriage returns in macros, my gcc doesn't like that, use \ 
and then a carriage return to go to a new line in a macro.

Hmm, maybe you could even macro-fy it some more . .

#define PCT(value, max) ((value*100)/max)
#define SUPREME_PCT(value, max) (PCT(value,max) >= 100 ? 1 : 0)
#define VERY_GOOD_PCT(value, max) (PCT(value, max) >= 90 ? 1 : 0)

#define PCT_WORD(value, max) (SUPREME_PCT(value, max) ? "supreme" : \
(VERY_GOOD_PCT(value, max) ? "very good" : etcetcetc ))

Looking back, I'm tempted to just remove all this macro crap, but oh 
well. Step 1 is to get rid of that static and figure a way to catch the 
strings in DIFFERENT addresses ;)


Disclaimer - It's 5 AM, I can't sleep, and I'm writing this in pine, so 
my parentheses may not add up, or this whole line of thought may be bunk. 
Who knows?

This archive was generated by hypermail 2b30 : 12/18/00 PST