我在这里做一个入门级的词法分析器。我的代码是
bool DfaTab :: isAccepted(string s){
FILE *fp1;
int i;
fp1 = fopen("javalist.dat","r");
while(!(feof(fp1))){
fscanf(fp1,"%s%d%[^\n]",tkname.c_str(),&tkval);
if(strcmp(s.c_str(),tkname.c_str()) == 0){
setTkVal(tkval);
setTkName(tkname.c_str());
state = true;
return state;
break;
}
else{
//What should I do here to skip to next line
}
}
return state;
fclose(fp1);
}
将从这里调用:
while (!(feof(src))) {
fscanf(src,"%s[^\t^ ^\n]",sym.c_str());
if (d.isAccepted(sym)) {
fprintf(des,"<%s, %d>\n",d.getTkName().c_str(),d.getTkVal());
}
else{
cout << "Can not find symbol " << d.getTkName().c_str();
cout << "Rejected.\n";
break;
}
}
我的问题是 isAccepted() 函数中的 fscanf() 函数不会跳到新行并重复打印在执行开始时读取的第一行并打印其余的执行。我现在该怎么办?
文件包含:
//javalist.dat
boolean 0
brake 1
case 2
catch 3
const 4
continue 5
default 6
....
最佳答案
在对文件执行读取操作之前调用feof
是不正确的。您可能应该将代码重组为如下所示:
// some reasonble max size
char buf[1024];
// read in a line
while(fgets(buf, sizeof(buf), fp1)) {
// parse the contents of that line
sscanf(buf, ...); //
// the rest of your code...
}
此外,您的代码中有一个相当主要的错误。
fscanf(fp1,"%s%d%[^\n]",tkname.c_str(),&tkval);
tkname.c_str()
的结果不是 可写字符串,它是一个const char *
。您可能不会将其传递给要写入的 fscanf
,这很容易导致未定义的行为,并且很容易导致崩溃。相反,您需要分配一个新缓冲区,读入该缓冲区,然后将其分配给字符串。
或者,您可以使用 iostreams 来更简单地解决这个问题:
bool DfaTab :: isAccepted(string s){
std::ifstream file("javalist.dat");
std::string line;
std::string name;
int val;
// read a line
while(std::getline(file, line)) {
// get the data out of the line
std::stringstream ss(line);
if(ss >> name >> val) {
if(name == s) {
setTkVal(val);
setTkNamename.c_str()); // if this method takes a std::string, no need for the .c_str()
state = true;
return state;
} else{
// just ignore this line and it'll continue
}
} else {
// an invalid line, handle as you please...
}
}
return state;
}
请注意这个解决方案实际上整体上更简单。
关于c++ - fscanf 卡在第一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26450779/