Skip to main content
gamedev.net
🔒 Locked

A printing problem

Started by pichu Dec 12, 2005 at 2:16 PM 5 replies 1.3k views
Original Post
pichu
pichu
I just recently stumbled across something strange. While trying to figure out the ASCII key code for the '%' sign, I did a piece of code like this. for (int i=0;i<256;i++) DebugWrite("%d %c\n", i, i ); (DebugWrite is my own function, almost exactly like printf, except it writes to a file) From all the ASCII charts, the '%' sign is character 37, but when I looked at the 37th character, there was nothing there, I couldn't even highlight it! Any ideas?
ToohrVyk
ToohrVyk
int main( ) {  for( int i = 0; i < 50; ++i ) {    printf( "%d %c\n", i, i );  }}


The above displays 37 %, so I'd be tempted to say you have a bug in your function.
Kuro
Kuro
Maybe it's because if you use printf, you have to print "%%", because if you do just a single "%", then it thinks that's an invalid code. (Like, "%c", "%d", etc.)
pichu
pichu
It does seem that way! Unfortunately, in my code that's not the only place it has shown itself.

I do use this function to insert the charachter into the string.

void InsertInString( int loc, char ch, char *str )
{
// make room for the new charachter
for ( int i=strlen( str )+2;i>loc;i-- )
str=str[i-1];
// and put in the new charachter
str[loc]=ch;
}
Zahlman
Zahlman
That's possible, but it's also possible that you're misled into thinking something weird is happening with the % symbol because you use the DebugWrite() function to inspect the contents of the inserted-into string.

That said, the C standard library already provides a function "almost exactly like printf, except it writes to a file": fprintf. And if you think you're using C++ instead... well, you probably don't want to get me started... :)
pichu
pichu
Actually, my DebugWrite function uses fprintf (I've been using DebugWrite for 2 years, and it hasn't let me down before). But I also use a piece from DirectX, d3dFont->DrawText() to display my text, so DebugWrite is only my secondary.
And I am using DirectInput to collect my input
Another strange thing that happens is that when I press the '%' key twice, it does add the sign to the string, but it does have that non-visible charachter next to it.
And thanks for your help guys, I really do appreciate it.


void DebugWrite( char *txt, ... )
{
FILE *fp;

char text[128];

va_list va;

// open the text file for appending
if ( ( fp = fopen( "log.txt", "a" ) ) == NULL )
return;

// extract the variables from the ... and put them in the string text
va_start( va, txt);
vsprintf( text, txt, va );
va_end( va );

// write to the file
fprintf( fp, text );

// and close the file
fclose( fp );
}
ZQJ
ZQJ
That DebugWrite is one hell of a dodgy function. The reason you're way of locating the % character doesn't work is as follows:

vsprintf(text, txt, va) gives text="37 %\n"

When you then put this string into fprintf the sequence %\n produces undefined results because that is not a valid formatting sequence. This is one of the classic C security holes that people get wrong a lot. What you should have is fprintf(fp, "%s", text) instead of fprintf(fp, text), because this just writes the string to fp. Alternatively you could use fputs in this situation. In fact there is also a buffer overflow bug in this function because if the resultant string is longer than 128 characters you'll overwrite the frame pointer and possibly the return address on the stack which will almost certainly crash your program. I'm also pretty sure you don't want to be opening and closing the file every time you want to write something to it (this will be SLOW), even though perhaps you do want to call fflush() after every write in case your program crashes. In the end, you probably want (something like) this code:

static FILE *debug_fp;int InitDebugWrite(){  debug_fp = fopen("log.txt", "at");  return (debug_fp != NULL) ? 0 : -1;}void DebugWrite(const char *format, ...){  va_list ap;  if (debug_fp == NULL)    return;  va_start(ap, format);  vfprintf(debug_fp, format, ap);  va_end(ap);  fflush(debug_fp);}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.