Introduction to Programming with c++ 13-3 文件结束符的一点小问题

问题

讲一个书上提到的关于文件结束符处理的小问题,之前没有注意过这个点。
问题也很简单:从一组文件里面读取数字并求和。

//scores.txt 注意:5后面有一个空格
1 2 3 4 5

考虑如下代码实现:

#include <iostream>
#include <fstream>
int main( void )
{
    std::ifstream fin;
    fin.open( "scores.txt" );
    if( !fin.is_open() )
    {
        std::cerr << "Can not open the file!" << std::endl;
        return -1;
    }

    int val = 0;
    int sum = 0;
    while( !fin.eof() )
    {
        fin >> val;
        sum += val;
    }
    std::cout << "Total is " << sum << std::endl;
    fin.close();
    return 0;
}

思路

程序应该输出15,但是却输出了20。这是什么原因?并且程序的逻辑看起来是没有错误的。
但是对于输入文件而言,如果删除掉5后面的空格。发现程序正确。
所以,问题可能就出在5后面的空格上面。因为,当5读取结束之后,此时,文件是没有到结束符的。还是会继续读取,但是由于读取空格到整型变量val中会出现问题,所以fin的状态会失效。并不会覆盖之前的val值。所以,又被累加了一遍,这才得到20。

所以,如果要用eof来判断文件是否结束,应该避免文件的结束符是诸如空格这样的字符。
虽然文件没有读取完毕,但是这并不是有效的输入。这点注意。
对于上面问题的修正,可以采取如下的方法:

#include <iostream>
#include <fstream>
int main( void )
{
    std::ifstream fin;
    fin.open( "scores.txt" );
    if( !fin.is_open() )
    {
        std::cerr << "Can not open the file!" << std::endl;
        return -1;
    }

    int val = 0;
    int sum = 0;
    while( !fin.eof() )
    {
        fin >> val;
        if( fin ) // 判断一下是否正确读取
        {
            sum += val;
        }
    }
    std::cout << "Total is " << sum << std::endl;
    fin.close();
    return 0;
}

或者,由于fin对象在读取到非数字的变量时会返回NULL。也就是说可以用fin >> val来当做文件读取结束的条件。因为,如果没有这个空格。当fin读取到eof的时候,还是会返回NULL。从而可以判断循环结束。

#include <iostream>
#include <fstream>
int main( void )
{
    std::ifstream fin;
    fin.open( "scores.txt" );
    if( !fin.is_open() )
    {
        std::cerr << "Can not open the file!" << std::endl;
        return -1;
    }

    int val = 0;
    int sum = 0;
    while( fin >> val )
    {
            sum += val;
    }
    std::cout << "Total is " << sum << std::endl;
    fin.close();
    return 0;
}

再或者,可以先把整个文件结尾的空白符都处理掉,然后使用第一种办法也是可以的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值