C++文件读取末尾空行问题

起因是做gitlet读取文件内容时遇到的内容不匹配错误,后来发现是自己读取文件内容时均使用getline函数,写回时读入的每个字符串都加上换行符,导致文件末尾可能多出换行符。

于是改成了

vector<string> Blob::readContentsForBlob(const string& file){
    vector<string> content;
    ifstream fin(file);
    string line;
    // 这样读取可以知道末尾是不是有空行,保证了读取内容一致
    while(!fin.eof()){
        getline(fin, line);
        content.push_back(line);
    }
    fin.close();
    return content;
}

通过返回值最后一项是否为空字符串来判断是否有空行。

平时没有注意过这个问题,于是试着读取其他数据

文件内容

类型一,末尾无空行

1
2
3

类型二,末尾有空行

1
2
3

int读取

以下代码为通常oj题目中读取方式,可以看到类型一和类型二的输出是一样的。

ifstream fin("file.txt");
int n;
while(fin >> n){
    cout<<n<<"-";
}
fin.close();

而以下代码则可以区分类型一和类型二

while(!fin.eof()){
    fin>>n;
    cout<<n<<"-";
}

输出分别为

1-2-3-
1-2-3-3-

对于eof函数,文件实际有效内容读完后,有空行和无空行的结果是不一样的,前者true,会再次进入读取,但是读取失败;后者false,不会再次进入读取。

字符读取

但通过字符输入时,两种代码在末尾无空行时的输出均为

1-2-3-

有空行时输出均为

1-2-3-3-

这是int和char的读取造成的,int要预先看到下一个字符,因此eof函数的判断会提前,而char则不会。

string读取

通过string直接输入时

string s;
while(!fin.eof()){
    fin >> s;
    cout << s << "-";
}

情况和int一样,也是因为string结束要提前读到下一个字符。

string使用getline输入时

string s;
while(getline(fin, s)){
    cout << s << "-";
}

只会读完所有有效行。

综上,只读取所有有效数据时(无论是否有空行),直接使用

while(fin >> n) ...
while(getline(fin, s)) ...
while(fin >> s) ...
while(fin >> ch) ...

如果想判断是否有空行,使用eof函数时即可,这时候一般只在整行读取时使用,方法见文章起始代码。

posted @ 2024-02-25 15:47  trashwin  阅读(82)  评论(0编辑  收藏  举报