簡體   English   中英

計算包含“ 5 + 3/2”的字符串的其他方法

[英]other ideas for calculating a string that contains e.g. “5 + 3 / 2”

我已經編寫了一個程序,您在其中輸入一個字符串。 該字符串應為常規術語,例如“ 5 + 3/2”,並且所有數字和運算符都必須通過空格分隔。 您可以輸入的術語應盡可能長,例如“ 1 * 2 * 5-1 * 4 +1 + 5 + 3 + 3 + 3”也應該起作用。 +,-,*和/是唯一允許使用的運算符。

我已經有了工作代碼。 但忽略了*和/以及+和-之前的事實。 但它可以完美地完成其他所有工作。 這個想法是創建兩個數組,一個數組將運算符保存在char數組中(稱為char operator []),另一個數組將整數保存在float數組中(稱為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;
    }

好的代碼不是很漂亮,但是我無法提出更多有用的東西。 我有很多想法,但是對於操作員來說,一切都失敗了。 我想在'+'中定義普通的+,其余的也一樣,但是這行不通。

因此,如果您對如何在行前包含點有任何建議,或者您有完全不同的方法來進行挖掘,我將很高興聽到它:)

從長遠來看,您想創建一個代表公式的對象。

一個好的結構就是一棵樹。 這樣的樹的內部節點是運算符,而葉子是數字。

然后,編寫一個將字符串解析為樹的解析器。 我會像這樣遞歸執行:

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))
}

使用split_string是一種方法,該方法嘗試按某個符號將字符串拆分,如果可能的話返回一個布爾值,並將其拆分為左右引用,

FormulaNode(symbol, left child, right child)是創建內部節點的構造函數,

FormulaNode(number, value)是創建葉子的構造函數。

當然,所有這些都是偽代碼,不想只是為了說明原理就強加給您樣式。 第二個構造函數可能僅是簽名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有效,不包含任何非法字符”等)等等)

(此外,如果繼續擴展此功能,則需要一些解析器,該解析器首先將其用方括號分隔)

如果您需要我解釋有關此結構的任何內容,只需問一下,我將進行編輯。

編輯:

Slava評論說,最好為不同類型派生FormulaNode。 沒錯,我本來是為了顯示這種設計而對其進行編輯的,但由於它可能會使初學者容易混淆,因此我再次將其刪除。

尤其是由於這種模式將需要稍微不同的布局-我們希望讓樹本身進行解析,因為派生類之間不應該相互了解。 從長遠來看,您想學習這樣的東西。 我建議您嘗試一下我介紹的模式,添加自己的樣式,添加更多功能(例如,用於加電的符號或使用負號表示負數的選項),然后將其放在CodeReview上 我的推理是,無論如何,這就是您想要做的,並且當您這樣做時,無論如何,您的代碼都會受到攻擊,直到“完美”為止。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM