c++ - fscanf 卡在第一行

标签 c++

我在这里做一个入门级的词法分析器。我的代码是

 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/

相关文章:

c++ - CUDA 中的复杂算术

c++ - 如何着手开发新的 Qt 5.7+ High-DPI Per Monitor DPI Aware 应用程序?

c++ - enable_if SFINAE 的问题

c++ - 没有 PROGMEM 的 Adafruit gfx 库 drawBitmap

c++ - 为什么不能实例化带有 "non const"复制构造函数的对,而没有实例化一对是可能的?

c++ - 使用以 10.0.0 形式定义版本号的宏

c++ - for循环中的构造函数问题

c++ - 连接到正在运行的 IE 实例 C++

c++ - 模板错误 : Iterator was not declared in the scope

c++ - C和C++如何在堆栈上存储大对象?