• Advertisement

Archived

This topic is now archived and is closed to further replies.

Strings with undetermined size

This topic is 5494 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Basically I''m wondering if there''s anyway to output strings using vsprintf and ensure that vsprintf will never run out of space in the string to write. Is there some way I can check in advance how many extra characters vsprintf will add and then size the string accordingly?

Share this post


Link to post
Share on other sites
Advertisement
If your compiler supports the C99 standardized version of snprintf (and vsnprintf), then the answer is yes. It must be the C99 standard version of snprintf (many compilers and C runtimes supported version of snprintf before the standard), otherwise it may behave differently. Here''s an example:

  
#include <stdio.h>

#include <stdlib.h>


int main(void) {
int alpha = 123, beta = 465, gamma = 789;
char *string;
int length;

length = snprintf(NULL,0,"alpha: %d\nbeta: %d\ngamma: %d\n",alpha,beta,gamma);

string = malloc(length+1);
if(string == NULL) /* handle error */;

snprintf(string,length+1,"alpha: %d\nbeta: %d\ngamma: %d\n",alpha,beta,gamma);

printf("string is: %s",string);

free(string);

return 0;
}



Share this post


Link to post
Share on other sites
Thanks very much - this is exactly what I was looking for.

EDIT: Ok this is interesting, in what version of VC++ is _vscprintf supported in? Because it's not in my local version of MSDN and its giving an undeclared indentifer when I put it in my code. I have VC++ 6.0 Standard.

[edited by - UnknownPlayer on February 9, 2003 1:33:10 AM]

Share this post


Link to post
Share on other sites
I''m using VC++.NET, so _vscprintf may not be available in older versions of Microsoft''s C run-time. If that''s the case, you may have to write code that goes through the format specifiers and determines exactly how much space you''re going to need. I''m afraid I don''t have any examples, but I seem to recall MFC''s CString::FormatMessage doing something similar in VC++ 6.0. If you''re willing to go through the MFC source, you might be able to "leverage" it.

You could also try Null and Void''s method, using _vsnprintf. Pass NULL and 0 as the first two parameters and see if it returns the length of the string you''ll need.

Share this post


Link to post
Share on other sites
It doesn''t - evidentally I need to get VC++ 7.0 to get the C99 standard implementation of the function (I would hope). Hmm...might try stripping some code from somewhere - damnit! This is really a lot more effort then this should need.

Share this post


Link to post
Share on other sites
you can use WTL''s CString class. it works exactly like MFC''s CString but doesn''t have any dependencies.

Share this post


Link to post
Share on other sites
The VC++ 7.0 version of _snprintf doesn''t conform to C99 as Null and Void has prescribed it. Microsoft''s CRT fails an assertion if you pass NULL as the first parameter.

Can I ask what you''re trying to accomplish? Perhaps you could use a fixed length buffer or the string/stringstream classes from STL?

Share this post


Link to post
Share on other sites
I''m just trying to implement a simple CText object in my game to display HUD text. STL string classes mess with the syntax too much. I''m wondering if it''s possible to download a function which will give me C99 snprintf functionality?

Share this post


Link to post
Share on other sites
quote:
Original post by UnknownPlayer
STL string classes mess with the syntax too much.
What do you mean? Also, if you want formatted output, try Boost Format

Share this post


Link to post
Share on other sites
Well, Boost Format has a pretty similar syntax for printf. Taken from the site:

  
cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50;
// prints "writing toto, x=40.230 : 50-th try"


And no worries about breaking boundaries.

Share this post


Link to post
Share on other sites
Well I think I''ve found a reasonable solution to the problem, not neat and clean but reasonable and functional for its intended purposes. The problem is I''ve now introduced some problem which is causing my strings to get their boundaries overwritten and I''m not quite sure where - this is the full function code:


  
void CText::ChangeText(const char* Text, ...)
{
delete String;

if (Text == null)
{
String = null;
return; // Nothing to do, get out early.

}

va_list arglist; // Set up variable argument list


// Is this probably the first initialization of this object?

if (LargestTextSize == 0)
{
LargestTextSize = strlen(Text) + 1;
LargestTextSize *= 2; // Multiply by two to give us a reasonable working space

}

String = new char[LargestTextSize]; // Create a new string for us

int Count = LargestTextSize * 2; // Create a number so huge we can''t possibly not write it


va_start(arglist, Text);

// Try and output to the buffer we just created.

// If we fail, then resize it and try again.

int outval = 0; // We''ll never be trying 0 length strings

while (outval <= 0)
{
outval = _vsnprintf(String, Count, Text, arglist);

// We need this seeming redundancy for optimization

if (outval <= 0)
{
LargestTextSize *= 2; // Double the buffer size

Count *= 2; // Needs to increase as well

delete String; // Delete the string we had

String = new char[LargestTextSize]; // Create one to the new size

}

if (String == null)
{
return;
}
}
va_end(arglist);

// We have the string successfully stored

// Resize LargestTextSize for the next round

LargestTextSize = strlen(String) + 1;
}
[/source

Share this post


Link to post
Share on other sites

  • Advertisement