什么';从C+;中的文件中读取行的首选模式+;? 我在C++教程中看到了至少两种从文件中读取线条的方法: std::ifstream fs("myfile.txt"); if (fs.is_open()) { while (fs.good()) { std::string line; std::getline(fs, line); // ...
以及: 当然,我可以添加一些检查以确保文件存在并已打开。除了异常处理之外,是否有理由选择更详细的第一种模式?你的标准做法是什么什么';从C+;中的文件中读取行的首选模式+;? 我在C++教程中看到了至少两种从文件中读取线条的方法: std::ifstream fs("myfile.txt"); if (fs.is_open()) { while (fs.good()) { std::string line; std::getline(fs, line); // ...,c++,file-io,C++,File Io,以及: 当然,我可以添加一些检查以确保文件存在并已打开。除了异常处理之外,是否有理由选择更详细的第一种模式?你的标准做法是什么 while (std::getline(fs, line)) {} 这不仅是正确的,而且更可取,因为它是惯用的。 我假设在第一种情况下,如果(!fs)中断,则在std::getline()as之后没有检查fs或类似的东西。因为如果你不这样做,那么第一个案例是完全错误的。或者,如果你这样做了,那么第二个仍然是可取的,因为它在逻辑上更简洁明了 函数good()应在尝试读取
while (std::getline(fs, line))
{}
这不仅是正确的,而且更可取,因为它是惯用的。
我假设在第一种情况下,如果(!fs)中断,则在std::getline()
as之后没有检查fs
代码>或类似的东西。因为如果你不这样做,那么第一个案例是完全错误的。或者,如果你这样做了,那么第二个仍然是可取的,因为它在逻辑上更简洁明了
函数good()
应在尝试读取流后使用;它用于检查尝试是否成功。在第一种情况下,您不会这样做。在std::getline()
之后,假设读取成功,甚至没有检查fs.good()
返回的内容。另外,您似乎假设如果fs.good()
返回true,std::getline
将成功地从流中读取一行。实际上,如果std::getline
成功地从流中读取一行,那么fs.good()
将返回true
cplusplus的文档中提到了这一点
如果未设置流的任何错误标志(eofbit、failbit和badbit),则函数返回true
也就是说,当您尝试从输入流读取数据时,如果尝试失败,则只会设置失败标志,good()
返回false
,作为失败的指示
如果要将行
变量的范围仅限于循环内部,则可以为
循环编写,如下所示:
for(std::string line; std::getline(fs, line); )
{
//use 'line'
}
注意:在阅读了@john的解决方案后,我想到了这个解决方案,但我认为它比他的版本好
请阅读此处的详细说明,说明为什么第二个选项更可取且更惯用:
或者读一下@Jerry Coffin写得很好的博客:
试试这个=>
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
//读取文本文件
#包括
#包括
#包括
使用名称空间std;
int main(){
弦线;
ifstream myfile(“example.txt”);
如果(myfile.is_open())
{
while(myfile.good())
{
getline(myfile,line);
cout第一个循环每次释放并重新分配字符串,浪费时间。
第二次将字符串写入已存在的空间,删除释放和重新分配,使其实际上比第一次更快(更好)。实际上,我更喜欢另一种方式
for (;;)
{
std::string line;
if (!getline(myFile, line))
break;
...
}
对我来说,它读起来更好,而且字符串的作用域正确(即,在使用它的循环内,而不是在循环外)
但是,在你写的两篇文章中,第二篇是正确的。把这看作是对纳瓦兹已经很好的答案的延伸评论
关于你的第一个选择
while (fs.good()) {
std::string line;
std::getline(fs, line);
...
这有多个问题。问题1是while
条件位于错误的位置并且是多余的。它位于错误的位置,因为fs.good()
表示最近对文件执行的操作是否正常。while条件应与即将进行的操作有关,而不是与以前的操作有关。无法知道对文件执行的即将进行的操作是否正常。什么即将进行的操作?fs.good()
不读取代码以查看即将执行的操作
第二个问题是,您忽略了来自std::getline()
的返回状态。如果您立即使用fs.good()
检查状态,这没关系。因此,请稍微解决一下
while (true) {
std::string line;
if (std::getline(fs, line)) {
...
}
else {
break;
}
}
可选地,如果(.STD::GETLINE(FS,LINE))中断,},但现在在循环的中间有一个<代码>中断/代码>,那么,如果可能的话,最好让退出条件成为循环语句本身的一部分。
与之相比
std::string line;
while (std::getline(fs, line)) {
...
}
这是从文件中读取行的标准习惯用法。C中也有一个非常类似的习惯用法。这个习惯用法非常古老,使用非常广泛,被广泛认为是从文件中读取行的正确方法
如果你来自一个禁止附带条件的商店?(有很多很多的编程标准都是这样做的)有一个方法可以绕过中间循环的中断:
std::string line;
for (std::getline(fs, line); fs.good(); std::getline(fs, line)) {
...
}
不像break方法那么难看,但大多数人都会同意,这并不像标准的习惯用法那么好看
我的建议是使用标准成语,除非某些标准禁止使用
附录
关于(std::getline(fs,line);fs.good();std::getline(fs,line))的:这很难看,有两个原因。一个是明显的复制代码块
<> P> >调用< <代码> GETLION>代码>然后>代码> Gue< /Calp>打破原子性。如果其他线程也从文件中读取,这又不是什么重要的事情,因为C++ I/O当前不是线程安全的。它将在即将到来的C++ 11中。ipe为灾难。yikes,谷歌给我带来的最大打击是:方法名good()是如何成为标准的?:@jda:函数good()
应该在您尝试读取流后使用;它用于检查尝试是否成功。在您的第一个例子中,您不会这样做。在std::getline()之后
,您假设读取成功,甚至没有检查fs.good()
返回的内容。此外,您似乎假设如果fs.good()
返回true,std::getline
将
std::string line;
for (std::getline(fs, line); fs.good(); std::getline(fs, line)) {
...
}