C++ EOF与GCC 5.2.1上的基本ios::EOF()
在使用GCC 5.2.1编译的程序上,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)的计
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。