04 Nov, 2007, Guest wrote in the 1st comment:
Votes: 0
Has anyone created a library or snippet anywhere that can produce printf() style functions for C++ STL strings? I know about the iomanip include, but that's pretty painful to try and use on a large scale.

If you're not sure what I'm asking, here's an example:

void print_string( char_data *ch, std::string argument )
{
printf( "You entered %s as an argument.\r\n", argument );
}


If there's a C++ equivalent of this, or someone knows how to make one, I'd be very happy to see it.
04 Nov, 2007, Jindrak wrote in the 2nd comment:
Votes: 0
1. void print_string( char_data *ch, std::string argument )
2. {
3. printf( "You entered %s as an argument.\r\n", argument.c_str() );
4. }



EDIT:
Would have included this link but didn't think about it until right as I posted.

http://www.cplusplus.com/reference/strin...

I personally find the way www.cplusplus.com is setup very helpful in finding information about various functions.
04 Nov, 2007, Guest wrote in the 3rd comment:
Votes: 0
I should perhaps have made myself a bit clearer - I also know about the .c_str() hack. I was hoping for something a little less uglified :P
05 Nov, 2007, David Haley wrote in the 4th comment:
Votes: 0
I'm guessing that you don't want to use the << iostream operator? (Is that what you meant by iomanip?)

If all you want is simple specifiers, it's pretty easy to fake that. What I would do is change the approach; instead of using %s, %d and so forth, I would create a function that takes a format specifier with numbers. Then, break it into strings around those specifiers, e.g. "You entered %1 as an argument" becomes:
"You entered "
"%1"
" as an argument"

Then, you loop over those strings, using << to pipe them into your stream; if you ever come across a number, you grab the appropriate argument from the list of arguments that we create from the function arguments. (Need to do some vararg fanciness there I suppose.)
05 Nov, 2007, Guest wrote in the 5th comment:
Votes: 0
The iostream operator is fine as long as you don't need fancy spacing and such. But I think it would be better to be able to simulate printf() style formatting on a std::string. Partly because what I'm doing is involving a lot of std::string conversions and I'd rather maintain the existing interface with my ch->printf() function. Right now that means using a whole lotta .c_str() crap. Crap I think is ugly as sin even though it works. I imagine it must involve some amount of overhead each time it's called too.

Of course what would be even cooler ( and I've probably asked about it before ) would be to use output streaming as such:

ch << "Hello World! " << victim->name << " greets you from hell!" << endl;

But I'm guessing that would be way more complicated - and doesn't address space formatting stuff like %-15s would in a C string.

BTW, the iomanip stuff, using #include<iomanip> is far too cumbersome to be desirable. It's got way too many operation functions in it to remember how to use.
05 Nov, 2007, Davion wrote in the 6th comment:
Votes: 0
#include <iostream>
#include <printf.h>
#include <string>

int print_string (FILE *stream, const struct printf_info *info, const void *const *args)
{ const std::string *s;
char *buffer;
int len;

/* Format the output into a string. */
s = *((const std::string **) (args[0]));
len = asprintf (&buffer, "%s", s->c_str());

if (len == -1)
return -1;

/* Pad to the minimum field width and print to the stream. */
len = fprintf (stream, "%*s", (info->left ? -info->width : info->width), buffer);

/* Clean up and return. */
free (buffer);
return len;
}


int print_string_arginfo (const struct printf_info *info, size_t n, int *argtypes)
{ /* We always take exactly one argument and this is a pointer to the structure.. */
if (n > 0)
argtypes[0] = PA_POINTER;
return 1;
}

int main (void)
{ std::string *str = new std::string("Lalala");

/* Register the print function for widgets. */
register_printf_function ('W', print_string, print_string_arginfo);

/* Now print the widget. */
printf ("|%W|\n", str);
printf ("|%35W|\n", str);
printf ("|%-35W|\n", str);

return 0;
}



That's some old GNU C frickin magic there batman ;). The only problem with this though, is there's nothing like it in ISO C, so it'll only work with g++/gcc. If you're looking for crossplatform, boost has a format library.
05 Nov, 2007, Davion wrote in the 7th comment:
Votes: 0
Samson said:
Right now that means using a whole lotta .c_str() crap. Crap I think is ugly as sin even though it works. I imagine it must involve some amount of overhead each time it's called too.

At the heart of std::string is still your basic C string, I believe. So calling c_str() should just return a const pointer to it's already internal data, don't think such overhead exists.

Samson said:
Of course what would be even cooler ( and I've probably asked about it before ) would be to use output streaming as such:

ch << "Hello World! " << victim->name << " greets you from hell!" << endl;

But I'm guessing that would be way more complicated - and doesn't address space formatting stuff like %-15s would in a C string.


This isn't as hard as you'd think. Just requires overloading the << operator (for each type) for CHAR_DATA
05 Nov, 2007, David Haley wrote in the 8th comment:
Votes: 0
Davion said:
Samson said:
Right now that means using a whole lotta .c_str() crap. Crap I think is ugly as sin even though it works. I imagine it must involve some amount of overhead each time it's called too.

At the heart of std::string is still your basic C string, I believe. So calling c_str() should just return a const pointer to it's already internal data, don't think such overhead exists.

Correct. The overhead is the function call to access the pointer, and that overhead goes away if your compiler is set to optimize for inline functions.

Davion said:
This isn't as hard as you'd think. Just requires overloading the << operator (for each type) for CHAR_DATA

Indeed, it's not bad at all. But Samson is right that it doesn't let you do the spacing formatting stuff without extra work like the io stream manipulators.

Davion said:
If you're looking for crossplatform, boost has a format library.

That is a pretty nifty trick, but personally I'd really rather not use GNU extensions or the boost library unless I really had to. Boost is a big dependency to have, and the GNU extensions reduce portability (even though most people do use gcc).
05 Nov, 2007, Davion wrote in the 9th comment:
Votes: 0
DavidHaley said:
That is a pretty nifty trick, but personally I'd really rather not use GNU extensions or the boost library unless I really had to. Boost is a big dependency to have, and the GNU extensions reduce portability (even though most people do use gcc).


Ya, I'm with ya on this. Only reason I threw out boost is because some (not I) people like it. As for the GNU extension, I'm pretty sure all of Samsons MUD projects compile with either gcc or g++ so for him, this shouldn't be a problem and will extend printf the way he wants it. I guess it's not really the C++ equivalent, just an old GNU hack lol.
0.0/9