C ++比较N个表达式的RHS与LHS

时间:2018-12-11 08:34:56

标签: c++

我需要确定一个简单表达式的LHS是否等于其RHS。输入包含整数N,然后是N行表达式。无论表达式是否正确,输出还包含N行(输出CORRECTWRONG)。

所以我试图为N行输入编写for循环,用于(int i = 1; i <= n; ++ i),但是我不知道在for循环中还包括什么。

还如何验证方程的LHS是否等于RHS?

2 个答案:

答案 0 :(得分:0)

您可以这样做:

  1. 定义用于表示表达式的数据类型。
  2. 编写一个函数来确定两个这样的表达式是否相等。
    • 使用硬编码数据对其进行测试。
  3. 编写一个读取一个表达式的函数。
    • 使用硬编码数据对其进行测试。
  4. 使用第2项和第3项中的函数读取两个表达式并进行比较。
    打印适当的回复。
  5. 环绕第4项循环。

答案 1 :(得分:0)

对于这样的输入(假设将其保存在文件“ equation_list.txt”中):

3 
3 = 1 + 2
3 = 3 + 2 
3 * 9 = 26 + 1

以下代码将生成如下控制台输出:

CORRECT
WRONG
CORRECT

函数for (int i = 1; i <= std::stoi(equations[0]); i++)中的int main()是您在问题中提到的循环。在循环发生之前,需要进行一些文件和字符串操作。

#include <fstream>
#include <sstream>
#include <vector>
#include <iostream>
#include <limits>

#include "exprtk.hpp"

bool check_equation(const std::string LHS, const std::string RHS)
{
    typedef exprtk::expression<double>     expression_t;
    typedef exprtk::parser<double>             parser_t;

    expression_t expression;
    parser_t parser;

    // Calculate LHS's value.
    parser.compile(LHS, expression);
    double LHS_result = expression.value();

    // Calculate RHS's value.
    parser.compile(RHS, expression);
    double RHS_result = expression.value();

    // Check if the difference of these two results is less than a very small 
    // value EPSILON.
    // This is the proper way in C++ to check equation of double values.
    // "if (LHS_result == RHS_result)" is not reliable.
    if (abs(LHS_result - RHS_result) < std::numeric_limits<double>::epsilon())
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main()
{
    std::ifstream file("equation_list.txt");
    std::stringstream buffer;

    // Read the equation list from file, saving into buffer.
    if (file)
    {
        buffer << file.rdbuf();
        file.close();
    }
    else
    {
        std::cout << "equation file does not exist!";
    }

    // Split the equations to individual ones (delimiter is '\n' (newline symbol)), 
    // saving into a vector.
    std::vector<std::string> equations;
    std::string s;

    while (getline(buffer, s, '\n'))
    {
        equations.push_back(s);
    }

    // Loop the vector to check the correctness of each equation. 
    // equations[0] is the number of equations (the first line in input).
    for (int i = 1; i <= std::stoi(equations[0]); i++)
    {
        // Again, using the previous technique, split this equation by 
        // delimiter '=', saving the result (i.e. LHS and RHS) into a vector.
        std::stringstream individual_equation(equations[i]);

        std::vector<std::string> parts;
        std::string s;

        // Assuming each line of equations has one and only one '=' symbol. Checking omitted.
        while (getline(individual_equation, s, '=')) 
        {
            parts.push_back(s);
        }

        // Now, parts[0] is LHS, and parts[1] is RHS.
        // Check if LHS equals to RHS.
        if (check_equation(parts[0], parts[1]) == true)
        {
            std::cout << "CORRECT" << std::endl;
        }
        else
        {
            std::cout << "WRONG" << std::endl;
        }
    }

    return 0;
}

问题的棘手部分是模拟字符串输入(LHS和RHS)的数学计算。这并不像乍看起来那样直观。我建议使用外部库解决此计算问题(请参见代码中的#include "exprtk.hpp"和函数bool check_equation(const std::string LHS, const std::string RHS))。该库称为 ExprTk 。您可以在http://partow.net/programming/exprtk/index.html中找到有关ExprTk的更多信息。

如果您打算自己实现数学计算模拟,建议您先研究一下Polish Notation,这是一种方便于计算机的读取表达式的方式。

仅提供波兰表示法的示例。 a + b / c - d * e是方便阅读的表达方式。计算机方便的方式是将其功能性地读取为sub(add(a, div(b, c)), mul(d, e))。将函数名替换为操作数符号后,该名称将变为波兰语表示法-+a/bc*de

最后,数据结构Binary Tree在实践中会变得很方便,所有操作数都位于叶子节点上,所有运算符都位于非叶子节点上。