MudBytes
» MUDBytes Community » Language Discussions » C and C++ » std::string interpolation
Pages: << prev 1 next >>
std::string interpolation
JohnnyStarr
Wizard






Group: Members
Posts: 953
Joined: Feb 14, 2009

Go to the bottom of the page Go to the top of the page
#1 id:44999 Posted Apr 8, 2010, 7:54 pm

I'm taking the idea of fprint_to_char(), but was wanting to have the std::string equivalent.
This doesn't work:

Code (C++):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
// send()
// can send formatted or unformatted strings to character.
void Character::send(std::string s, ...)
{
	const char *fmt = s.c_str();
 
	char buf [MAX_STRING_LENGTH];
	va_list args;
	va_start (args, fmt);
	vsprintf (buf, fmt, args);
	va_end (args);
 
	Server::instance()->sendCharacter(buf, this);	
}
 


You cant send a const (fmt) into vsprintf().
I was hoping there would be a c++ algorithm that does something similar to C's <stdarg.h>

This is just kind of a wrapper for const char* fmt right now.
If there's a quick fix you might know of, I'll gladly take it, and put this off until I'm more comfortable with std strings.

EDIT:
I'm sure the question you might have is: "Why not just use char*?"
Well, the answer is: I guess I don't really have one. I just figured it might be a good idea. I think that it will make
customization like do_score() a breeze.

Last edited Apr 8, 2010, 8:05 pm by JohnnyStarr
JohnnyStarr
Wizard






Group: Members
Posts: 953
Joined: Feb 14, 2009

Go to the bottom of the page Go to the top of the page
#2 id:45002 Posted Apr 8, 2010, 8:57 pm

I'll answer my own question:

I'm planning on keeping my send( const char* fmt, ... )
But i'm going to add Character::stream( ostringstream& stm)

So far it's allowed me to do some pretty cool stuff.
Gives it a Ruby feel:

Code (C++):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
void do_test( Character *ch, char *argument )
{
    std::ostringstream buf;
    buf << "Hi, my name is " << ch->name  << << "\r\n";
    buf << "I am level: "    << ch->level << << "\r\n";
    buf << "The first item in my inventory is " << 
        (ch->carrying ? ch->carrying->short_desc : "(nothing)") << "\r\n";
    ch->stream(buf);
}
 
// in character.cpp
void Character::stream(std::ostringstream &stm)
{
    send(stm.str().c_str());
}
 


Anyway, I know this is probably not new to anyone else, but it helps a ton.


Last edited Apr 8, 2010, 9:22 pm by JohnnyStarr
kiasyn
Wizard






Group: Administrators
Posts: 1,109
Joined: May 15, 2006

Go to the bottom of the page Go to the top of the page
#3 id:45003 Posted Apr 8, 2010, 9:24 pm

I would not name it stream, as it could conflict if you ever use the stream class?
.........................
http://www.mudbytes.net/kiasyn-sig.png

http://portal.hypernia.com/banners/hypernia_button.jpg http://www.shastaherps.org/badges/linode88.png

quixadhal
Wizard






Group: Members
Posts: 1,815
Joined: Oct 17, 2007

Go to the bottom of the page Go to the top of the page
#4 id:45006 Posted Apr 9, 2010, 12:46 am

Actually, why not just go all the way and have Character inherit ostringstream?  That way you could treat the character itself as a stream object.

Code (text):
1
2
3
ch << "This is a silly message\r\n";

.........................
http://i302.photobucket.com/albums/nn96/quixadhal/DramaBytes2.png

Kaz
Conjurer






Group: Members
Posts: 125
Joined: Oct 31, 2009

Go to the bottom of the page Go to the top of the page
#5 id:45016 Posted Apr 9, 2010, 8:29 am

Here is some compiled and tested code that you should be able to manipulate to your needs.  Personally, I just use Boost.Format.

Code (text):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <string>
#include <iostream>
#include <cstdarg>
#include <cstdio>
 
using namespace std;
 
void string_printf(string const &str, ...)
{
    va_list args;
    char buf[1024];
 
    char const *fmt = str.c_str();
 
    va_start(args, str);
    vsprintf(buf, fmt, args);
    va_end(args);
 
    cout << buf << endl;
}
 
int main()
{
    string blah = "blah %s foo %d bar %s";
    string_printf(blah, "ONE", 2, "THREE");
}
 

JohnnyStarr
Wizard






Group: Members
Posts: 953
Joined: Feb 14, 2009

Go to the bottom of the page Go to the top of the page
#6 id:45023 Posted Apr 9, 2010, 12:17 pm

@quix: That just seems wacky to me, but good to know you can do that.

I actually went a different route. I forgot about method overloading:

Code (c++):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
// can send formatted or unformatted strings to character.
void Character::send(const char *fmt, ...)
{
	// cast const to non const to accommodate const and non const arguments.
	char *fmt2 = (char*) fmt;
	char buf [MAX_STRING_LENGTH];
	va_list args;
	va_start (args, fmt2);
	vsprintf (buf, fmt2, args);
	va_end (args);
	Server::instance()->sendCharacter(buf, this);	
}
 
void Character::send(std::ostringstream &stm)
{
	send(stm.str().c_str());
}
 
void Character::send(std::string &str)
{
	send(str.c_str());
}
 


This way you can send whatever makes most sense at the time.

Kayle
Wizard






Group: Members
Posts: 1,253
Joined: Nov 27, 2006

Go to the bottom of the page Go to the top of the page
#7 id:45024 Posted Apr 9, 2010, 12:20 pm

Why would you cast a const char* to char*? That doesn't make any sense to me.
.........................
Owner/Coder -- Malevolent Whispers -- Development Phase - Not accepting players
Coder -- Star Wars: The Sith Wars -- Open Alpha - Players Welcome - Full System Re-writes Imminent.
FUSS Project Team Lead -- SmaugMuds.Org - The Smaug MUDs Community Center

I3 Contact: Kayle@SithWars                               

David Haley
Wizard






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

Go to the bottom of the page Go to the top of the page
#8 id:45026 Posted Apr 9, 2010, 12:26 pm

It doesn't make sense and is actually useless. A non-const argument will be converted to const by the compiler. (The word "conversion" is slightly misleading, because nothing is being actually changed.) So, the const version of the function is already accommodating both const and non-const arguments.

It is in fact dangerous because now you're opening the door to modifying the input by accident which is something you really don't want to do.
.........................
-- d.c.h --
BabbleMUD Project (custom codebase)
Legends of the Darkstone (head coder)
http://david.the-haleys.org
.........................

Sharmair
Sorcerer






Group: Members
Posts: 261
Joined: Nov 9, 2008

Go to the bottom of the page Go to the top of the page
#9 id:45028 Posted Apr 9, 2010, 12:40 pm

That 2nd argument to va_start should be the last required parameter in the function,
fmt in that case not fmt2.  This was also a problem with the first code that passed
the string.  Though in that case I would have not passed a string, but a reference
to a string (probably a constant reference actually).  I also have no idea why you
would even have fmt2 in that last code, or why you would cast it.

JohnnyStarr
Wizard






Group: Members
Posts: 953
Joined: Feb 14, 2009

Go to the bottom of the page Go to the top of the page
#10 id:45029 Posted Apr 9, 2010, 12:44 pm

The problem is you cant convert a string or ostringstream to non const char*.
The send routine is in fact needing to modify the input because it gives an error on vsprintf if the char* fmt is const
it will not let you modify the original text, which is kind of the point right? Don't you want to alter the input text
because it will be changed from "%s is a string, and %d is a number." to "France is a string, and 34 is a number."

I totally get that you shouldn't be doing this if you can avoid it, so what would you suggest?

David Haley
Wizard






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

Go to the bottom of the page Go to the top of the page
#11 id:45030 Posted Apr 9, 2010, 12:46 pm

No you don't want to write into your format buffer. You write into an output buffer. (But that's what you're doing. So I'm confused about why you talk of writing into the input text buffer.)
.........................
-- d.c.h --
BabbleMUD Project (custom codebase)
Legends of the Darkstone (head coder)
http://david.the-haleys.org
.........................

JohnnyStarr
Wizard






Group: Members
Posts: 953
Joined: Feb 14, 2009

Go to the bottom of the page Go to the top of the page
#12 id:45031 Posted Apr 9, 2010, 12:49 pm

Ok, nevermind i get it. I changed the cast and got rid of the fmt2 and it works
just fine. so i guess i must have missed something. I get what you mean about not altering the fmt string too.

Sharmair
Sorcerer






Group: Members
Posts: 261
Joined: Nov 9, 2008

Go to the bottom of the page Go to the top of the page
#13 id:45032 Posted Apr 9, 2010, 12:59 pm

The 2nd (format) argument to vfprintf should be declared as a const char*.  If you
are really getting an error about that, I would make sure your MUD code is not declaring
vfprintf instead of a system header (and doing it wrong).

Pages:<< prev 1 next >>

Valid XHTML 1.1! Valid CSS!