3

はい、C++ では動的変数を使用できないことはわかっています。私が探しているのは回避策です。

考え方は基本的にこれです。私はたくさんの数学的モデルを一緒に持っています。を除いて、それらはすべてまったく同じ形式を持っています。

  1. いくつかの関数の数学的定義
  2. 必要な定数: それらの名前、その数、およびその値。

定数の値は実験ごとに変わる可能性がありますが、それ以外はすべて材料モデル自体のプロパティです。モデルの定数パラメーターは、入力ファイルで次の形式で指定されます。

variable_A=2.0

マテリアル モデル (すべての関数を含む) は、Maple を介して抽象的な数式から生成された生成コードを使用して以前に作成され、起動するための優れた GUI 環境がありました。悲しいことに、これは複数の理由で壊れています。他のいくつかの作業の結果、形式的な記述の違いを除いて、モデルはすべてコードがまったく同じになりました。このコードを生成するためのまったく別のプログラム (現在は壊れていて、以前は使用していたもの) を用意する代わりに、より単純な代替手段を探しています。別。ただし、これらのモデルを実装するユーザーは、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++ の知識をあまり必要としない 1 つの場所にこれをすべて貼り付けようとする私の試みはすべて、ばかげているか、恐ろしく安全ではありません。

通常、私はそのようなオープンエンドの質問をするのは嫌いですが、頭痛の種になりたくありません. 私はこのプロジェクトに短期間しか取り組んでいないので、なんらかの形式の UI を設計したり、コードを生成したりすることは現実的ではありません。現時点では、「概念実証」に取り組んでいます。

モデルを調べて、関数内の必要な行を直接変更するよりも、これを行うためのより良い方法はありますか?

EDIT:私はこのプロジェクト全体を書いたわけではなく、もともとこのように動作することを意図していませんでした. これらのファイルを生成するために私たちが持っていた元のツールは Maple のコード生成を使用し、関数と変数は優れた GUI で Maple 構文として入力されました。残念ながら、GUI はもう (一貫して) 機能しないようです。バージョンを切り替えると、Maple が返したコードは正しい結果を生成しなくなりました。問題の正確な原因はわかりません。現在、他の方法を模索しています。 . 新しいファイルもたくさん(他の作業の結果として)以前のものよりも似ています。これは、新しい手法の動機の一部です。簡単な方法で一緒に作業するのに数行しか必要ない場合は、コード生成を回避できることを望んでいました。これは「私のために直してください!」ではありません。質問です。これらの他のオプションが何であるかを知りたいだけです。はい、そもそも良い状況ではないことはわかっています。もしこれが最初から計画されていたのであれば、このようにはならないでしょう。しかし、この設定はおそらく一時的なものであり、先に述べたように、何よりも概念実証にすぎません。

うまくいけば、質問は今より明確です。私の問題は、特に使いやすい方法ですべてを 1 か所にグループ化することです。お待ちいただいてありがとうございます。

4

5 に答える 5

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

あなたの質問を正しく理解していれば、必要な変更はこれらだけです。

于 2012-07-06T07:03:01.627 に答える
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 )。ほとんどの場合、独自のサポート変数があると思いますが、おそらく独自の明示的なマップを作成する必要はありません。

于 2012-06-30T04:01:35.193 に答える
0

必要なのは、入力ファイルに式を記述させ、それを自分で解析し、データベースから不明な参照を検索して、評価することだけです。非常に高い評価パフォーマンスを必要としない場合、これはあなたと彼らの両方にとって比較的簡単です。たとえば、Luaを使用すると、これを非常に簡単に自然に実行できます__index。データベースを検索するためにグローバルテーブルにメタテーブル値を設定するだけで、データベース定数はすべて「グローバル」Lua値になります。 。

于 2012-06-30T03:56:30.013 に答える
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

つまり、他の人が見るファイルはわずか 5 行ほどのコードであり、非常に単純でまったく威圧的ではなく、見えない他のファイルにすべての魔法が隠されていることを意味します。

(2) 他の人が示唆したように、ユーザーのコードを C++ コードの一部ではないスクリプトに (精神、lua、javascript、またはその他のスクリプト言語を介して) 入れることができます。これは、モデルごとに再コンパイルする必要がないことを意味します。実行時に実際のグローバル変数を追加または削除することもできますが、これはより複雑です。

于 2012-06-30T05:19:43.493 に答える
0

これは頭​​痛の種を増やすだけかもしれませんが、将来的には、boost.spirit を使用して実際のパーサーを構築するか、proto を使用してドメイン固有言語を構築することを検討してください。

于 2012-06-30T04:06:06.050 に答える