Skip to content

Instantly share code, notes, and snippets.

@fbaeuerlein
Last active February 11, 2019 19:53
Show Gist options
  • Save fbaeuerlein/f3c32f1345a6ed16c8a95a826fdc5d72 to your computer and use it in GitHub Desktop.
Save fbaeuerlein/f3c32f1345a6ed16c8a95a826fdc5d72 to your computer and use it in GitHub Desktop.
adding sprintf to exprTK for number to string conversion and formatting
#include <string>
#include <cassert>
#include <iostream>
#include "exprtk/exprtk.hpp"
/**
* @brief class containig a generic funtion for formatting numbers with snprintf
*
* Uses the igeneric_function overload for strings
*
* @tparam T parser scalar value type
* @tparam T type of conversion for snprintf
*/
template <typename T, typename ConversionType = T>
struct formatter : public exprtk::igeneric_function<T>
{
typedef typename exprtk::igeneric_function<T>::parameter_list_t
parameter_list_t;
typedef typename exprtk::igeneric_function<T> igenfunct_t;
formatter()
// function should take a string as first parameter and a scalar as a second one
: exprtk::igeneric_function<T>("ST",igenfunct_t::e_rtrn_string)
{
}
inline T operator()(std::string & result, parameter_list_t parameters)
{
typedef typename exprtk::igeneric_function<T>::generic_type generic_type;
typedef typename generic_type::scalar_view scalar_t;
typedef typename generic_type::string_view string_t;
assert(parameters.size() == 2);
// extract formatting string and value from parameters
string_t string(parameters[0]);
scalar_t scalar(parameters[1]);
char buffer[64];
if ( snprintf(buffer, sizeof(buffer), &string[0], static_cast<ConversionType>(scalar())) < 0 )
{
// AN error occurred!;
}
result = buffer; // "return" string
return T(0);
}
};
int main()
{
typedef double T;
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
// expression to build a string containing concatenated three numbers (padded with zeros)
std::string expression_string =
"return [fmt('%04i',x) + fmt('%04i',y) + fmt('%04i',z), 'abcd', 3];";
// variable definition
T x = 123, y = 89, z = 3;
formatter<T, int> fmt; // instantiate formater with conversion of T to int
symbol_table_t symbol_table;
symbol_table.add_variable("x", x);
symbol_table.add_variable("y", y);
symbol_table.add_variable("z", z);
symbol_table.add_function("fmt", fmt);
expression_t expression;
expression.register_symbol_table(symbol_table);
// parse the expression
parser_t parser;
if (!parser.compile(expression_string,expression))
{
printf("Error: %s\n", parser.error().c_str());
return -1;
}
// print results
if (expression.results().count() > 0)
{
std::cout << "Expression return count: " << expression.results().count() << std::endl;
typedef exprtk::results_context<T> results_context_t;
typedef typename results_context_t::type_store_t type_t;
typedef typename type_t::scalar_view scalar_t;
typedef typename type_t::vector_view vector_t;
typedef typename type_t::string_view string_t;
const results_context_t &results = expression.results();
for (std::size_t i = 0; i < results.count(); ++i)
{
type_t t = results[i];
// determine the right type of return values
switch (t.type)
{
case type_t::e_scalar:
{
scalar_t scalar(t);
std::cout << "Scalar result: " << i << " " << scalar() << std::endl;
}
break;
case type_t::e_vector:
break;
case type_t::e_string:
{
string_t string(t);
std::cout << "String result: " << i << " " << std::string(string.begin(), string.end()) << std::endl;
}
break;
default:
std::cout << "No result there!" << std::endl;
break;
}
}
}
std::cout << "Finished ..." << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment