c++语⾔循环读写⽂件夹,在C++中逐⾏读取⽂件的内容包括:
5 3
6 4
7 1
10 5
11 6
12 3
12 4
其中,5 3是⼀个坐标对。如何在C++中逐⾏处理此数据?
我可以得到第⼀⾏,但如何得到⽂件的下⼀⾏?
ifstream myfile;
myfile.open ("");
⾸先,制作⼀个ifstream:
#include
std::ifstream infile("");
两种标准⽅法是:
假设每⾏由两个数字组成,并逐个标记地读取:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
基于⾏的分析,使⽤字符串流:
#include
#include
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
int a, b;
if (!(iss >> a >> b)) { break; } // error
// process pair (a,b)
}
您不应该混合(1)和(2),因为基于令牌的解析不会吞掉新⾏,因此,如果在基于令牌的提取使您到达⾏的末尾之后使⽤getline(),则可能会以虚假的空⾏结束。
解决⽅案1是否将逗号作为令牌?
@爱德华德卡拉克:我不明⽩"象征性的逗号"是什么意思。逗号不代表整数。
OP⽤⼀个空格来分隔两个整数。我想知道如果操作a⽤作逗号a分隔符,while(infile>>a>>b)是否有效,因为这是我⾃⼰程序中的场景。
@爱德华:啊,所以当你说"令牌"时,你的意思是"分隔符"。正确的。⽤逗号,你会说:int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))。
@Kerreksb:只有逗号被空格包围,即"1,2",这才有效。如果⾏包含"1,2",那么代码将尝试将"1,2"转换为整数(存储在A中),⽽C和B将在下⼀⾏获得标记/分隔符。除了空⽩分隔符之外,您还需要使⽤std::getline()并解析该⾏。
@马克:你确定吗?
@凯瑞克:嗯。我错了。我不知道它能做到。我可能有⾃⼰的代码需要重写。
关于while(getline(f, line)) { }结构的解释和错误处理,请看这篇(我的)⽂章:gehrcke.de/2011/06/…(我认为我不需要良⼼不好地在这⾥发布这个,它甚⾄稍微提前了这个答案的⽇期)。
农民任务指挥部
@伽罗⽡:茅草屋顶:—)
好好享受你的冷饮吧
跳过""注释⾏的最佳⽅法是使⽤第⼀种或第⼆种⽅法?谢谢。
@Elgnoh:在第⼀种⽅法中不能这样做,它假定您正在解析令牌,并且不知道"⾏"是什么。第⼆种⽅法很简单,只需检查⾏字符串的第⼀个字符(可能跳过空⽩)。
@Kerreksb:我理解,在第⼀种⽅法中,请澄清⼀下,>>返回对stream对象的引⽤。所以问题是,当流到达EOF时,将返回什么使while循环中断。
@vivekmaran:流在读取数字以形成最后⼀个元素时达到eof。在下⼀轮中,没有剩余的数字,试图读取超过流结尾的数据会使流"失败",这是循环的退出条件。这是⼀个演⽰。
@Vivekmaran:如果你的阅读⽅式不是"提前阅读",就像把单个的字符拿出来,那么你永远不会触发EOF,直到你真正跨过流的末端:/permlink/ofayftnefucamv
@Kerreksb:谢谢你拿到了eof部分,刚刚发现直接使⽤ifstream进⾏条件检查会触发bool操作符,如果eof被击中会返回false,并导致循环中断。
@Vivekmaran:不,对!fail()进⾏布尔转换检查,⽽不是对good()进⾏布尔转换检查,这在处理eof时有所不同(见此处)。
@Kerreksb,如果我需要在使⽤getline()读取整⾏后逐个读取输⼊,该怎么办?我的意思是,在python语⾔中,我可以从⼀个列表(a.k.a 数组)中的⼀⾏⼀⾏地读取输⼊,然后我可以迭代这个列表,⼀次选择⼀个项⽬,然后做我想做的任何事情!我该如何处理C++中的这种情况?有什么建议吗?
@当然,您可以将每⼀⾏存储在⼀个容器中(例如std::vector),然后在循环完成后处理该容器。当然,这意味着在继续之前,您需要能够使⽤整个⽂件,例如,您不能以交互⽅式读取⾏。(但我希望在python中也是如此。)如果性能是⼀个问题,那么最好在⼀个步骤中将整个⽂件读取到内存中,然后只存储换⾏符的位置,例如作为std::vector,但如果这是性能瓶颈,我只会这样做。
@阿努:也许问⼀个新问题?
@Kerreksb,这是我要解决的问题?使⽤上⾯的帖⼦,但没有得到线索,怎么做?有什么建议吗?
⾮常适合我,谢谢!
使⽤ifstream从⽂件中读取数据:
std::ifstream input("" );
如果您确实需要逐⾏阅读,请执⾏以下操作:
for( std::string line; getline( input, line ); )
{
...for each line
}
但您可能只需要提取坐标对:
int x, y;
input >> x >> y;
更新:
在代码中使⽤ofstream myfile;,但是ofstream中的o代表output。如果要读取⽂件(输⼊),请使⽤ifstream。如果您既想读⼜想写,请使⽤fstream。
您的解决⽅案有点改进:与Kerrek SB的第⼆个解决⽅案相⽐,您的⾏变量在⽂件读取后是不可见的,这也是⼀个很好且简单的解决⽅案。
getline在string中,所以不要忘记#include。
在C++中逐⾏读取⽂件可以以不同的⽅式完成。[fast]使⽤std::getline()循环
最简单的⽅法是使⽤std::getline()调⽤打开std::ifstream并循环。代码清晰易懂。
#include
std::ifstream file(FILENAME);
if (file.is_open()) {
std::string line;
while (getline(file, line)) {
// using printf() in all tests for consistency
printf("%s", line.c_str());
}
file.close();
}python怎么读文件夹下的文件夹
[快速]使⽤Boost的⽂件描述源
另⼀种可能是使⽤Boost库,但是代码会变得更加冗长。性能与上⾯的代码⾮常相似(使⽤std::getline()循环)。
#include
#include
#include
namespace io = boost::iostreams;
void readLineByLineBoost() {
int fdr = open(FILENAME, O_RDONLY);
if (fdr >= 0) {
io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle);
io::stream <:file_descriptor_source> in(fdDevice);
if (fdDevice.is_open()) {
std::string line;
while (std::getline(in, line)) {
// using printf() in all tests for consistency
printf("%s", line.c_str());
}
fdDevice.close();
}
}
}
[最快]使⽤C代码
如果性能对软件⾄关重要,您可以考虑使⽤C语⾔。此代码可以⽐上⾯的C++版本快4-5倍,参见下⾯的基准
FILE* fp = fopen(FILENAME,"r");
if (fp == NULL)
exit(EXIT_FAILURE);
char* line = NULL;
size_t len = 0;
while ((getline(&line, &len, fp)) != -1) {
// using printf() in all tests for consistency
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
基准——哪个更快?
我⽤上⾯的代码做了⼀些性能基准测试,结果很有趣。我⽤包含100000⾏、1000000⾏和10000000
⾏⽂本的ASCII⽂件测试了代码。每⾏⽂本平均包含10个单词。该程序是⽤-O3优化编译的,其输出被转发到/dev/null以从测量中删除测井时间变量。最后,但并⾮最不重要的是,每段代码都⽤printf()函数记录每⼀⾏,以确保⼀致性。
结果显⽰每段代码读取⽂件所⽤的时间(毫秒)。
两种C++⽅法之间的性能差异很⼩,在实践中不应该有任何差别。C代码的性能使基准测试令⼈印象深刻,并且在速度⽅⾯可以改变游戏规则。
10K lines    100K lines    1000K lines
Loop with std::getline()        105ms          894ms          9773ms
Boost code                      106ms          968ms          9561ms
C code                            23ms          243ms          2397ms
如果在控制台输出中删除C++与C的同步会发⽣什么?您可能正在衡量std::cout与printf的默认⾏为的已知缺点。
谢谢你提出这个问题。我已经重做了测试,性能还是⼀样的。为了保持⼀致性,我对代码进⾏了编辑,以便在所有情况下使⽤printf()函数。我也尝试过在所有情况下使⽤std::cout,这完全没有区别。正如我刚才在本⽂中所描述的,程序的输出被发送到/dev/null,所以打印⾏的时间是不被测量的。
Groovy。谢谢。想知道经济减速在哪⾥。
Hi @ GoGoTeixeRea.我知道这是⼀个⽼线程,我试图复制您的结果,并且看不到C和C++ GITHUBCOM/SIMONSSO/RealFiffi基准之间的任何显著差异。
既然坐标是成对的,为什么不为它们编写⼀个结构呢?
struct CoordinatePair
{
int x;
int y;
};
然后可以为IStream编写重载的提取运算符:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
is >> coordinates.x >> coordinates.y;
return is;