带参数调用函数从字符串中提取 [英] Call function with parameters extracted from string

查看:307
本文介绍了带参数调用函数从字符串中提取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在看下面的问题:

我得到的格式如下字符串:

I get strings that are formatted like this:

functionname_parameter1_parameter2_parameter3
otherfunctionname_parameter1_parameter2
.
.
.

和我想调用该函数具有给定参数。
所以我们可以说我有一个功能测试:

and i would like to call the function with the given parameters. So let's say i have a function test:

void test(int x, float y, std::string z) {}

和我得到的消息:

test_5_2.0_abc

然后我想功能测试像这样被自动调用:

then i would like the function test to be automatically invoked like this:

test(5, 2.0, "abc");

你对如何用C实现这一点任何提示++?

Do you have any hints on how to accomplish this in C++?

推荐答案

更新:更新 stream_function 修复参数评估顺序问题@Nawaz在评论中提到,并且也去掉了的std ::功能以提高效率。 <击>注意,评价阶修复仅适用于铛,因为GCC不遵循标准此处的GCC的一个例子,具有手动顺序执行,可以发现的here

Update: Updated stream_function to fix the argument-evaluation-order problem @Nawaz mentioned in the comments, and also removed the std::function for improved efficiency. Note that the evaluation-order fix only works for Clang, as GCC doesn't follow the standard here. An example for GCC, with manual order-enforcement, can be found here.

这通常不是那么容易实现。我写了周围的std ::功能有点包装类一旦从的std :: istream的提取参数。下面是使用一个例子C ++ 11:

This is generally not that easy to accomplish. I wrote a little wrapper class around std::function once that extracts the arguments from a std::istream. Here's an example using C++11:

#include <map>
#include <string>
#include <iostream>
#include <sstream>
#include <functional>
#include <stdexcept>
#include <type_traits>

// for proper evaluation of the stream extraction to the arguments
template<class R>
struct invoker{
  R result;
  template<class F, class... Args>
  invoker(F&& f, Args&&... args)
    : result(f(std::forward<Args>(args)...)) {}
};

template<>
struct invoker<void>{
  template<class F, class... Args>
  invoker(F&& f, Args&&... args)
  { f(std::forward<Args>(args)...); }
};

template<class F, class Sig>
struct stream_function_;

template<class F, class R, class... Args>
struct stream_function_<F, R(Args...)>{
  stream_function_(F f)
    : _f(f) {}

  void operator()(std::istream& args, std::string* out_opt) const{
    call(args, out_opt, std::is_void<R>());
  }

private:  
  template<class T>
  static T get(std::istream& args){
    T t; // must be default constructible
    if(!(args >> t)){
      args.clear();
      throw std::invalid_argument("invalid argument to stream_function");
    }
    return t;
  }

  // void return
  void call(std::istream& args, std::string*, std::true_type) const{
    invoker<void>{_f, get<Args>(args)...};
  }

  // non-void return
  void call(std::istream& args, std::string* out_opt, std::false_type) const{
    if(!out_opt) // no return wanted, redirect
      return call(args, nullptr, std::true_type());

    std::stringstream conv;
    if(!(conv << invoker<R>{_f, get<Args>(args)...}.result))
      throw std::runtime_error("bad return in stream_function");
    *out_opt = conv.str();
  }

  F _f;
};

template<class Sig, class F>
stream_function_<F, Sig> stream_function(F f){ return {f}; }

typedef std::function<void(std::istream&, std::string*)> func_type;
typedef std::map<std::string, func_type> dict_type;

void print(){
  std::cout << "print()\n";
}

int add(int a, int b){
  return a + b;
}

int sub(int a, int b){
  return a - b;
}

int main(){
  dict_type func_dict;
  func_dict["print"] = stream_function<void()>(print);
  func_dict["add"] = stream_function<int(int,int)>(add);
  func_dict["sub"] = stream_function<int(int,int)>(sub);

  for(;;){
    std::cout << "Which function should be called?\n";
    std::string tmp;
    std::cin >> tmp;
    auto it = func_dict.find(tmp);
    if(it == func_dict.end()){
      std::cout << "Invalid function '" << tmp << "'\n";
      continue;
    }
    tmp.clear();
    try{
      it->second(std::cin, &tmp);
    }catch(std::exception const& e){
      std::cout << "Error: '" << e.what() << "'\n";
      std::cin.ignore();
      continue;
    }
    std::cout << "Result: " << (tmp.empty()? "none" : tmp) << '\n';
  }
}

锵3.3下的编译和按预期工作(小活生生的例子)。

Which function should be called?
a
Invalid function 'a'
Which function should be called?
add
2
d
Error: 'invalid argument to stream_function'
Which function should be called?
add
2
3
Result: 5
Which function should be called?
add 2 6
Result: 8
Which function should be called?
add 2   
6
Result: 8
Which function should be called?
sub 8 2
Result: 6

这很有趣,又劈了一起上课,希望你喜欢。请注意,您需要修改code稍微为您的示例工作,因为C ++输入输出流有空格分隔符为,所以你需要用空格替换所有下划线在您的邮件。应该很容易做到,虽然,在这之后仅仅建造一个的std :: istringstream 从消息:

std::istringstream input(message_without_underscores);
// call and pass 'input'

这篇关于带参数调用函数从字符串中提取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆