Retrieving the string result from an Exprtk expression
Asked Answered
H

2

9

Is it possible to get the returned strings from an Exprtk expression? The code below returns NaN as answer, which is to be expected. But getting the string, in this case 'One', only seems possible using a return[] statement or by using an explicit string variable. But a simple std::string expression->value_() would be a great help. Stepping through the code shows a control_block_ with a string value_ private property with the correct result. But how is it accessible?

In the code there are two strings to evaluate, but both show the identical behavior.

Thanks for any thoughts. ...

#include "exprtk.hpp"

int main()

{
   typedef exprtk::symbol_table<double> symbol_table_t;
   typedef exprtk::expression<double>   expression_t;
   typedef exprtk::parser<double>       parser_t;

   const std::string expression_string =
                     //"if (1 > 0) {'One';} else {'Two';}";
                        "if (1 > 0,'One','Two')";

   expression_t expression;
   parser_t parser;

   if (parser.compile(expression_string, expression))
   {
       double result = expression.value();
       //  How can the string result be retrieved at this point?
   }
   return 0;
}

...

Hypodermis answered 29/6, 2023 at 18:25 Comment(3)
There is no direct method to access the string result of an expression evaluation in the Exprtk library. Rather than string operations, the library is primarily intended for numerical computations. However, you may slightly tweak your code to accomplish the desired result. One method is to store the string values in a variable within the expression and then access that variable after the expression has been evaluated. cpp std::string stringResult = parser.symbols().get_variable("result").value_string(); Warenne
Thank you for your suggestion. I realize that Exprtk is primarily numbers oriented, but strings are supported in many ways. So adding a Value_() seems a trivial task for someone who knows the ins and outs of the package.Hypodermis
Using the most recent exprtk.hpp there is no parser.symbols() function available, or anything similar. What am I missing?Hypodermis
Z
6

The exprtk::results_context has the following helper methods:

  1. bool get_scalar(const std::size_t& index, T& out)
  2. bool get_string(const std::size_t& index, std::string& out)
  3. bool get_vector(const std::size_t& index, std::vector<T>& out)

These methods allow for easy access to the return values based on their index in the sequence of the activated return call.

#include <cstdio>
#include <string>

#include "exprtk.hpp"

int main()
{
   using symbol_table_t    = exprtk::symbol_table<double>;
   using expression_t      = exprtk::expression<double>;
   using parser_t          = exprtk::parser<double>;
   using results_context_t = exprtk::results_context<double>;

   const std::string expression_string =
      " if (1 > 0)         "
      "    return ['One']; "
      " else               "
      "    return ['Two']; ";

   expression_t expression;
   parser_t parser;

   if (!parser.compile(expression_string, expression))
   {
      printf("ERROR: Invalid expression: %s\n",expression_string.c_str());
      return 1;
   }

   expression.value();

   const results_context_t& results = expression.results();

   std::string str_output;

   if (results.get_string(0,str_output))
   {
      printf("output string: %s\n",str_output.c_str());
   }
   else
   {
      printf("ERROR: Failed to extract string return value!\n");
   }

   return 0;
}
Zip answered 23/10, 2023 at 18:5 Comment(0)
A
0

I share how I solved it since the documentation was also quite confusing for me.

I use return in the expression for the return string, and then get the results of the expression.

#include "exprtk.hpp"
#include <iostream>
#include <string>
int main()
{

    typedef exprtk::symbol_table<double> symbol_table_t;
    typedef exprtk::expression<double> expression_t;
    typedef exprtk::parser<double> parser_t;

    symbol_table_t symbol_table;
    expression_t expression;
    parser_t parser;


    if(!parser.compile("return [1, 2, 'return-call 1234']", expression)){
        std::cout << "Error parsing expression \n";
    }

    double result = expression.value();
    if(std::isnan(result)){
        std::cout << "Result is NaN, check results list\n";
    }

    if (expression.results().count())
    {
        typedef exprtk::results_context<double> 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::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];

            switch (t.type)
            {
            case type_t::e_scalar: {
                scalar_t value(t);
                std::cout << "Scalar value:" << value() << "\n";
                break;
            }
            case type_t::e_string: {
                string_t value_t(t);
                std::string value = to_str(value_t).c_str();
                std::cout << "String value Len: " << value.size() << " Value: '" << value << "'\n";
                break;
            }
            default: {
                continue;
            }
            }
        }
    }
    return 0;
}

Hope this helps someone, cheers!

Aldebaran answered 9/8, 2023 at 16:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.