为啥我的 C++ 递归下降解析器只适用于几台计算机? [关闭]
Posted
技术标签:
【中文标题】为啥我的 C++ 递归下降解析器只适用于几台计算机? [关闭]【英文标题】:Why does my C++ recursive descent parser only work for a few computers? [closed]为什么我的 C++ 递归下降解析器只适用于几台计算机? [关闭] 【发布时间】:2013-03-14 13:22:45 【问题描述】:由于某种原因,我的程序似乎无法在使用 Code Blocks 12.11 的计算机或使用 VMware 的教授的计算机上运行,但它在两个使用 Visual C++ 2012 的同学计算机上运行良好。因为我的计算机在 Windows XP 上运行,我不能使用 Visual C++ 2012 甚至 2010,所以我必须使用代码块。我的程序旨在从文件中读取字符串列表并检查这些字符串是否符合 BNF 语法。
从未打印过任何错误。该程序编译得很好,但在我或我教授的计算机上运行时没有输出。
编辑:预期的输出应该是它询问要读取的文本文件的名称。然后,对于文件中的每个字符串,程序应该输出该字符串是否使用该语言。如果文件不存在,则程序输出“操作失败”。而不是这个,程序直接进入“按任意键终止”,这只是假设程序已经完成运行时显示。
/* This is a recursive descent parser that uses the following productions. The
'||' operator stands for concatenation. The '|' operator for alternatives.
P_statement -> P_Identifier = P_Expression | P_Expression
P_Expression -> P_Term + P_Expression | P_Term - P_Expression | P_Term
P_Term -> P_Factor * P_Term | P_Factor / P_Term | P_Factor
P_Factor -> P_Exponential ^ P_Factor | P_Exponential
P_Exponential -> P_Identifier | L | UI | UL | (P_statement)
P_Unary -> + | - | !
P_Identifier -> P_Character | P_Character||P_Identifier
P_Character -> a | b | ... | y | z
P_Number -> P_Digit | P_Digid||P_Number
P_Digit -> 0 | 1 | ... | 8 | 9
*/
#include <iostream>
#include <string>
#include <fstream>
using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
using std::ios;
using std::ofstream;
using std::string;
// The functions that test whether the current string matches a particular
// production, hence the 'P_' prefix.
bool P_statement(void);
bool P_Expression(void);
bool P_Term(void);
bool P_Factor(void);
bool P_Exponential(void);
bool P_Unary(void);
bool P_Identifier(void);
bool P_Character(void);
bool P_Number(void);
bool P_Digit(void);
string s;
int main()
string mystr;
cout << "What is your text file? ";
cin >> mystr;
ifstream input(mystr.c_str());
if(input.is_open())
while(input.good())
getline(input, s);
string C = s;
if (P_statement() && s == "")
cout << "The string \"" << C << "\" is in the language." <<endl;
else
cout << "The string \"" << C << "\" is not in the language." <<endl;
input.close();
else cout << "Operation failed" << endl;
return 0;
bool P_statement(void)
if (P_Identifier())
if (s[0] == '=')
s = s.substr(1);
if (P_Expression())
return true;
s = s.substr(1);
if(P_Expression())
return true;
return false;
bool P_Expression(void)
if (P_Term())
if (s[0] == '+' || s[0] == '-')
s = s.substr(1);
if (P_Expression())
return true;
return true;
return false;
bool P_Term(void)
if(P_Factor())
if (s[0]=='*' || s[0]=='/')
s = s.substr(1);
if (P_Term())
return true;
return true;
return false;
bool P_Factor(void)
if (P_Exponential())
if (s[0] == '^')
s = s.substr(1);
if (P_Factor())
return true;
return true;
return false;
bool P_Exponential(void)
if(P_Identifier())
return true;
else if(P_Number())
return true;
else if(P_Unary())
if (P_Identifier())
return true;
else if(P_Number())
return true;
else if (s[0] == '(')
s = s.substr(1);
if (P_statement())
if (s[0] == ')')
s = s.substr(1);
return true;
return false;
bool P_Unary(void)
if (s[0] =='+' || s[0]=='-' || s[0]=='!')
s = s.substr(1);
return true;
return false;
bool P_Identifier(void)
if(P_Character())
if(P_Identifier())
return true;
return true;
return false;
bool P_Character(void)
if ('a' <= s[0] && s[0] <= 'z')
s = s.substr(1);
return true;
return false;
bool P_Number(void)
if(P_Digit())
if(P_Number())
return true;
return true;
return false;
bool P_Digit(void)
if ('0' <= s[0] && s[0] <= '9')
s = s.substr(1);
return true;
return false;
【问题讨论】:
预期的输出是什么,你会得到什么?此外,您还粘贴了大量代码。程序中是否有一个子部分显示出与您不符合预期的相同行为? Visual Studio 2012 有一个 XP 编译器,您可以免费下载。它可能是更新 1 的一部分。 那些函数名和变量名太可怕了。 您可以从更改while(input.good())
开始。不要循环.good()
。相反,它应该是while(getline(input, s))
。这可能会改变行为。就像其他人所说的那样,您粘贴了很多代码,您在混淆方面做得很好,这使得它更难提供帮助。
您必须遵循良好的命名约定
【参考方案1】:
您的测试函数有副作用,并且您继续对全局字符串s
进行操作。您使用数组索引到字符串中而不检查它有多长。你几乎肯定会得到未定义的行为。这可能是您在平台之间出现差异的根源。
然而,真正的问题是您的代码不清楚,不值得弄清楚它的真正作用。
更新:
您说“没有打印错误”和“它没有输出”。由于代码块上的标准库行为不同,这可能就像不刷新 std::cout 一样简单。就像<< endl
到您的第一条消息的末尾一样,看看您是否获得了刷新的缓冲区。我关于您代码中未定义行为的其他 cmets 仍然适用,但如果您根本没有收到任何消息,这可能是第一个问题。
【讨论】:
【参考方案2】:您编写的程序将接受此无效语句并将其称为有效:
a=(a7-62)^2
您不允许在标识符中使用数字,因此根据您的语法,该程序不是一个有效的程序。但是你的程序会接受它。
一旦您弄清楚它为什么会这样并解决了问题,您的程序可能会在不同平台上具有更可预测的行为。
【讨论】:
【参考方案3】:bool A(void);
bool E(void);
bool T(void);
bool F(void);
bool P(void);
bool U(void);
bool I(void);
bool C(void);
bool L(void);
bool D(void);
没有。
【讨论】:
好吧,尽管我很想对此投赞成票,但我不能让自己这么做,因为这并不是问题的真正答案。这是非常正确的。 :-) 很遗憾“低质量帖子”审核任务没有“建议回答者改进答案”按钮。以上是关于为啥我的 C++ 递归下降解析器只适用于几台计算机? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 jQuery 选择器只选择特定网站上的第一个层次结构元素?