【问题标题】:Evaluating expression statements from a text file in C++在 C++ 中评估文本文件中的表达式语句
【发布时间】:2019-05-10 16:48:51
【问题描述】:

我正在修改一个(嗯,我的第一个)计算表达式的 C++ 程序。例如,通过输入:

(x + (y * 3)), x = 2, y = 6;

它应该输出以下内容:

Value = 20

当用户在控制台中键入表达式时,程序可以工作,但我希望它从文本文件中读取和评估表达式(每个都在单独的行上)。我已成功读取文件在,甚至可以在控制台中打印它的内容,但是我在解析和评估每一行时遇到了麻烦。这个项目附带的头文件和源文件还有很多,但我认为所有相关信息都在 main 函数中:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

#include "expression.h"
#include "subexpression.h"
#include "symboltable.h"
#include "parse.h"

SymbolTable symbolTable;

void parseAssignments();

int main()
{
    Expression* expression;
    char paren, comma;
    string program;

    ifstream myfile("expressions.txt");

    if (myfile.is_open())
    {
        while (getline(myfile, program))
        {
            cout << program << '\n'; //confirms that file was read properly

            //code to parse expressions and print results
        }
        myfile.close();
    }
    else cout << "Unable to open file";

    //original code that parses expression the user inputs
    /*cout << "Enter expression: ";
    cin >> paren;
    expression = SubExpression::parse();
    cin >> comma;
    parseAssignments();
    cout << "Value = " << expression->evaluate() << end1;*/

    cin.get(); //added this so the window doesn't close automatically
    return 0;
}

在过去的几天里,我尝试了很多方法,我认为这归结为我的 C++ 对这两行到底发生了什么一无所知。我的理论是它解析第一行括号右侧的所有内容,以及第二行逗号右侧的所有内容(忽略范围重叠的事实)。

    cin >> paren;
    cin >> comma;

因此,在其他方法中,我尝试在 while 循环中包含以下内容。我正在使用 MS Visual Studio,当我单击“>本地 Windows 调试器”时,它将打开一个控制台窗口,其中打印了第一个表达式和一条闪烁的线,就像它在等待我输入内容一样。我关闭了窗口,而不是“继续”而不是“本地 Windows 调试器”,它只会结束程序。我完全有可能只是错误地使用了 Visual Studio。

myfile >> paren;
expression = SubExpression::parse();
myfile >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();

还有这个:

std::istringstream iss(program);
iss >> paren;
expression = SubExpression::parse();
iss >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();

当然还有这个:

getline(myfile, program) >> paren;
expression = SubExpression::parse();
getline(myfile, program) >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();

我是否采取了完全错误的方法,或者更糟的是我应该专注于更改其他功能吗?谢谢!!

编辑:似乎在parse() 和其他一些.cpp 文件中调用了cin &gt;&gt;,这阻止了我上面的三个尝试产生很大的影响。现在我正在考虑将这一行作为参数包含在下面的函数中。如果它不起作用,我会报告任何错误。

string parseName()
{
    char alnum;
    string name = "";

    cin >> ws;
    while (isalnum(cin.peek()))
    {
        cin >> alnum;
        name += alnum;
    }
    return name;
}

编辑 2:它工作!由于整个程序都在使用cin &gt;&gt;,因此我必须创建一个新变量std::stringstream in(program);,然后将其用作函数中的参数,如下所示:

void parseAssignments(stringstream& in);

int main()
{
    Expression* expression;
    char paren, comma;
    string program;

    ifstream myfile("expressions.txt");

    if (myfile.is_open())
    {
        while (getline(myfile, program))
        {
            cout << program << '\n'; //confirms that file was read properly

            std::stringstream in(program);
            in >> paren;
            expression = SubExpression::parse(in);
            in >> comma;
            parseAssignments(in);
            cout << "Value = " << expression->evaluate() << '\n\;
        }
        myfile.close();
    }
    else cout << "Unable to open file";

    cin.get(); //added this so the window doesn't close automatically
    return 0;
}

感谢你们的帮助!我想我会回到使用 C++ 更简单的东西并从那里开始构建......

【问题讨论】:

  • 你能比“没有成功”更具体吗?
  • 为什么stringstream 版本不起作用?
  • 有什么问题?
  • 这对于第一个程序来说是雄心勃勃的!
  • 同意^ed。评估( 2 + ( 3 * 6 ) )(注意:空格,没有变量)已经是一个挑战。也许您甚至应该考虑2 3 6 * +(反向波兰表示法)。中缀可能很熟悉,但括号很难。

标签: c++


【解决方案1】:

让我们从这个开始

cin >> paren;
expression = SubExpression::parse();
cin >> comma;

此代码从 cin(终端)读取单个字符,然后调用 parse,然后读取另一个单个字符。它永远不会读懂你的表情。它也从不对这两个单独的角色做任何事情,它只是把它们扔掉。

这告诉我,从终端读取表达式的代码在 SubExpression::parse() 中——该代码(您没有显示)显然是直接从 cin 读取的。

这立即表明了为什么你所有的尝试都失败了——你的表达式在一个文件或一个字符串中,但你的解析例程仍然顽固地从 cin 读取。您需要更改该例程以从其他地方读取。

【讨论】:

  • 谢谢!从SubExpression::parse() 读取表达式是有道理的,果然我不仅在 parse.cpp 中找到了 cin,还在其他 2 个 .cpp 文件中找到了 cin!我正在用myfile &gt;&gt; 改正这些问题,但是我是否应该实例化ifstream myfile("expressions.txt"); 并每次都包装在相同的if 和while 循环中?我认为答案是否定的,但我不确定替代方案是什么。
  • 没关系,我想通了。再次感谢,您为我指明了正确的方向。
  • @Syk3:最好让parse 接受istream &amp; arg 并从中读取。
猜你喜欢
  • 1970-01-01
  • 2014-12-08
  • 1970-01-01
  • 2016-11-11
  • 1970-01-01
  • 1970-01-01
  • 2011-07-22
  • 2011-01-27
  • 2015-11-05
相关资源
最近更新 更多