要运行下面的程序,首先得创建一个包含数字的文本文件。为此,可以用使用文本编辑器(如用于编写源代码的文本编辑器)。假设该文件为名scores.txt,包含的内容如下:1
218 19 18.5 13.5 14
16 19.5 20 18 12 18.5
1 |
|
程序说明
该程序没有使用硬编码文件名,而是将用户提供的文件名存储到字符数组filename中,然后该数组用作open()的参数:1
inFile.open(fielname);
检查文件是否被打开至关重要。下面是一些可能出问题的地方:指定的文件可能不存在;文件可能位于另一个目录(文件夹)中;访问可能拒绝;用户可能输错了文件名或省略了文件扩展名。很多初学者花了大量的时间检查文件读取循环的哪里出了问题后,最终却发现问题在于程序没有打开文件。检查文件是否被成功打开可避免这种精力放在错误地方的情况发生。
需要注意的是文件读取循环的正确设计。读取文件时,有几点需要检查。
首先,程序读取文件时不应超过EOF。如果最后一次读取数据时遇到EOF,方法eof()将返回true。
其次,程序可能遇到类型不匹配的情况。例如,下面程序期望文件中只包含数字。如果最后一次读取操作中发生了类型不匹配的情况,方法fail()将返回true(如果遇到EOF,该方法也将返回true)。
最后,可能出现意外的问题,如文件受损或硬件故障。如果最后一次读取文件时发生了这样的问题,方法bad()将返回true。不要分别检查这些情况,一种更简单的方法是使用good()方法,该方法在没有发生任何错误时返回true:1
2
3
4while (inFile.good()) //while input good and not at EOF
{
...
}
然后,可以使用其他方法来确定循环终止的真正原因:1
2
3
4
5
6if (inFile.eof())
cout<<"Enter of file reached.\n";
else if (inFiel.fail())
cout<<"Input terminated by data mismatch .\n";
else
cout << "Input terminated for unknown reason.\n";
这些代码紧跟在循环的后面,用于判断循环为何停止。由于eof()只能判断是否到达EOF,而fail()可用于检查EOF和类型不匹配,因此上述代码首先判断是否到达EOF。这样,如果执行到了else if 测试,便可排除EOF,因此,如果fail()返回true,便可断定导致循环终止的原因是类型不匹配
。
方法good()指出最后一次读取输入的操作是否成功,这一点至关重要。这意味着应该在执行读取输入的操作后,立刻应用这种测试。为此,一种标方法是,在循环之前(首次执行循环前)放置一条输入语句,并在循环的末尾(下次执行循环测试之前)放置另一条输入语句:1
2
3
4
5
6
7// standard file-reading loop design
inFile >> value; //get first value
while (inFile.good()) //while input good and not at EOF
{
//loop body goes here
inFile >> value; //get next value
}
鉴于以下事实,可以对上述代码进行精简:表达式inFile>>value的结果为inFiel,而在需要一个bool值的情况下,inFile的结果为inFile.good(),即true或false。
因此,可以将两条输入语句用一条用作循环测试的输入语句
代替。也就是说,可以将上述循环结构替换为如下循环结构:1
2
3
4
5
6
7// abbreviated file-reading loop design
// omit pre-loop input
while (inFiel >> value) //read and test for success
{
//loop body goes here
// cmit end-of-loop input
}
这种设计仍然遵循了在测试前进行读取的规则,因此要计算表达式inFile >> value的值,程序必须首先试图将一个数字读取到value中。