Jump to content
  • Advertisement

Archived

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

enigmamwu03

Question about strings

This topic is 5676 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

Is there any possible way to turn a string into a command line. For example you take in a function name from a user and then use that string to run the function. int main() { string szFunctionName; getline(cin, szFunctionName); if(szFunctionName=="Add" || szFunctionName=="Subt") szFunctionName.c_str()(); else cout<<"That function does not exist."; } void Add() { cout<<"running"; } void Subt() { cout<<"running"; } I have tried this but it doesn''t work. Is there any other way to do this without having a long list of functions and a larger if or switch statement?

Share this post


Link to post
Share on other sites
Advertisement
One solution is a container of pair type. First is function name in terms of string. Second is function point.

Kuphryn

Share this post


Link to post
Share on other sites
yes and no

1. No, the C / C++ language has no ability to call a function by name ... period. At run time, the compiler doesn''t even know the names of your functions at all (unless you are in debug mode), much less have the abilty to look up a function in the program by it''s name.

What you are trying to do is not a runtime feature of C++, it is compile time only ... the compiler, not the program, has the knowledge to look up a function by name, and put the code to call it in the program.

2. Yes, you can do something that ACTS like what you want ... in a limited way, using something like the map idea proposed above. Your 3 easy options in C++ are - 1. to use the equilelent of a switch statement (many hard coded if blocks), where for each recognized string, you call the function. 2. to use a map like object (and array works here too) where each entry is the function pointer ... then you call that function. 3. Use functors, objects which have overridden the parenthesis oprator, and manipulate them however you want ... calling the one that matches

... for example you can write a base class, just like any other

  
class SimpleFunctor
{
public:
virtual const std::string& Name(void) const = 0;
virtual void operator()(void) = 0;
};


then you override those function in your derived class, and viola, you have objects which make dealing with function pointers very easy ...

NOTE ... IF you use virtual function, you are going to pay a run-time cost per call ... 1 extra dereference. This won''t matter 90% of the time ... but never use such a thing in the heart of a rendering loop or anything ultra performance critical. This is one of those "abstraction costs" you hear so much about ... it''s not caused by the C++ language ... it''s caused by using a C++ feature ... and can be avoided when necessary.

Share this post


Link to post
Share on other sites
Thanks for the help Xai, but i am still not quite sure on how to use that. could you post an example or email me one.
email-enigmamwu@yahoo.com
thanks again

Share this post


Link to post
Share on other sites
Hmmm, the best way I can describe a functor is that it''s an object that acts like a function (because it overloads the parenthesis operator), and since it''s an object it can have member data.

For example, if you had a no-parameter function named Bob, you''d call it like so:

Bob();

Now imagine a functor, using the definition provided by Xai - however, protend for a second that those declarations aren''t virtual. To create that functor instance and call it''s parenthesis operator, it would look like this:

SimpleFunctor sf;

sf();


It looks exactly like a function call. Well, it is, only using an operator, and sf itself isn''t a function

Now imagine that the functor class had a member variable:


  
class SimpleFunctor
{
public:
const std::string& Name(void) const { return "Fred"; }
void operator()(void) { cout << ":)" }

int mInteger;
};


And now this:


SimpleFunctor sf1;
SimpleFunctor sf2;
SimpleFunctor sf3;

sf1();
sf2();
sf3();

Each object uses the same overloaded operator, but since each instance has it''s own data, all three can operate on their different member data. It''s like using functions with static variables, only not really

You can also use these functors in standard algorithm functions, and these algorithms use different overloaded operators and stuff to do their thing. Since each instance has it''s own data, you can totally change the behavior of an overloaded operator just by feeding the class instance different data.

Share this post


Link to post
Share on other sites
Here''s an example of how something like what xai described might be done:

  
struct SimpleFunctor {
virtual const std::string name() const =0;
virtual void operator()(void*) =0;
};

class FuncA : public SimpleFunctor {
public:
const std::string name() const { return "FuncA"; }
void operator()(void* data) {
cout << "func a: " << (char*)data << endl;
}
};

class FuncB : public SimpleFunctor {
public:
const std::string name() const { return "FuncB"; }
void operator()(void*) {
cout << "func b:" << endl;
}
};

struct UserData {
char* username;
char* password;
int age;
UserData ( char* un, char* pw, int ag ) {
username = new char[strlen(un)+1];
strcpy ( username, un );
password = new char[strlen(pw)+1];
strcpy ( password, pw );
age = ag;
}
~UserData() {
delete[] username;
delete[] password;
}
};

class FuncC : public SimpleFunctor {
public:
const std::string name() const { return "FuncC"; }
void operator()(void* ud) {
UserData* user = (UserData*)ud;
cout << "username: " << user->username << endl;
cout << "password: " << user->password << endl;
cout << "age : " << user->age << endl;
delete user;
}
};

class FunctionMap {
public:
void add ( SimpleFunctor* sf ) {
funcs[sf->name()] = sf;
}
void call ( const string& funcname, void* data=0 ) {
map<string,SimpleFunctor*>::iterator it = funcs.find(funcname);
if ( it != funcs.end() ) {
((*it).second)->operator()(data);
}
}

private:
map <string,SimpleFunctor*> funcs;
};

int main() {

FunctionMap fmap;
fmap.add ( new FuncA );
fmap.add ( new FuncB );
fmap.add ( new FuncC );

fmap.call ( "FuncA", (void*)"Hello World" );
fmap.call ( "FuncB" );
fmap.call ( "FuncC", new UserData ( "neophyte", "secret", 27 ) );

return 0;
}


Apologies for a somewhat long example, but once I started I figured I might as well show how to use such a simple setup to call functions with arbitrarily complex arguments as well.

Hope this helps you out.

-Neophyte

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!