我正在为学校项目编写编译器,这项任务要求我将文本文件的标记打印到控制台窗口。我想说清楚不希望我的功课完成。
我一直在使用这个遍历文件的愚蠢函数,并将char或c-string值(我的导师在他的指令的这一部分上含糊不清......)连接到一个名为“token”的字符串变量。 “我可以完成文件的第一行,即“main()”,但是当我尝试访问下一行时,我得到两个错误中的一个。第一个是字符串下标超出范围错误,但我认为这是因为我试图访问不存在的字符串数组的一部分。我得到的最普遍错误是调试断言错误:
Debug Assertion使Final.exe失败 文件:f:\ dd \ vctools \ crt_bld \ self_x86 \ crt \ src \ isctype.c表达式: (无符号)(c + 1)< = 256
我已经包含了我的函数及其相关的头文件。除了函数调用之外,main中没有任何内容。如果可能的话,你能看到我没看到的东西。我意识到我的代码结构很差,我不会说谎(毕竟我在学校)。所以,任何评论,批评和建议都是非常受欢迎的。永远,谢谢你的任何时候。
.CPP文件(现在如此)
#include <iostream>
#include <string>
using namespace std;
void tokenWork::openFile()
{
fileName = "test.txt";
source.open(fileName);
if(!source.is_open())
{
cout << "Cannot find file " << endl;
}
}
void tokenWork::traveseLine()
{
pos = 0;
while (!source.eof())
{
getline(source,myLine);
int length = myLine.length();
letters = new char[length];
myLine.copy(letters,length);
c = letters[pos];
if (isalpha(c))
token = token + myLine[pos];
else if (isdigit(c))
token = token + letters;
else
{
cout << token << endl;
token = "";
}
if (c == '{' || c == '}' || c == '+' || c == '=' || myLine[pos] == '(' || c == ')' || c == ';')
cout << myLine[pos] << endl;
c = letters[pos++];
}
}
.h文件
#ifndef H_LEX
#define H_LEX
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
class tokenWork
{
public:
std::string fileName;
std::string myLine;
std::string token;
int pos;
int length;
int c;
char *letters;
ifstream source;
void openFile();
void traveseLine();
void closeFile();
};
#endif
答案 0 :(得分:2)
调试断言错误源于对std::isalpha/isdigit
的调用,当您向其传递值为&gt;的参数时255,这是类型char
(您可能应该使用而不是int
)的最大值,可以容纳。我不能告诉你确切的起源,因为你没有提供源文件,但你应该能够很容易地自己弄明白:在调试器下运行程序,它会在断言处中断。向上移动调用堆栈并检查变量的值,这应该给你一个线索。
一些提示:
答案 1 :(得分:1)
如果您只是想在每条给定的行上打印令牌,我会对您正在进行的所有额外工作感到非常困惑。缩小你的功能(和一个小的改变)应该让你有一个开始:
// note, poorly named function, it traverses the whole file
void tokenWork::traveseLine()
{
pos = 0;
while (!source.eof())
{
getline(source,myLine);
int len = myLine.size();
// NOTE: This was missing from your code, it traverses the line
// that was read in with getline() above.
for(int x = 0; x < len; ++x)
{
// NOTE: This is (in my opinion) a slightly more readable
// version of your if() statement above on tokens
// It doesn't have all your tokens, additional ones
// can be added by adding a case for them above the
// line that prints them out. Since there is no break
// statement, the functionality for all the cases above
// fall through so they all get printed out.
switch(myLine[x])
{
case '{':
case '}':
case '+':
case '=':
// add additional tokens as case statements as necessary
cout << myLine[x] << endl; // print it out
break;
default: // not a token
break;
}
}
}
答案 2 :(得分:1)
#include <cctype>
为了使用isdigit()和isalpha()
和这个
c = letters[pos++];
看起来像是一个bug的来源。 pos总是递增,但是它会不会停止?如果它到达最后一个字符(letters.length() - 1)并且你点击这一行会发生什么:增量?我怀疑阵列超出界限。
答案 3 :(得分:0)
有点难以指出代码中的特定位置 - 它有很多问题......
您最常看到的错误可能来自
token = token + letters;
字母不是以null结尾的(string :: copy不提供空终止,并且你不会为null保留空格),因此+
运算符会掉线并遇到令人讨厌的东西。< / p>
除此之外,您似乎每pos
增加getline
一次,并且永远不会重置它。你的代码看起来应该有一个内循环,但我没有看到任何。