2017-05-12 6 views
2

私は入力として文字列を与えるプログラムを書いています。この文字列は通常の用語でなければなりません。 "5 + 3/2"であり、すべての数字と演算子は空白で区切られなければなりません。入力できる期間は、必要な期間だけ長くする必要があります。 "1 * 2 * 5 - 1 * 4 + 1 + 5 + 3 + 3 + 3"もうまくいくはずです。 +、 - 、*、および/は、使用が許可されている唯一の演算子です。などの文字列を計算するための他のアイデア。 "5 + 3/2"

私はすでに動作しているコードを持っています。 *および/およびbefore +および - の事実を無視します。しかしそれは他のすべてを完全に行います。 2つの配列を作成し、演算子をchar配列(char演算子[])に保存し、もう一方の配列は浮動小数点配列(float values [])に整数を保存します。私はこの計算方法を持っています:

void calc(float values[], char operators[]) { 
    float res_final; 
    float res_array[10]; 
    int counter = (sizeof(values)/sizeof(*values)); 

    for (int i = 0; i < getBorder(values); i++) { 
     if (i == 0) { 
      res_array[i] = switchFunction(values[i], values[i + 1], operators[i]); 
     } 

     res_final = switchFunction(res_array[i], values[i + 2], operators[i + 1]); 
     res_array[i+1] = res_final; 
     if (i == getBorder(values)) { 
      break; 
     } 
    } 
    std::cout << "evaluation of expression is: " << res_final << std::endl; 
    } 

    float switchFunction(float val_1, float val_2, char op) { 
    switch (op) { 
    case '+': return val_1 + val_2; 
     break; 
    case '-': return val_1 - val_2; 
     break; 
    case '*': return val_1 * val_2; 
     break; 
    case '/': return val_1/val_2; 
     break; 
    } 
    return 0; 
    } 

よく、コードは本当にかわいいですが、私はもっと役に立つものを考え出すことができませんでした。私は非常に多くのアイデアを持っていますが、それは演算子になるとすべてが失敗しました。私は通常の+を '+'で定義し、残りのものも定義したかったのですが、これはうまく動作しません。そう

あなたが行の前にポイントを含める方法上の任意の提案を持っているか、あなたは私に完全に異なるアプローチを持っている場合、私はそれを聞いて喜んでいるだろう場合:)

+0

特定の質問がありますか?もしそうでなければ、あなたの質問は話題とは異なるです。 [コードレビュー](https://codereview.stackexchange.com/)をお探しですか? –

+0

'sizeof(values)/ sizeof(* values)'は関数内では機能しません。 [逆ポーランド記法](https://en.wikipedia.org/wiki/Reverse_Polish_notation) –

+0

に変換する必要がある中置式を計算するには、http://stackoverflow.com/questions/13421424/をご覧ください。 1つのスキャンを使用してスタック中の式を評価する方法を示します。 – mangupt

答えて

3

長期的には、あなたがしたいです式を表すObjectを作成します。

良い構造は木です。このようなツリーの内部ノードは演算子であり、リーフは数値です。

次に、文字列を解析してツリーにするパーサーを作成します。私はこのように、この再帰的にしてください:split_stringと

FormulaNode parse(input){ 
    string left, right; 
    if(split_string(input, * or /, left, right){ 
     return FormulaNode(* or /, parse(left), parse(right)) 
    if(split_string(input, + or -, left, right){ 
     ... 
    } 
    return FormulaNode(number, to_value(string)) 
} 

は、特定の記号で文字列を分割しようとする方法であること、それが可能であった場合はブール値を返すと、

左右の参照に分割し

FormulaNode(symbol, left child, right child)葉を作成し、コンストラクタである内側ノードを作成するコンストラクタ、

FormulaNode(number, value)

です。

もちろん、これはすべて擬似コードであり、原理を説明するために、あなたにスタイルを適用したくありませんでした。 2番目のコンストラクタはおそらく、署名がFormulaNode(const double)である可能性があります。シンボルに関しては、enumerate OperatorType {addition,...}のようなものを作成することをお勧めします。

編集:ここ

は多少異なる設計と大きなアーキテクチャです:

class FormulaTree{ 

    private: 

    class FormulaNode{ 

     private: 

      bool is_number; 

      //used members if is number 
      double value; 

      //used members if not is number/is operator 
      OperatorType type; 
      unique_ptr<FormulaNode> left_child, right_child; 

     public: 

      FormulaNode(string input); 
      double evaluate() const; 
    }; 

     unique_ptr<FormulaNode> root; 

    public: 

     Formula(string input); 
     double evaluate() const; 
} 

FormulaTree::FormulaNode::FormulaNode(string input){ 

    if(input contains * or /){ 

     char symbol = first occurence(input, * or /); 
     vector<string> split_input= split at first occurence(input, symbol); 
     type = OperatorType(symbol); 

     is_number = false; 
     left_child = make_unique(new FormulaNode(split_input[0])); 
     right_child = make_unique(new FormulaNode(split_input[1])); 
     return; 
    } 

    if(input contains + or -){ 

     ... 
    } 

    is_number = true; 
    value = parse to int(input); 
} 

(擬似コードで)と(長期的には、あなたがかもしれません"文字列が演算子の片側で空でない"、 "解析されたintを解析する、不正な文字が含まれていない"などの入力が合法であるかどうかをチェックするものを追加したい場合

(あなたはこれを拡大していく場合も、あなたが最初に括弧でそれを分割し、いくつかのパーサが必要)

あなたは単に私が編集しましょう、頼む、この構造については何も説明して私を必要とした場合。

EDIT:

スラバは、さまざまな種類のFormulaNodeを導出する方が良いだろうとコメントしました。これは正しいことですが、最初はこのようなデザインを表示するために編集しましたが、初心者を混乱させる可能性があるため、再度削除しました。

特にこのようなパターンには多少異なるレイアウトが必要なので、派生クラスは互いに知ってはいけないので、ツリー自体に解析をさせたいと思うでしょう。長期的には、あなたはそのようなことを学びたいと思っています。私が提示したパターンを試してみて、独自のスタイルを追加し、いくつかの機能を追加することをお勧めします(負の数を表すためにマイナス記号を使用するオプションや電源記号など)。CodeReviewに貼り付けてください。私の推論は、これがあなたがやりたがっていることであり、あなたがそうしたときに、あなたのコードはすべての部分で "完璧"になるまで攻撃されるということです。

+0

FormulaNodeは、可能なすべての値とフラグを保持するのではなく、値またはエクステンションとして拡張できる基本クラスでなければなりません。 – Slava

+0

@スラバ右、編集済み。でも、初心者を混乱させたくないかどうかわからない。 – Aziuth

+0

@Slavaもう一度削除しました。初心者のためにあまりにも混乱していることがわかりました。しかし、再び...ハム。これをどのように表示するか分かりません。 N30が自分の好みで自分のパターンを使い、CodeReviewで評価させようとするなら、最良の方法だと思います。私にとってはあまり意味がないし、彼はそれを試してみるのではなく、細部にまで行きすぎるようにする。今のところunique_ptrが過剰であるかもしれません。 N30:これを行う(つまり、CodeReviewに投稿する)場合は、ここにリンクを付けてタグを付けてください。 – Aziuth

関連する問題