MudBytes
» MUDBytes Community » Coding Discussions » Coding and Design » C++ equivalent of printf() st...
Pages: << prev 1 next >>
C++ equivalent of printf() style functions
Guest
Unregistered


Go to the bottom of the page Go to the top of the page
#1 id:6653 Posted Nov 4, 2007, 12:30 pm

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:

Code (text):
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.

Last edited Nov 4, 2007, 12:31 pm by Samson
Jindrak
Apprentice






Group: Members
Posts: 11
Joined: May 18, 2006

Go to the bottom of the page Go to the top of the page
#2 id:6656 Posted Nov 4, 2007, 2:24 pm

Code (text):
  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/string/string/

I personally find the way www.cplusplus.com is setup very helpful in finding information about various functions.
.........................
Jindrak can be found at The Carnival of Carnage:

  telnet://www.godwars.net:4123
  Carnival of Carnage Web Site
  Friend Us on Facebook
  Find Us on Twitter

Last edited Nov 4, 2007, 2:28 pm by Jindrak
Guest
Unregistered


Go to the bottom of the page Go to the top of the page
#3 id:6657 Posted Nov 4, 2007, 2:28 pm

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

David Haley
Wizard






Group: Members
Posts: 7,841
Joined: Jun 30, 2007

Go to the bottom of the page Go to the top of the page
#4 id:6658 Posted Nov 4, 2007, 6:41 pm

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.)
.........................
-- d.c.h --
BabbleMUD Project (custom codebase)
Legends of the Darkstone (head coder)
http://david.the-haleys.org
.........................

Guest
Unregistered


Go to the bottom of the page Go to the top of the page
#5 id:6659 Posted Nov 4, 2007, 6:54 pm

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.

Davion
Idle Hand






Group: Administrators
Posts: 1,787
Joined: May 14, 2006

Go to the bottom of the page Go to the top of the page
#6 id:6660 Posted Nov 4, 2007, 6:55 pm

Code (text):
#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.
.........................
http://mudbytes.net/mudbytessignature-davion2.png

Last edited Nov 4, 2007, 6:57 pm by Davion
Davion
Idle Hand






Group: Administrators
Posts: 1,787
Joined: May 14, 2006

Go to the bottom of the page Go to the top of the page
#7 id:6662 Posted Nov 4, 2007, 7:02 pm

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
.........................
http://mudbytes.net/mudbytessignature-davion2.png

David Haley
Wizard






Group: Members
Posts: 7,841
Joined: Jun 30, 2007

Go to the bottom of the page Go to the top of the page
#8 id:6663 Posted Nov 4, 2007, 7:22 pm


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).
.........................
-- d.c.h --
BabbleMUD Project (custom codebase)
Legends of the Darkstone (head coder)
http://david.the-haleys.org
.........................

Davion
Idle Hand






Group: Administrators
Posts: 1,787
Joined: May 14, 2006

Go to the bottom of the page Go to the top of the page
#9 id:6664 Posted Nov 4, 2007, 7:47 pm

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.
.........................
http://mudbytes.net/mudbytessignature-davion2.png

Last edited Nov 4, 2007, 7:49 pm by Davion
Pages:<< prev 1 next >>