简体   繁体   English

C++ 中 fstream 的行为

[英]Behaviour of fstream in C++

I have made the following script, that is supposed to read from a file:我制作了以下脚本,应该从文件中读取:

    char match[] = "match";

    int a;
    int b;

    inp >> lin;
    while(!inp.eof()) {
        if(!strcmp(lin, match)) {
            inp >> a >> b;
            cout << a << " " << b <<endl;
        }
        inp >> lin;
    }

    inp.close();
    return num_atm;
}

It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.它应该读取所​​有单词,如果一行以 match 开头,它还应该打印该行的其余部分。

My input file is this:我的输入文件是这样的:

match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6

It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever.它将正确打印 1 2, 5 2,并跳过 3 6。但是,它会卡住并继续打印 5 0 并永远继续打印 5 0。 I get that match is put into b, which is an integer, but I don't get why this is looped.我得到匹配被放入 b,这是一个整数,但我不明白为什么这是循环。 Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5?输入读取不应该匹配 4 一次,尝试读/写 5 并匹配,然后用第 4 行和第 5 行的匹配来完成吗? Then it should next read the number 1 and 4 and then match from number 6.然后它应该接下来读取数字 1 和 4,然后从数字 6 开始匹配。

I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.我也明白,由于单词不适合整数,它会再次读取第五行中的匹配,但这不是它的作用。

It goes back to the match in the fourth line which it already read, and reads it again.它返回到它已经阅读的第四行中的匹配项,并再次阅读。 Why is this?为什么是这样?

When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped.当您使用>>行尾阅读时,其处理方式与空格相同:它们只是更多的空白被跳过。 That means you see这意味着你看到

match 1 2 
match 5 2 
nope 3 6 
match 5 
match 1 4 
match 5 9 

But the program sees但是程序看到

match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9 

Let's fast forward to where things go south让我们快进到事情向南的地方

Contents of stream:流的内容:

nope 3 6 match 5 match 1 4 match 5 9 

Processing加工

inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9 
if(!strcmp(lin, match)) { // nope != match skip body
}
inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9 
if(!strcmp(lin, match)) { // 3 != match skip body
}
inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9 
if(!strcmp(lin, match)) { // 6 != match skip body
}
inp >> lin; // reads match stream: 5 match 1 4 match 5 9 
if(!strcmp(lin, match)) { // match != match Enter body
    inp >> a >> b; // reads 5 and fails to parse match into an integer.
                   // stream: match 1 4 match 5 9 
                   // stream now in failure state
    cout << a << " " << b <<endl; // prints 5 and garbage because b was not read

}
inp >> lin; // reads nothing. Stream failed
if(!strcmp(lin, match)) { // match != match Enter body
    inp >> a >> b; // reads nothing. Stream failed
                   // stream: match 1 4 match 5 9 
                   // stream now in failure state
    cout << a << " " << b <<endl; // prints g and garbage because b was not read

}

Because nothing is ever read, while(!inp.eof()) is utterly worthless.因为什么都没有读过,所以while(!inp.eof())完全没有价值。 The end of the file can never be reached.永远无法到达文件的末尾。 The program will loop forever, probably printing whatever it last read.该程序将永远循环,可能会打印上次读取的内容。 Successfully read.成功阅读。

Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like如果您有一条没有 2 个数字的匹配行,解决这个问题完全取决于您想要做什么,但典型的框架看起来像

std::string line;
while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.
{
    std::istringstream strm(line);
    std::string lin;
    if(strm >> lin && lin == match) // enters if lin was read and lin ==  match
                                    // if lin can't be read, it doesn't matter. 
                                    // strm is disposable
    {
        int a;
        int b;

        if (strm >> a >> b) // enters if both a and b were read
        {
            cout << a << " " << b <<"\n"; // endl flushes. Very expensive. just use a newline.
        }
    }
}

Output from this should be something like输出应该是这样的

1 2 
5 2 
1 4 
5 9 

If you want to make some use of match 5 ... Well it's up to you what you want to put in b if there is no b in the file.如果您想使用match 5 ...那么,如果文件中没有b ,那么您想在b放入什么取决于您。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM