C++ EOF与GCC 5.2.1上的基本ios::EOF()

C++ EOF与GCC 5.2.1上的基本ios::EOF(),c++,visual-studio,gcc,ifstream,C++,Visual Studio,Gcc,Ifstream,在使用GCC 5.2.1编译的程序上,ifstream的状态在到达文件末尾时不会切换到basic\u ios::eof(),即条件if(eof())在到达文件结尾后计算为false,而在Visual Studio 2015上编译的相同代码的行为与预期相同:当到达文件结尾时,if条件中的基本ios::eof()计算为true 我用if(bad())替换了if(eof()),然后用if(fail())替换了if(eof()),它们的计算结果都是false。但是,当我放置EOF宏时,if(EOF)的计

在使用GCC 5.2.1编译的程序上,
ifstream
的状态在到达文件末尾时不会切换到
basic\u ios::eof()
,即条件
if(eof())
在到达文件结尾后计算为
false
,而在Visual Studio 2015上编译的相同代码的行为与预期相同:当到达文件结尾时,
if
条件中的
基本ios::eof()
计算为
true

我用
if(bad())
替换了
if(eof())
,然后用
if(fail())
替换了
if(eof())
,它们的计算结果都是
false
。但是,当我放置
EOF
宏时,
if(EOF)
的计算结果为
true
——就像VS编译的程序上的
if(EOF())
一样

std::basic_ios::eof()
无法在使用GCC编译的程序上运行的原因可能是什么

下面是程序代码

#include <string>
#include <iostream>
#include <fstream>
#include <regex>

using namespace std;
using namespace std::chrono;

int ex10()
{
    ifstream in{ "school.txt" };
    if (!in) cout << "The 'school.txt' file was not opened.\n";

    string line;

    regex header{ R"(^([\w]+)(\t{2}\w+\s*\w*)(\t\w+\s*\w*)(\t\w+\s*\w*)$)" };
    regex row{ R"(^(\w+\s*\w*)(\t{1,2}\d+)(\t{2}\d+)(\t{2}\d+)$)" };

    if (getline(in, line)) {
        smatch matches;
        if (!regex_match(line, matches, header))
            cerr << "Wrong header format.\n";
    }
    int linenum = 0;
    int boys = 0;
    int girls = 0;

    ofstream out{ "schoolCompressed.txt" };
    if (!out) cout << "The output file was not created.\n";
    string prevLine;
    int accumBoys;
    int accumGirls;
    int accumTot;

    while (getline(in, line)) {
        ++linenum;
        smatch matches;
        if (!regex_match(line, matches, row))
            cerr << "Row #" << linenum << " doesn't match the format.\n";


        int curr_boy = stoi(matches[2]);
        int curr_girl = stoi(matches[3]);
        int curr_total = stoi(matches[4]);

        if (curr_boy + curr_girl != curr_total)
            cerr << "Wrong children number in line #" << linenum << '\n';

        if (line[0] != prevLine[0]) {

            if (linenum != 1) out << prevLine[0] << "\t\t" << accumBoys << "\t\t"
                << accumGirls << "\t\t" << accumTot << '\n';
            accumBoys = curr_boy;
            accumGirls = curr_girl;
            accumTot = curr_total;

        }

        else if (line[0] == prevLine[0]) {

            accumBoys += curr_boy;
            accumGirls += curr_girl;
            accumTot += curr_total;
        }


        if (EOF && curr_boy == boys && curr_girl == girls) { out << line; return 0; } //this works on GCC
        //if (in.eof() && curr_boy == boys && curr_girl == girls) { out << line; return 0; } <= this works on VS 2015


        boys += curr_boy;
        girls += curr_girl;
        prevLine = line;
    }
    cerr << "Somehow the program didn't manage to complete its task :(.\n";
    return 1;
}
int main()
{
    ex10();
}
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间std::chrono;
int ex10()
{
{“school.txt”}中的ifstream;

如果(!in)coutEOF是常量整数的宏,那么

 if (EOF && curr_boy == boys && curr_girl == girls)
它只是并没有做你们期望的事情,也就是检查文件的结尾

只有当io操作失败时,才应使用
eof()。
条例规定,

std::basic_ios::eof仅报告most设置的流状态 最近的I/O操作。它不检查关联的数据源。例如,如果最近的I/O是一个get(),它返回了文件的最后一个字节,eof()返回false下一个get()无法读取任何内容并设置eofbit。只有eof()返回true

在您的代码中

while (getline(in, line)) {
   ...
   if (in.eof())
   ...
}
预期的行为是GCC的行为。要知道您在文件末尾,您应该尝试进一步阅读。这与

while (!in.eof()) {
   ...
   getline(in, line)
   ...
}
您应该将curr_boy和条件移出while循环,并消除eof测试

int curr_boy = 0;
int curr_girl = 0;
while (getline(in, line)) {
}

if (curr_boy == boys && curr_girl == girls) { out << line; return 0; }
int curr\u boy=0;
int curr_girl=0;
while(getline(in,line)){
}

如果(curr_boy==boys&&curr_girl==girls){out您是否在相同的操作系统上使用相同的文件

getline
函数将设置
eof
标志,如果它在看到
'\n'
之前到达文件末尾。这只能发生在文件的最后一行


您可能应该将结束测试移到while循环之外,在那里我们知道,当最新的
getline
读取另一行失败时,我们已经到达了文件的结尾。

如果没有实际看到您的程序,我们无法解释为什么您的程序无法工作。请发布一个包含重现问题所需的所有内容的日志。我f(EOF)?真的吗?EOF是一个常数。@UmNyobe事实上,当if只有
if(curr\u boy==boys&&curr\u girl==girls)
没有
EOF()
EOF
时,代码会编译并工作。我只是不明白为什么
EOF()
在GCCT上编译代码时不起作用
school.txt
文件在这两种情况下都是相同的。表的最后一行不是以“\n”结尾。这就是我询问操作系统的原因。例如,如果在Cygwin下运行,则有一种配置,可以为文本文件中的行结尾选择Windows或Linux规则。这可能会导致有点不同。不管怎样,为什么不读到没有更多的行,然后你就知道你到了结尾。我在Ubuntu 15上使用GCC编译的可执行文件;在Windows 7上使用VS编译的可执行文件。在Windows上没有这个问题。但是如果(curr\u boy==boys&&curr\u girl==girls)
if(curr\u boy==boys&&curr\u girl==girls)
产生错误,因为变量
curr\u boy
curr\u girl
在其中声明。当我按照您的建议将其放置在循环外部,并修改为
if(in.eof()){虽然还不清楚,但是你必须将curr变量移到外部。当有eof时,循环大部分时间都会终止。但是你必须执行getline,这将导致eof。这就是为什么eof在循环外部工作,而不应该在内部工作。现在Visual studio因不严格遵守标准而闻名。可能是这样VS中的一个bug。