Read file line by line using ifstream in C++
The contents of file.txt are:
5 3
6 4
7 1
10 5
11 6
12 3
12 4
Where 5 3
is a coordinate pair.
How do I process this data line by line in C++?
I am able to get the first line, but how do I get the next line of the file?
ifstream myfile;
myfile.open ("text.txt");
c++ file-io ofstream
add a comment |
The contents of file.txt are:
5 3
6 4
7 1
10 5
11 6
12 3
12 4
Where 5 3
is a coordinate pair.
How do I process this data line by line in C++?
I am able to get the first line, but how do I get the next line of the file?
ifstream myfile;
myfile.open ("text.txt");
c++ file-io ofstream
add a comment |
The contents of file.txt are:
5 3
6 4
7 1
10 5
11 6
12 3
12 4
Where 5 3
is a coordinate pair.
How do I process this data line by line in C++?
I am able to get the first line, but how do I get the next line of the file?
ifstream myfile;
myfile.open ("text.txt");
c++ file-io ofstream
The contents of file.txt are:
5 3
6 4
7 1
10 5
11 6
12 3
12 4
Where 5 3
is a coordinate pair.
How do I process this data line by line in C++?
I am able to get the first line, but how do I get the next line of the file?
ifstream myfile;
myfile.open ("text.txt");
c++ file-io ofstream
c++ file-io ofstream
edited Sep 6 '18 at 0:08
jww
52.9k39226495
52.9k39226495
asked Oct 23 '11 at 20:24
dukevindukevin
7,562246698
7,562246698
add a comment |
add a comment |
7 Answers
7
active
oldest
votes
First, make an ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
The two standard methods are:
Assume that every line consists of two numbers and read token by token:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
Line-based parsing, using string streams:
#include <sstream>
#include <string>
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)
}
You shouldn't mix (1) and (2), since the token-based parsing doesn't gobble up newlines, so you may end up with spurious empty lines if you use getline()
after token-based extraction got you to the end of a line already.
12
Will solution #1 work with commas as the token?
– stackptr
Oct 18 '14 at 14:18
6
the OP used a space to delimit the two integers. I wanted to know if while (infile >> a >> b) would work if the OP used a as a comma a delimiter, because that is the scenario in my own program
– stackptr
Oct 18 '14 at 14:46
24
@EdwardKarak: Ah, so when you said "token" you meant "delimiter". Right. With a comma, you'd say:int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
– Kerrek SB
Oct 18 '14 at 15:25
11
@MarkH: Are you sure?
– Kerrek SB
Jan 6 '15 at 9:00
9
@KerrekSB: Huh. I was wrong. I didn't know it could do that. I might have some code of my own to rewrite.
– Mark H
Jan 6 '15 at 15:00
|
show 17 more comments
Use ifstream
to read data from a file:
std::ifstream input( "filename.ext" );
If you really need to read line by line, then do this:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
But you probably just need to extract coordinate pairs:
int x, y;
input >> x >> y;
Update:
In your code you use ofstream myfile;
, however the o
in ofstream
stands for output
. If you want to read from the file (input) use ifstream
. If you want to both read and write use fstream
.
7
Your solution is a bit improved: your line variable is not visible after file read-in in contrast to Kerrek SB's second solution which is good and simple solution too.
– DanielTuzes
Jul 23 '13 at 14:24
3
getline
is instring
see, so don't forget the#include <string>
– mxmlnkn
Jul 12 '17 at 23:02
add a comment |
Reading a file line by line in C++ can be done in some different ways.
[Fast] Loop with std::getline()
The simplest approach is to open an std::ifstream and loop using std::getline() calls. The code is clean and easy to understand.
#include <fstream>
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();
}
[Fast] Use Boost's file_description_source
Another possibility is to use the Boost library, but the code gets a bit more verbose. The performance is quite similar to the code above (Loop with std::getline()).
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>
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 <io::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();
}
}
}
[Fastest] Use C code
If performance is critical for your software, you may consider using the C language. This code can be 4-5 times faster than the C++ versions above, see benchmark below
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);
Benchmark -- Which one is faster?
I have done some performance benchmarks with the code above and the results are interesting. I have tested the code with ASCII files that contain 100,000 lines, 1,000,000 lines and 10,000,000 lines of text. Each line of text contains 10 words in average. The program is compiled with -O3
optimization and its output is forwarded to /dev/null
in order to remove the logging time variable from the measurement. Last, but not least, each piece of code logs each line with the printf()
function for consistency.
The results show the time (in ms) that each piece of code took to read the files.
The performance difference between the two C++ approaches is minimal and shouldn't make any difference in practice. The performance of the C code is what makes the benchmark impressive and can be a game changer in terms of speed.
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms
What happens if you remove C++'s synchronization with C on the console outputs? You might be measuring a known disadvantage of the default behavior ofstd::cout
vsprintf
.
– user4581301
Jul 30 '18 at 20:41
1
Thanks for bringing this concern. I've redone the tests and the performance is still the same. I have edited the code to use theprintf()
function in all cases for consistency. I have also tried usingstd::cout
in all cases and this made absolutely no difference. As I have just described in the text, the output of the program goes to/dev/null
so the time to print the lines is not measured.
– HugoTeixeira
Jul 31 '18 at 2:11
4
Groovy. Thanks. Wonder where the slowdown is.
– user4581301
Jul 31 '18 at 4:34
add a comment |
Since your coordinates belong together as pairs, why not write a struct for them?
struct CoordinatePair
{
int x;
int y;
};
Then you can write an overloaded extraction operator for istreams:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
is >> coordinates.x >> coordinates.y;
return is;
}
And then you can read a file of coordinates straight into a vector like this:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
char filename = "coordinates.txt";
std::vector<CoordinatePair> v;
std::ifstream ifs(filename);
if (ifs) {
std::copy(std::istream_iterator<CoordinatePair>(ifs),
std::istream_iterator<CoordinatePair>(),
std::back_inserter(v));
}
else {
std::cerr << "Couldn't open " << filename << " for readingn";
}
// Now you can work with the contents of v
}
1
What happens when it's not possible to read twoint
tokens from the stream inoperator>>
? How can one make it work with a backtracking parser (i.e. whenoperator>>
fails, roll back the stream to previous position end return false or something like that)?
– fferri
Dec 1 '16 at 13:31
If it's not possible to read twoint
tokens, then theis
stream will evaluate tofalse
and the reading loop will terminate at that point. You can detect this withinoperator>>
by checking the return value of the individual reads. If you want to roll back the stream, you would callis.clear()
.
– Martin Broadhurst
Jan 7 '17 at 14:10
in theoperator>>
it is more correct to sayis >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
since otherwise you are assuming that your input stream is in the whitespace-skipping mode.
– Darko Veberic
Mar 27 '17 at 17:55
add a comment |
Expanding on the accepted answer, if the input is:
1,NYC
2,ABQ
...
you will still be able to apply the same logic, like this:
#include <fstream>
std::ifstream infile("thefile.txt");
if (infile.is_open()) {
int number;
std::string str;
char c;
while (infile >> number >> c >> str && c == ',')
std::cout << number << " " << str << "n";
}
infile.close();
add a comment |
Although there is no need to close the file manually but it is good idea to do so if the scope of the file variable is bigger:
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
add a comment |
with command line arguments:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include "print.h"
using namespace std;
int main (int argc, char *argv)
{
vector<string> list;
ifstream in_stream;
string line;
in_stream.open(argv[1]);
while(!in_stream.eof())
{
in_stream >> line;
list.push_back(line);
}
in_stream.close();
print(list);
sort(list.begin(), list.end());
print(list);
}
37
while (!file.eof())
is wrong.
– 0x499602D2
Oct 27 '13 at 16:46
7
Good, but it will fail in many other cases. It's better to dowhile (in_stream >> line)
.
– 0x499602D2
Dec 11 '13 at 19:03
1
I would suggest using getline here also. The above delimits the input based on any whitespaces which may not be desired while getline() has default delimiter 'n'
– Anirudh
Jun 23 '14 at 11:07
4
To explainwhile(!in_stream.eof())
: say the last line contains "12 4n" (per question), when your loop's>> line
reads"4"
, it will recognise then
as white-space delimiting the value"4"
and stop with the input position at that final newline, but will not yet have tried to go beyond the newline;eof()
will not have been set. So, when yourwhile
loop testseof()
it thinks there's more input, callsin_stream >> line;
again but you don't test for the failure: in C++03line
is unspecified, in C++11 I think""
. Either way, youpush_back
one repeat or garbage string.
– Tony Delroy
May 28 '15 at 10:07
2
Please fix the broken loop oneof()
: stackoverflow.com/questions/5605125/… In addition to looping oneof()
you don't bother to check if your read succeeds before putting its value in the vector.
– Galik
Jun 19 '15 at 23:34
|
show 2 more comments
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
First, make an ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
The two standard methods are:
Assume that every line consists of two numbers and read token by token:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
Line-based parsing, using string streams:
#include <sstream>
#include <string>
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)
}
You shouldn't mix (1) and (2), since the token-based parsing doesn't gobble up newlines, so you may end up with spurious empty lines if you use getline()
after token-based extraction got you to the end of a line already.
12
Will solution #1 work with commas as the token?
– stackptr
Oct 18 '14 at 14:18
6
the OP used a space to delimit the two integers. I wanted to know if while (infile >> a >> b) would work if the OP used a as a comma a delimiter, because that is the scenario in my own program
– stackptr
Oct 18 '14 at 14:46
24
@EdwardKarak: Ah, so when you said "token" you meant "delimiter". Right. With a comma, you'd say:int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
– Kerrek SB
Oct 18 '14 at 15:25
11
@MarkH: Are you sure?
– Kerrek SB
Jan 6 '15 at 9:00
9
@KerrekSB: Huh. I was wrong. I didn't know it could do that. I might have some code of my own to rewrite.
– Mark H
Jan 6 '15 at 15:00
|
show 17 more comments
First, make an ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
The two standard methods are:
Assume that every line consists of two numbers and read token by token:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
Line-based parsing, using string streams:
#include <sstream>
#include <string>
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)
}
You shouldn't mix (1) and (2), since the token-based parsing doesn't gobble up newlines, so you may end up with spurious empty lines if you use getline()
after token-based extraction got you to the end of a line already.
12
Will solution #1 work with commas as the token?
– stackptr
Oct 18 '14 at 14:18
6
the OP used a space to delimit the two integers. I wanted to know if while (infile >> a >> b) would work if the OP used a as a comma a delimiter, because that is the scenario in my own program
– stackptr
Oct 18 '14 at 14:46
24
@EdwardKarak: Ah, so when you said "token" you meant "delimiter". Right. With a comma, you'd say:int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
– Kerrek SB
Oct 18 '14 at 15:25
11
@MarkH: Are you sure?
– Kerrek SB
Jan 6 '15 at 9:00
9
@KerrekSB: Huh. I was wrong. I didn't know it could do that. I might have some code of my own to rewrite.
– Mark H
Jan 6 '15 at 15:00
|
show 17 more comments
First, make an ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
The two standard methods are:
Assume that every line consists of two numbers and read token by token:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
Line-based parsing, using string streams:
#include <sstream>
#include <string>
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)
}
You shouldn't mix (1) and (2), since the token-based parsing doesn't gobble up newlines, so you may end up with spurious empty lines if you use getline()
after token-based extraction got you to the end of a line already.
First, make an ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
The two standard methods are:
Assume that every line consists of two numbers and read token by token:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
Line-based parsing, using string streams:
#include <sstream>
#include <string>
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)
}
You shouldn't mix (1) and (2), since the token-based parsing doesn't gobble up newlines, so you may end up with spurious empty lines if you use getline()
after token-based extraction got you to the end of a line already.
edited Mar 28 '12 at 6:57
Michael Mrozek
116k17146153
116k17146153
answered Oct 23 '11 at 20:34
Kerrek SBKerrek SB
365k61687920
365k61687920
12
Will solution #1 work with commas as the token?
– stackptr
Oct 18 '14 at 14:18
6
the OP used a space to delimit the two integers. I wanted to know if while (infile >> a >> b) would work if the OP used a as a comma a delimiter, because that is the scenario in my own program
– stackptr
Oct 18 '14 at 14:46
24
@EdwardKarak: Ah, so when you said "token" you meant "delimiter". Right. With a comma, you'd say:int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
– Kerrek SB
Oct 18 '14 at 15:25
11
@MarkH: Are you sure?
– Kerrek SB
Jan 6 '15 at 9:00
9
@KerrekSB: Huh. I was wrong. I didn't know it could do that. I might have some code of my own to rewrite.
– Mark H
Jan 6 '15 at 15:00
|
show 17 more comments
12
Will solution #1 work with commas as the token?
– stackptr
Oct 18 '14 at 14:18
6
the OP used a space to delimit the two integers. I wanted to know if while (infile >> a >> b) would work if the OP used a as a comma a delimiter, because that is the scenario in my own program
– stackptr
Oct 18 '14 at 14:46
24
@EdwardKarak: Ah, so when you said "token" you meant "delimiter". Right. With a comma, you'd say:int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
– Kerrek SB
Oct 18 '14 at 15:25
11
@MarkH: Are you sure?
– Kerrek SB
Jan 6 '15 at 9:00
9
@KerrekSB: Huh. I was wrong. I didn't know it could do that. I might have some code of my own to rewrite.
– Mark H
Jan 6 '15 at 15:00
12
12
Will solution #1 work with commas as the token?
– stackptr
Oct 18 '14 at 14:18
Will solution #1 work with commas as the token?
– stackptr
Oct 18 '14 at 14:18
6
6
the OP used a space to delimit the two integers. I wanted to know if while (infile >> a >> b) would work if the OP used a as a comma a delimiter, because that is the scenario in my own program
– stackptr
Oct 18 '14 at 14:46
the OP used a space to delimit the two integers. I wanted to know if while (infile >> a >> b) would work if the OP used a as a comma a delimiter, because that is the scenario in my own program
– stackptr
Oct 18 '14 at 14:46
24
24
@EdwardKarak: Ah, so when you said "token" you meant "delimiter". Right. With a comma, you'd say:
int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
– Kerrek SB
Oct 18 '14 at 15:25
@EdwardKarak: Ah, so when you said "token" you meant "delimiter". Right. With a comma, you'd say:
int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
– Kerrek SB
Oct 18 '14 at 15:25
11
11
@MarkH: Are you sure?
– Kerrek SB
Jan 6 '15 at 9:00
@MarkH: Are you sure?
– Kerrek SB
Jan 6 '15 at 9:00
9
9
@KerrekSB: Huh. I was wrong. I didn't know it could do that. I might have some code of my own to rewrite.
– Mark H
Jan 6 '15 at 15:00
@KerrekSB: Huh. I was wrong. I didn't know it could do that. I might have some code of my own to rewrite.
– Mark H
Jan 6 '15 at 15:00
|
show 17 more comments
Use ifstream
to read data from a file:
std::ifstream input( "filename.ext" );
If you really need to read line by line, then do this:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
But you probably just need to extract coordinate pairs:
int x, y;
input >> x >> y;
Update:
In your code you use ofstream myfile;
, however the o
in ofstream
stands for output
. If you want to read from the file (input) use ifstream
. If you want to both read and write use fstream
.
7
Your solution is a bit improved: your line variable is not visible after file read-in in contrast to Kerrek SB's second solution which is good and simple solution too.
– DanielTuzes
Jul 23 '13 at 14:24
3
getline
is instring
see, so don't forget the#include <string>
– mxmlnkn
Jul 12 '17 at 23:02
add a comment |
Use ifstream
to read data from a file:
std::ifstream input( "filename.ext" );
If you really need to read line by line, then do this:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
But you probably just need to extract coordinate pairs:
int x, y;
input >> x >> y;
Update:
In your code you use ofstream myfile;
, however the o
in ofstream
stands for output
. If you want to read from the file (input) use ifstream
. If you want to both read and write use fstream
.
7
Your solution is a bit improved: your line variable is not visible after file read-in in contrast to Kerrek SB's second solution which is good and simple solution too.
– DanielTuzes
Jul 23 '13 at 14:24
3
getline
is instring
see, so don't forget the#include <string>
– mxmlnkn
Jul 12 '17 at 23:02
add a comment |
Use ifstream
to read data from a file:
std::ifstream input( "filename.ext" );
If you really need to read line by line, then do this:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
But you probably just need to extract coordinate pairs:
int x, y;
input >> x >> y;
Update:
In your code you use ofstream myfile;
, however the o
in ofstream
stands for output
. If you want to read from the file (input) use ifstream
. If you want to both read and write use fstream
.
Use ifstream
to read data from a file:
std::ifstream input( "filename.ext" );
If you really need to read line by line, then do this:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
But you probably just need to extract coordinate pairs:
int x, y;
input >> x >> y;
Update:
In your code you use ofstream myfile;
, however the o
in ofstream
stands for output
. If you want to read from the file (input) use ifstream
. If you want to both read and write use fstream
.
edited Jul 7 '12 at 18:04
answered Oct 23 '11 at 20:32
K-balloK-ballo
68.5k19125153
68.5k19125153
7
Your solution is a bit improved: your line variable is not visible after file read-in in contrast to Kerrek SB's second solution which is good and simple solution too.
– DanielTuzes
Jul 23 '13 at 14:24
3
getline
is instring
see, so don't forget the#include <string>
– mxmlnkn
Jul 12 '17 at 23:02
add a comment |
7
Your solution is a bit improved: your line variable is not visible after file read-in in contrast to Kerrek SB's second solution which is good and simple solution too.
– DanielTuzes
Jul 23 '13 at 14:24
3
getline
is instring
see, so don't forget the#include <string>
– mxmlnkn
Jul 12 '17 at 23:02
7
7
Your solution is a bit improved: your line variable is not visible after file read-in in contrast to Kerrek SB's second solution which is good and simple solution too.
– DanielTuzes
Jul 23 '13 at 14:24
Your solution is a bit improved: your line variable is not visible after file read-in in contrast to Kerrek SB's second solution which is good and simple solution too.
– DanielTuzes
Jul 23 '13 at 14:24
3
3
getline
is in string
see, so don't forget the #include <string>
– mxmlnkn
Jul 12 '17 at 23:02
getline
is in string
see, so don't forget the #include <string>
– mxmlnkn
Jul 12 '17 at 23:02
add a comment |
Reading a file line by line in C++ can be done in some different ways.
[Fast] Loop with std::getline()
The simplest approach is to open an std::ifstream and loop using std::getline() calls. The code is clean and easy to understand.
#include <fstream>
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();
}
[Fast] Use Boost's file_description_source
Another possibility is to use the Boost library, but the code gets a bit more verbose. The performance is quite similar to the code above (Loop with std::getline()).
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>
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 <io::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();
}
}
}
[Fastest] Use C code
If performance is critical for your software, you may consider using the C language. This code can be 4-5 times faster than the C++ versions above, see benchmark below
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);
Benchmark -- Which one is faster?
I have done some performance benchmarks with the code above and the results are interesting. I have tested the code with ASCII files that contain 100,000 lines, 1,000,000 lines and 10,000,000 lines of text. Each line of text contains 10 words in average. The program is compiled with -O3
optimization and its output is forwarded to /dev/null
in order to remove the logging time variable from the measurement. Last, but not least, each piece of code logs each line with the printf()
function for consistency.
The results show the time (in ms) that each piece of code took to read the files.
The performance difference between the two C++ approaches is minimal and shouldn't make any difference in practice. The performance of the C code is what makes the benchmark impressive and can be a game changer in terms of speed.
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms
What happens if you remove C++'s synchronization with C on the console outputs? You might be measuring a known disadvantage of the default behavior ofstd::cout
vsprintf
.
– user4581301
Jul 30 '18 at 20:41
1
Thanks for bringing this concern. I've redone the tests and the performance is still the same. I have edited the code to use theprintf()
function in all cases for consistency. I have also tried usingstd::cout
in all cases and this made absolutely no difference. As I have just described in the text, the output of the program goes to/dev/null
so the time to print the lines is not measured.
– HugoTeixeira
Jul 31 '18 at 2:11
4
Groovy. Thanks. Wonder where the slowdown is.
– user4581301
Jul 31 '18 at 4:34
add a comment |
Reading a file line by line in C++ can be done in some different ways.
[Fast] Loop with std::getline()
The simplest approach is to open an std::ifstream and loop using std::getline() calls. The code is clean and easy to understand.
#include <fstream>
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();
}
[Fast] Use Boost's file_description_source
Another possibility is to use the Boost library, but the code gets a bit more verbose. The performance is quite similar to the code above (Loop with std::getline()).
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>
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 <io::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();
}
}
}
[Fastest] Use C code
If performance is critical for your software, you may consider using the C language. This code can be 4-5 times faster than the C++ versions above, see benchmark below
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);
Benchmark -- Which one is faster?
I have done some performance benchmarks with the code above and the results are interesting. I have tested the code with ASCII files that contain 100,000 lines, 1,000,000 lines and 10,000,000 lines of text. Each line of text contains 10 words in average. The program is compiled with -O3
optimization and its output is forwarded to /dev/null
in order to remove the logging time variable from the measurement. Last, but not least, each piece of code logs each line with the printf()
function for consistency.
The results show the time (in ms) that each piece of code took to read the files.
The performance difference between the two C++ approaches is minimal and shouldn't make any difference in practice. The performance of the C code is what makes the benchmark impressive and can be a game changer in terms of speed.
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms
What happens if you remove C++'s synchronization with C on the console outputs? You might be measuring a known disadvantage of the default behavior ofstd::cout
vsprintf
.
– user4581301
Jul 30 '18 at 20:41
1
Thanks for bringing this concern. I've redone the tests and the performance is still the same. I have edited the code to use theprintf()
function in all cases for consistency. I have also tried usingstd::cout
in all cases and this made absolutely no difference. As I have just described in the text, the output of the program goes to/dev/null
so the time to print the lines is not measured.
– HugoTeixeira
Jul 31 '18 at 2:11
4
Groovy. Thanks. Wonder where the slowdown is.
– user4581301
Jul 31 '18 at 4:34
add a comment |
Reading a file line by line in C++ can be done in some different ways.
[Fast] Loop with std::getline()
The simplest approach is to open an std::ifstream and loop using std::getline() calls. The code is clean and easy to understand.
#include <fstream>
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();
}
[Fast] Use Boost's file_description_source
Another possibility is to use the Boost library, but the code gets a bit more verbose. The performance is quite similar to the code above (Loop with std::getline()).
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>
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 <io::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();
}
}
}
[Fastest] Use C code
If performance is critical for your software, you may consider using the C language. This code can be 4-5 times faster than the C++ versions above, see benchmark below
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);
Benchmark -- Which one is faster?
I have done some performance benchmarks with the code above and the results are interesting. I have tested the code with ASCII files that contain 100,000 lines, 1,000,000 lines and 10,000,000 lines of text. Each line of text contains 10 words in average. The program is compiled with -O3
optimization and its output is forwarded to /dev/null
in order to remove the logging time variable from the measurement. Last, but not least, each piece of code logs each line with the printf()
function for consistency.
The results show the time (in ms) that each piece of code took to read the files.
The performance difference between the two C++ approaches is minimal and shouldn't make any difference in practice. The performance of the C code is what makes the benchmark impressive and can be a game changer in terms of speed.
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms
Reading a file line by line in C++ can be done in some different ways.
[Fast] Loop with std::getline()
The simplest approach is to open an std::ifstream and loop using std::getline() calls. The code is clean and easy to understand.
#include <fstream>
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();
}
[Fast] Use Boost's file_description_source
Another possibility is to use the Boost library, but the code gets a bit more verbose. The performance is quite similar to the code above (Loop with std::getline()).
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>
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 <io::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();
}
}
}
[Fastest] Use C code
If performance is critical for your software, you may consider using the C language. This code can be 4-5 times faster than the C++ versions above, see benchmark below
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);
Benchmark -- Which one is faster?
I have done some performance benchmarks with the code above and the results are interesting. I have tested the code with ASCII files that contain 100,000 lines, 1,000,000 lines and 10,000,000 lines of text. Each line of text contains 10 words in average. The program is compiled with -O3
optimization and its output is forwarded to /dev/null
in order to remove the logging time variable from the measurement. Last, but not least, each piece of code logs each line with the printf()
function for consistency.
The results show the time (in ms) that each piece of code took to read the files.
The performance difference between the two C++ approaches is minimal and shouldn't make any difference in practice. The performance of the C code is what makes the benchmark impressive and can be a game changer in terms of speed.
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms
edited Jul 31 '18 at 2:03
answered Jul 28 '18 at 14:35
HugoTeixeiraHugoTeixeira
2,4952921
2,4952921
What happens if you remove C++'s synchronization with C on the console outputs? You might be measuring a known disadvantage of the default behavior ofstd::cout
vsprintf
.
– user4581301
Jul 30 '18 at 20:41
1
Thanks for bringing this concern. I've redone the tests and the performance is still the same. I have edited the code to use theprintf()
function in all cases for consistency. I have also tried usingstd::cout
in all cases and this made absolutely no difference. As I have just described in the text, the output of the program goes to/dev/null
so the time to print the lines is not measured.
– HugoTeixeira
Jul 31 '18 at 2:11
4
Groovy. Thanks. Wonder where the slowdown is.
– user4581301
Jul 31 '18 at 4:34
add a comment |
What happens if you remove C++'s synchronization with C on the console outputs? You might be measuring a known disadvantage of the default behavior ofstd::cout
vsprintf
.
– user4581301
Jul 30 '18 at 20:41
1
Thanks for bringing this concern. I've redone the tests and the performance is still the same. I have edited the code to use theprintf()
function in all cases for consistency. I have also tried usingstd::cout
in all cases and this made absolutely no difference. As I have just described in the text, the output of the program goes to/dev/null
so the time to print the lines is not measured.
– HugoTeixeira
Jul 31 '18 at 2:11
4
Groovy. Thanks. Wonder where the slowdown is.
– user4581301
Jul 31 '18 at 4:34
What happens if you remove C++'s synchronization with C on the console outputs? You might be measuring a known disadvantage of the default behavior of
std::cout
vs printf
.– user4581301
Jul 30 '18 at 20:41
What happens if you remove C++'s synchronization with C on the console outputs? You might be measuring a known disadvantage of the default behavior of
std::cout
vs printf
.– user4581301
Jul 30 '18 at 20:41
1
1
Thanks for bringing this concern. I've redone the tests and the performance is still the same. I have edited the code to use the
printf()
function in all cases for consistency. I have also tried using std::cout
in all cases and this made absolutely no difference. As I have just described in the text, the output of the program goes to /dev/null
so the time to print the lines is not measured.– HugoTeixeira
Jul 31 '18 at 2:11
Thanks for bringing this concern. I've redone the tests and the performance is still the same. I have edited the code to use the
printf()
function in all cases for consistency. I have also tried using std::cout
in all cases and this made absolutely no difference. As I have just described in the text, the output of the program goes to /dev/null
so the time to print the lines is not measured.– HugoTeixeira
Jul 31 '18 at 2:11
4
4
Groovy. Thanks. Wonder where the slowdown is.
– user4581301
Jul 31 '18 at 4:34
Groovy. Thanks. Wonder where the slowdown is.
– user4581301
Jul 31 '18 at 4:34
add a comment |
Since your coordinates belong together as pairs, why not write a struct for them?
struct CoordinatePair
{
int x;
int y;
};
Then you can write an overloaded extraction operator for istreams:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
is >> coordinates.x >> coordinates.y;
return is;
}
And then you can read a file of coordinates straight into a vector like this:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
char filename = "coordinates.txt";
std::vector<CoordinatePair> v;
std::ifstream ifs(filename);
if (ifs) {
std::copy(std::istream_iterator<CoordinatePair>(ifs),
std::istream_iterator<CoordinatePair>(),
std::back_inserter(v));
}
else {
std::cerr << "Couldn't open " << filename << " for readingn";
}
// Now you can work with the contents of v
}
1
What happens when it's not possible to read twoint
tokens from the stream inoperator>>
? How can one make it work with a backtracking parser (i.e. whenoperator>>
fails, roll back the stream to previous position end return false or something like that)?
– fferri
Dec 1 '16 at 13:31
If it's not possible to read twoint
tokens, then theis
stream will evaluate tofalse
and the reading loop will terminate at that point. You can detect this withinoperator>>
by checking the return value of the individual reads. If you want to roll back the stream, you would callis.clear()
.
– Martin Broadhurst
Jan 7 '17 at 14:10
in theoperator>>
it is more correct to sayis >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
since otherwise you are assuming that your input stream is in the whitespace-skipping mode.
– Darko Veberic
Mar 27 '17 at 17:55
add a comment |
Since your coordinates belong together as pairs, why not write a struct for them?
struct CoordinatePair
{
int x;
int y;
};
Then you can write an overloaded extraction operator for istreams:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
is >> coordinates.x >> coordinates.y;
return is;
}
And then you can read a file of coordinates straight into a vector like this:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
char filename = "coordinates.txt";
std::vector<CoordinatePair> v;
std::ifstream ifs(filename);
if (ifs) {
std::copy(std::istream_iterator<CoordinatePair>(ifs),
std::istream_iterator<CoordinatePair>(),
std::back_inserter(v));
}
else {
std::cerr << "Couldn't open " << filename << " for readingn";
}
// Now you can work with the contents of v
}
1
What happens when it's not possible to read twoint
tokens from the stream inoperator>>
? How can one make it work with a backtracking parser (i.e. whenoperator>>
fails, roll back the stream to previous position end return false or something like that)?
– fferri
Dec 1 '16 at 13:31
If it's not possible to read twoint
tokens, then theis
stream will evaluate tofalse
and the reading loop will terminate at that point. You can detect this withinoperator>>
by checking the return value of the individual reads. If you want to roll back the stream, you would callis.clear()
.
– Martin Broadhurst
Jan 7 '17 at 14:10
in theoperator>>
it is more correct to sayis >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
since otherwise you are assuming that your input stream is in the whitespace-skipping mode.
– Darko Veberic
Mar 27 '17 at 17:55
add a comment |
Since your coordinates belong together as pairs, why not write a struct for them?
struct CoordinatePair
{
int x;
int y;
};
Then you can write an overloaded extraction operator for istreams:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
is >> coordinates.x >> coordinates.y;
return is;
}
And then you can read a file of coordinates straight into a vector like this:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
char filename = "coordinates.txt";
std::vector<CoordinatePair> v;
std::ifstream ifs(filename);
if (ifs) {
std::copy(std::istream_iterator<CoordinatePair>(ifs),
std::istream_iterator<CoordinatePair>(),
std::back_inserter(v));
}
else {
std::cerr << "Couldn't open " << filename << " for readingn";
}
// Now you can work with the contents of v
}
Since your coordinates belong together as pairs, why not write a struct for them?
struct CoordinatePair
{
int x;
int y;
};
Then you can write an overloaded extraction operator for istreams:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
is >> coordinates.x >> coordinates.y;
return is;
}
And then you can read a file of coordinates straight into a vector like this:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
char filename = "coordinates.txt";
std::vector<CoordinatePair> v;
std::ifstream ifs(filename);
if (ifs) {
std::copy(std::istream_iterator<CoordinatePair>(ifs),
std::istream_iterator<CoordinatePair>(),
std::back_inserter(v));
}
else {
std::cerr << "Couldn't open " << filename << " for readingn";
}
// Now you can work with the contents of v
}
answered Aug 20 '16 at 16:58
Martin BroadhurstMartin Broadhurst
7,84522229
7,84522229
1
What happens when it's not possible to read twoint
tokens from the stream inoperator>>
? How can one make it work with a backtracking parser (i.e. whenoperator>>
fails, roll back the stream to previous position end return false or something like that)?
– fferri
Dec 1 '16 at 13:31
If it's not possible to read twoint
tokens, then theis
stream will evaluate tofalse
and the reading loop will terminate at that point. You can detect this withinoperator>>
by checking the return value of the individual reads. If you want to roll back the stream, you would callis.clear()
.
– Martin Broadhurst
Jan 7 '17 at 14:10
in theoperator>>
it is more correct to sayis >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
since otherwise you are assuming that your input stream is in the whitespace-skipping mode.
– Darko Veberic
Mar 27 '17 at 17:55
add a comment |
1
What happens when it's not possible to read twoint
tokens from the stream inoperator>>
? How can one make it work with a backtracking parser (i.e. whenoperator>>
fails, roll back the stream to previous position end return false or something like that)?
– fferri
Dec 1 '16 at 13:31
If it's not possible to read twoint
tokens, then theis
stream will evaluate tofalse
and the reading loop will terminate at that point. You can detect this withinoperator>>
by checking the return value of the individual reads. If you want to roll back the stream, you would callis.clear()
.
– Martin Broadhurst
Jan 7 '17 at 14:10
in theoperator>>
it is more correct to sayis >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
since otherwise you are assuming that your input stream is in the whitespace-skipping mode.
– Darko Veberic
Mar 27 '17 at 17:55
1
1
What happens when it's not possible to read two
int
tokens from the stream in operator>>
? How can one make it work with a backtracking parser (i.e. when operator>>
fails, roll back the stream to previous position end return false or something like that)?– fferri
Dec 1 '16 at 13:31
What happens when it's not possible to read two
int
tokens from the stream in operator>>
? How can one make it work with a backtracking parser (i.e. when operator>>
fails, roll back the stream to previous position end return false or something like that)?– fferri
Dec 1 '16 at 13:31
If it's not possible to read two
int
tokens, then the is
stream will evaluate to false
and the reading loop will terminate at that point. You can detect this within operator>>
by checking the return value of the individual reads. If you want to roll back the stream, you would call is.clear()
.– Martin Broadhurst
Jan 7 '17 at 14:10
If it's not possible to read two
int
tokens, then the is
stream will evaluate to false
and the reading loop will terminate at that point. You can detect this within operator>>
by checking the return value of the individual reads. If you want to roll back the stream, you would call is.clear()
.– Martin Broadhurst
Jan 7 '17 at 14:10
in the
operator>>
it is more correct to say is >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
since otherwise you are assuming that your input stream is in the whitespace-skipping mode.– Darko Veberic
Mar 27 '17 at 17:55
in the
operator>>
it is more correct to say is >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
since otherwise you are assuming that your input stream is in the whitespace-skipping mode.– Darko Veberic
Mar 27 '17 at 17:55
add a comment |
Expanding on the accepted answer, if the input is:
1,NYC
2,ABQ
...
you will still be able to apply the same logic, like this:
#include <fstream>
std::ifstream infile("thefile.txt");
if (infile.is_open()) {
int number;
std::string str;
char c;
while (infile >> number >> c >> str && c == ',')
std::cout << number << " " << str << "n";
}
infile.close();
add a comment |
Expanding on the accepted answer, if the input is:
1,NYC
2,ABQ
...
you will still be able to apply the same logic, like this:
#include <fstream>
std::ifstream infile("thefile.txt");
if (infile.is_open()) {
int number;
std::string str;
char c;
while (infile >> number >> c >> str && c == ',')
std::cout << number << " " << str << "n";
}
infile.close();
add a comment |
Expanding on the accepted answer, if the input is:
1,NYC
2,ABQ
...
you will still be able to apply the same logic, like this:
#include <fstream>
std::ifstream infile("thefile.txt");
if (infile.is_open()) {
int number;
std::string str;
char c;
while (infile >> number >> c >> str && c == ',')
std::cout << number << " " << str << "n";
}
infile.close();
Expanding on the accepted answer, if the input is:
1,NYC
2,ABQ
...
you will still be able to apply the same logic, like this:
#include <fstream>
std::ifstream infile("thefile.txt");
if (infile.is_open()) {
int number;
std::string str;
char c;
while (infile >> number >> c >> str && c == ',')
std::cout << number << " " << str << "n";
}
infile.close();
edited Nov 25 '17 at 22:18
answered May 18 '17 at 9:35
gsamarasgsamaras
51.1k24100186
51.1k24100186
add a comment |
add a comment |
Although there is no need to close the file manually but it is good idea to do so if the scope of the file variable is bigger:
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
add a comment |
Although there is no need to close the file manually but it is good idea to do so if the scope of the file variable is bigger:
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
add a comment |
Although there is no need to close the file manually but it is good idea to do so if the scope of the file variable is bigger:
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
Although there is no need to close the file manually but it is good idea to do so if the scope of the file variable is bigger:
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
answered May 1 '18 at 20:11
Vijay BansalVijay Bansal
20325
20325
add a comment |
add a comment |
with command line arguments:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include "print.h"
using namespace std;
int main (int argc, char *argv)
{
vector<string> list;
ifstream in_stream;
string line;
in_stream.open(argv[1]);
while(!in_stream.eof())
{
in_stream >> line;
list.push_back(line);
}
in_stream.close();
print(list);
sort(list.begin(), list.end());
print(list);
}
37
while (!file.eof())
is wrong.
– 0x499602D2
Oct 27 '13 at 16:46
7
Good, but it will fail in many other cases. It's better to dowhile (in_stream >> line)
.
– 0x499602D2
Dec 11 '13 at 19:03
1
I would suggest using getline here also. The above delimits the input based on any whitespaces which may not be desired while getline() has default delimiter 'n'
– Anirudh
Jun 23 '14 at 11:07
4
To explainwhile(!in_stream.eof())
: say the last line contains "12 4n" (per question), when your loop's>> line
reads"4"
, it will recognise then
as white-space delimiting the value"4"
and stop with the input position at that final newline, but will not yet have tried to go beyond the newline;eof()
will not have been set. So, when yourwhile
loop testseof()
it thinks there's more input, callsin_stream >> line;
again but you don't test for the failure: in C++03line
is unspecified, in C++11 I think""
. Either way, youpush_back
one repeat or garbage string.
– Tony Delroy
May 28 '15 at 10:07
2
Please fix the broken loop oneof()
: stackoverflow.com/questions/5605125/… In addition to looping oneof()
you don't bother to check if your read succeeds before putting its value in the vector.
– Galik
Jun 19 '15 at 23:34
|
show 2 more comments
with command line arguments:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include "print.h"
using namespace std;
int main (int argc, char *argv)
{
vector<string> list;
ifstream in_stream;
string line;
in_stream.open(argv[1]);
while(!in_stream.eof())
{
in_stream >> line;
list.push_back(line);
}
in_stream.close();
print(list);
sort(list.begin(), list.end());
print(list);
}
37
while (!file.eof())
is wrong.
– 0x499602D2
Oct 27 '13 at 16:46
7
Good, but it will fail in many other cases. It's better to dowhile (in_stream >> line)
.
– 0x499602D2
Dec 11 '13 at 19:03
1
I would suggest using getline here also. The above delimits the input based on any whitespaces which may not be desired while getline() has default delimiter 'n'
– Anirudh
Jun 23 '14 at 11:07
4
To explainwhile(!in_stream.eof())
: say the last line contains "12 4n" (per question), when your loop's>> line
reads"4"
, it will recognise then
as white-space delimiting the value"4"
and stop with the input position at that final newline, but will not yet have tried to go beyond the newline;eof()
will not have been set. So, when yourwhile
loop testseof()
it thinks there's more input, callsin_stream >> line;
again but you don't test for the failure: in C++03line
is unspecified, in C++11 I think""
. Either way, youpush_back
one repeat or garbage string.
– Tony Delroy
May 28 '15 at 10:07
2
Please fix the broken loop oneof()
: stackoverflow.com/questions/5605125/… In addition to looping oneof()
you don't bother to check if your read succeeds before putting its value in the vector.
– Galik
Jun 19 '15 at 23:34
|
show 2 more comments
with command line arguments:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include "print.h"
using namespace std;
int main (int argc, char *argv)
{
vector<string> list;
ifstream in_stream;
string line;
in_stream.open(argv[1]);
while(!in_stream.eof())
{
in_stream >> line;
list.push_back(line);
}
in_stream.close();
print(list);
sort(list.begin(), list.end());
print(list);
}
with command line arguments:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include "print.h"
using namespace std;
int main (int argc, char *argv)
{
vector<string> list;
ifstream in_stream;
string line;
in_stream.open(argv[1]);
while(!in_stream.eof())
{
in_stream >> line;
list.push_back(line);
}
in_stream.close();
print(list);
sort(list.begin(), list.end());
print(list);
}
edited Oct 31 '15 at 12:55
hrust
5031825
5031825
answered Jun 21 '12 at 21:53
Alex SpencerAlex Spencer
54811021
54811021
37
while (!file.eof())
is wrong.
– 0x499602D2
Oct 27 '13 at 16:46
7
Good, but it will fail in many other cases. It's better to dowhile (in_stream >> line)
.
– 0x499602D2
Dec 11 '13 at 19:03
1
I would suggest using getline here also. The above delimits the input based on any whitespaces which may not be desired while getline() has default delimiter 'n'
– Anirudh
Jun 23 '14 at 11:07
4
To explainwhile(!in_stream.eof())
: say the last line contains "12 4n" (per question), when your loop's>> line
reads"4"
, it will recognise then
as white-space delimiting the value"4"
and stop with the input position at that final newline, but will not yet have tried to go beyond the newline;eof()
will not have been set. So, when yourwhile
loop testseof()
it thinks there's more input, callsin_stream >> line;
again but you don't test for the failure: in C++03line
is unspecified, in C++11 I think""
. Either way, youpush_back
one repeat or garbage string.
– Tony Delroy
May 28 '15 at 10:07
2
Please fix the broken loop oneof()
: stackoverflow.com/questions/5605125/… In addition to looping oneof()
you don't bother to check if your read succeeds before putting its value in the vector.
– Galik
Jun 19 '15 at 23:34
|
show 2 more comments
37
while (!file.eof())
is wrong.
– 0x499602D2
Oct 27 '13 at 16:46
7
Good, but it will fail in many other cases. It's better to dowhile (in_stream >> line)
.
– 0x499602D2
Dec 11 '13 at 19:03
1
I would suggest using getline here also. The above delimits the input based on any whitespaces which may not be desired while getline() has default delimiter 'n'
– Anirudh
Jun 23 '14 at 11:07
4
To explainwhile(!in_stream.eof())
: say the last line contains "12 4n" (per question), when your loop's>> line
reads"4"
, it will recognise then
as white-space delimiting the value"4"
and stop with the input position at that final newline, but will not yet have tried to go beyond the newline;eof()
will not have been set. So, when yourwhile
loop testseof()
it thinks there's more input, callsin_stream >> line;
again but you don't test for the failure: in C++03line
is unspecified, in C++11 I think""
. Either way, youpush_back
one repeat or garbage string.
– Tony Delroy
May 28 '15 at 10:07
2
Please fix the broken loop oneof()
: stackoverflow.com/questions/5605125/… In addition to looping oneof()
you don't bother to check if your read succeeds before putting its value in the vector.
– Galik
Jun 19 '15 at 23:34
37
37
while (!file.eof())
is wrong.– 0x499602D2
Oct 27 '13 at 16:46
while (!file.eof())
is wrong.– 0x499602D2
Oct 27 '13 at 16:46
7
7
Good, but it will fail in many other cases. It's better to do
while (in_stream >> line)
.– 0x499602D2
Dec 11 '13 at 19:03
Good, but it will fail in many other cases. It's better to do
while (in_stream >> line)
.– 0x499602D2
Dec 11 '13 at 19:03
1
1
I would suggest using getline here also. The above delimits the input based on any whitespaces which may not be desired while getline() has default delimiter 'n'
– Anirudh
Jun 23 '14 at 11:07
I would suggest using getline here also. The above delimits the input based on any whitespaces which may not be desired while getline() has default delimiter 'n'
– Anirudh
Jun 23 '14 at 11:07
4
4
To explain
while(!in_stream.eof())
: say the last line contains "12 4n" (per question), when your loop's >> line
reads "4"
, it will recognise the n
as white-space delimiting the value "4"
and stop with the input position at that final newline, but will not yet have tried to go beyond the newline; eof()
will not have been set. So, when your while
loop tests eof()
it thinks there's more input, calls in_stream >> line;
again but you don't test for the failure: in C++03 line
is unspecified, in C++11 I think ""
. Either way, you push_back
one repeat or garbage string.– Tony Delroy
May 28 '15 at 10:07
To explain
while(!in_stream.eof())
: say the last line contains "12 4n" (per question), when your loop's >> line
reads "4"
, it will recognise the n
as white-space delimiting the value "4"
and stop with the input position at that final newline, but will not yet have tried to go beyond the newline; eof()
will not have been set. So, when your while
loop tests eof()
it thinks there's more input, calls in_stream >> line;
again but you don't test for the failure: in C++03 line
is unspecified, in C++11 I think ""
. Either way, you push_back
one repeat or garbage string.– Tony Delroy
May 28 '15 at 10:07
2
2
Please fix the broken loop on
eof()
: stackoverflow.com/questions/5605125/… In addition to looping on eof()
you don't bother to check if your read succeeds before putting its value in the vector.– Galik
Jun 19 '15 at 23:34
Please fix the broken loop on
eof()
: stackoverflow.com/questions/5605125/… In addition to looping on eof()
you don't bother to check if your read succeeds before putting its value in the vector.– Galik
Jun 19 '15 at 23:34
|
show 2 more comments