创建动态变量

时间:2012-06-30 03:34:27

标签: c++ macros user-input

是的,我知道c ++中不可能有动态变量。我正在寻找的是一种解决方法。

这个想法基本上就是这个。我有一堆数学模型在一起。它们都具有完全相同的形式,除了

  1. 一些函数的数学定义
  2. 所需的常数:它们被称为什么,它们的数量和价值。
  3. 常数的值可能会在实验之间发生变化,但其他一切都是材料模型本身的属性。模型的常量参数在输入文件中以

    的形式给出

    variable_A=2.0

    材料模型(包括所有函数)之前是通过生成的代码完成的,通过Maple从抽象的数学表达式生成,具有良好的GUI环境来引导。由于多种原因,现在可悲地打破了这种情况。作为其他一些工作的结果,模型现在在代码中完全相同,除了它们的形式描述不同之处。我没有找到一个完整的单独程序来生成这个代码(目前已被破坏,而且我们曾经拥有这些代码),我正在寻找一种更简单的替代方案,因为现在我只需要在给定文件中大约需要20行来区分一种材料。另一个。但是,实现这些模型的用户不会对c ++有任何了解。因此,虽然我可以简单地要求他们浏览文件并在各个地方更改内容,但我一直在寻找更加用户友好的内容:因此用户只需在一个地方更改几行 并以这种方式定义他们的模型,而不必查看其余的代码。

    用户定义的功能如下所示。

    double myfunction(double arg1, double arg2, vector arg3 ) \\just an example
    {
        ...
        ...
        double a=database.find_constant("a_const");
        double b=database.find_constant("b_const");
        return sqrt(a*3+pow(b,2)-a/b)+...; \\still example pseudocode
    }
    

    顶部的省略号相当丑陋(不错的代码,只是语法沉重且无关紧要),因此我不希望最终用户必须处理它们。我可以通过例子更好地描述我的问题:

    我最初的计划是在顶部使用宏(是的,我知道,恐怖),这样就可以像

    一样
     #define A database.find_constant("a_const")
     #define FUNCTION pow(A-2,3)   
     ...
    double myfunction(...)
    {
        ...
        return FUNCTION;
    }
    

    然后我发现你无法嵌套宏。回想起来很明显,但我离题了。然后我意识到我可以更改#define A语句以使A成为全局变量。然后,我甚至考虑全局变量。基本上,我所有尝试将这一切都放在用户不需要太多c ++知识的地方都是荒谬和/或非常不安全的。

    通常我讨厌问这样的开放式问题,但我真的不想让自己头疼。我将只在短时间内完成这个项目,因此设计某种形式的UI和/或生成代码是不切实际的。我现在要去'概念证明'了。

    有没有更好的方法来让他们通过模型并直接更改函数中所需的行?

    编辑:我没有编写整个项目,也不打算以这种方式工作。我们用于生成这些文件的原始工具使用了Maple的代码生成,其中函数和变量在一个漂亮的GUI中作为Maple语法输入。不幸的是,GUI似乎不再起作用(一致地),并且一旦我们切换版本,Maple返回的代码停止产生正确的结果:我们不确定问题究竟是什么,我们现在正在探索其他途径。新文件很多比之前的文件更相似(作为其他工作的结果),这是新技术的动机的一部分。如果我只需要几行就能以简单的方式协同工作,那我希望能绕过代码生成。这不是“为我修好的!”问题,我只想了解其他选项可能是什么。是的,我知道这开始并不是一个好的情况,如果这是从一开始就计划好的,就不会这样做。但这种设置可能是暂时的,正如我所说的更像是一个概念证明而不是其他任何东西。

    希望现在的问题更加清晰。我的问题特别是以一种简单易用的方式将所有内容分组到一个地方。感谢您的耐心等待。

5 个答案:

答案 0 :(得分:1)

变量本身实际上可以非常容易地处理:读取值并将它们放入std::map<std::string, double>(或int而不是double(如果值都是整数)。例如:

std::map<std::string, double> values;

// Code to read name and value from the file goes here.
// Then something like:
values[name] = value;

其余评估表达式是一个相当深刻的主题。它的代码很容易找到(例如,muParser)。我猜大多数人都有自己的支持变量,所以你可能不需要写一个你自己的显式地图。

答案 1 :(得分:1)

您可以尝试“像宏一样行动”但不是,就是将各种函数组封装在匿名结构中:

struct
{
    double find_constant(const char* s) { do-stuff...; }
    double calc_value(int a, int b) { do-stuff...; }
    ...
} GeneralStuff;

使用宏来访问此结构中的函数:

#define DoStuff GeneralStuff

并在您的代码中访问它:

...
DoStuff.find_constant("a_const");
...

如果用户需要更改代码,他会创建结构的副本,应用更改,以及 重新定义宏:

struct
{
    ...changed code...
} MyStuff;

#define DoStuff MyStuff

如果我理解你的问题,这些将是唯一需要的更改。

答案 2 :(得分:0)

您需要的只是让他们在输入文件中编写表达式,然后自己解析并查找数据库中的任何未知引用,然后对其进行评估。如果您不需要非常高的评估性能,这对您和他们来说都相对简单。例如,您可以使用Lua轻松地自然地执行此操作 - 您需要做的就是在全局表上设置__index metatable值以查找数据库,并且所有数据库常量都是“全球”Lua值。

答案 3 :(得分:0)

这可能只会引起更多麻烦,但对于未来这样的事情,可以考虑使用boost.spirit来构建一个实际的解析器,或者可能是proto来构建一个特定于域的语言。

答案 4 :(得分:0)

(1)如果您希望用户查看和编辑最少的代码,您可以考虑滥用预处理器,将代码分成数学前的位(BEGIN_ROBERTS_MAGIC.inl)和数学后的代码(END_ROBERTS_MAGIC.inl)

BEGIN_ROBERTS_MAGIC.inl(您的代码)

#include <cmath>
...otherstuff
double function(*args go here*)
{
    ....prep work
    //this file ends right before the lines with the math

END_ROBERTS_MAGIC.inl(您的代码)

    //this file begins right after the lines with the math
}
...otherstuff

STUPID_PHYSICS_MODEL.cpp(他们的代码)

#include "BEGIN_ROBERTS_MAGIC.inl"

double a=database.find_constant("a_const"); //or double a = constant["a"];
double b=database.find_constant("b_const"); //or double b = constant["b"];

return sqrt(a*3+pow(b,2)-a/b)+...;

#include "END_ROBERTS_MAGIC.inl

这意味着其他人看到的文件只有五行左右的代码,看起来非常简单而且完全不会令人生畏,所有魔法都藏在他们看不到的其他文件中。

(2)正如其他人所建议的,您可以将用户的代码放入不属于C ++代码的脚本中(通过精神,lua,javascript或任何其他脚本语言),这意味着您不必为每个脚本重新编译模型,还可以在运行时添加或删除实际的全局变量,但这更复杂。