EOF vs basic_ios::eof() on GCC 5.2.1
EOF vs basic_ios::eof() on GCC 5.2.1
在使用GCC 5.2.1编译的程序中,当ifstream
到达文件结尾时,其状态不会切换到basic_ios::eof()
——即,条件if(eof())
在到达文件结尾后计算为false
——而在Visual Studio 2015上编译的相同代码的行为与预期一致:当到达文件末尾时,basic_ios::eof()
在if
条件中计算为true
。
我先用if(bad())
代替if(eof())
,然后用if(fail())
代替,并将它们全部评定为false
。然而,当我放置EOF
宏时,if(EOF)
的求值结果为true
——就像在由VS编译的程序上使用if(eof())
一样。
std::basic_ios::eof()
不使用GCC编译的程序的原因是什么?
PS:下面是程序的代码
#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*)(tw+s*w*)(tw+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] << "tt" << accumBoys << "tt"
<< accumGirls << "tt" << 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();
}
school.txt
文件的文本
KLASSE DRENGE PIGER ELEVER
0A 12 11 23
1A 7 8 15
1B 4 11 15
2A 10 13 23
3A 10 12 22
4A 7 7 14
4B 10 5 15
5A 19 8 27
6A 10 9 19
6B 9 10 19
7A 7 19 26
7G 3 5 8
7I 7 3 10
8A 10 16 26
9A 12 15 27
0MO 3 2 5
0P1 1 1 2
0P2 0 5 5
10B 4 4 8
10CE 0 1 1
1MO 8 5 13
2CE 8 5 13
3DCE 3 3 6
4MO 4 1 5
6CE 3 4 7
8CE 4 4 8
9CE 4 9 13
REST 5 6 11
Alle klasser 184 202 386
EOF是一个常量整数的宏,因此
if (EOF && curr_boy == boys && curr_girl == girls)
正在"工作"。它只是并没有做你们期望的事情,也就是检查文件的末尾。
只有当io操作失败时,才应使用eof()
。文件规定
std::basic_ios::eof仅报告由最近的I/O操作。它不检查关联的数据源。例如,如果最近的I/O是一个get(),它返回了文件的最后一个字节,则eof()返回false。nextget()无法读取任何内容并设置eofbit。只有当eof()返回真正的时
在您的代码中,您有
while (getline(in, line)) {
...
if (in.eof())
...
}
预期行为是GCC的行为。要知道你已经到了文件的末尾,你应该尝试进一步阅读。这与类似
while (!in.eof()) {
...
getline(in, line)
...
}
您应该将curr_boy和条件移出while循环,并消除eof-test
int curr_boy = 0;
int curr_girl = 0;
while (getline(in, line)) {
}
if (curr_boy == boys && curr_girl == girls) { out << line; return 0; }
您是否在相同的操作系统中使用相同的文件?
如果getline
函数在看到'n'
之前到达文件末尾,它将设置eof
标志。这只能发生在文件的最后一行。
您可能应该将结束测试移动到while循环外部的,在那里我们知道,当最新的getline
未能读取另一行时,我们已经到达了文件的末尾。
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 奇怪的结构&GCC&clang(void*返回类型)
- GCC本机矩阵运算库
- 瓦尔格林德:数学函数"Conditional jump or move depends on uninitialised value(s)"
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- gcc和c++17的过载解析失败
- 数据成员SFINAE的C++17测试:gcc vs clang
- GCC对可能有效的代码抛出init list生存期警告
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 使用gcc从静态链接的文件中查找可选符号
- 普通环路未使用gcc 4.8.5自动矢量化
- 有了gcc,是否可以链接库,但前提是它存在
- 在clang++预处理器中确定gcc工具链版本
- How to recover system gcc compiler on centos 6
- EOF vs basic_ios::eof() on GCC 5.2.1
- InterlockedOr8 on gcc MinGW
- 在哪里可以获得英特尔的 Tbb for gcc on Windows
- flock-ing a C++ ifstream on Linux (GCC 4.6)