Explain the magic? Counting lines in a file

D

Dale Atkin

As part of a larger project, I need to be able to count the number of lines
in a file (so I know what to expect). Anyways, I came accross the following
code that seems to do the trick, the only thing is, I'm not 100% sure what
it is doing, or how.

#include<iostream>
#include<fstream>

main(int argc, char *argv[])
{
using namespace std;
ifstream fin(argv[1]);
int
numlines=count(istreambuf_iterator<char>(fin),istreambuf_iterator<char>(),
'\n');
cout << numlines;
}

I think I've managed to figure most of it out, but I'm not really sure.
First off, what does "using namespace std;" do? Please don't say it puts you
in to the standard name space, what I want to know is what namespace was I
in, and why do I want to be in the std namespace.
From what I can tell, the count function takes in a start position and an
end position (is this an address in memory or what does it take here), and a
delimeter, so would that make istreambuf_iterator<char>(fin) the begining
and istreambuf_interator<char>(), the end?
Does this make sense. The documentation I can find says that it is an
"Iterator that reads successive characters from the stream buffer for which
it was constructed", but what exactly is an iterator? How would one
generally use one? (sounds like it is something I should know about).
Is char the amount we're iterating by each time? would
istreambuf_iterator<double>(fin) make sense for a binary file full of
doubles (I don't happen to have one to test the behavior with)...

Also, a point on style, does one typically include the ".h" in the include
statement or not? I have been tending to, but most of the example code I
find doesn't have it (I know I don't need to, but will other people point at
my code and laugh at me if I do...)

Thanx,

Dale
 
M

Mike Wahler

Dale Atkin said:
As part of a larger project, I need to be able to count the number of lines
in a file (so I know what to expect). Anyways, I came accross the following
code that seems to do the trick, the only thing is, I'm not 100% sure what
it is doing, or how.

#include<iostream>
#include<fstream>

main(int argc, char *argv[])
{
using namespace std;
ifstream fin(argv[1]);
int
numlines=count(istreambuf_iterator<char>(fin),istreambuf_iterator<char>(),
'\n');
cout << numlines;
}

I think I've managed to figure most of it out, but I'm not really sure.
First off, what does "using namespace std;" do?

It causes the namespace 'std' to be included in name lookup.
Please don't say it puts you
in to the standard name space,

It doesn't.
what I want to know is what namespace was I
in,

Lacking any namespace definition or reference to one,
the namespace you're working with is the 'global namespace'.
and why do I want to be in the std namespace.

Namespace 'std' is where all the standard library names
(except macros) are declared.
From what I can tell, the count function takes in a start position and an
end position
Yes.

(is this an address in memory or what does it take here),

They're called 'iterators'.
and a
delimeter,

No delimiters are being used. The '\n' is the character
being searched for and counted.
so would that make istreambuf_iterator<char>(fin) the begining
and istreambuf_interator<char>(), the end?

Yes. Those iterators designate 'beginning of stream' and 'end of stream'
Does this make sense. The documentation I can find says that it is an
"Iterator that reads successive characters from the stream buffer for which
it was constructed", but what exactly is an iterator?

It a method of accessing containers or streams via a common
means.
How would one
generally use one?

It depends upon the type of iterator, and what you need to do.
(sounds like it is something I should know about).

Yes. You need some books. See www.accu.org for peer
reviews and recommendations.
Is char the amount we're iterating by each time?
Yes.

would
istreambuf_iterator<double>(fin) make sense for a binary file full of
doubles

It might. But it depends upon what you really need to do.
(I don't happen to have one to test the behavior with)...

Also, a point on style, does one typically include the ".h" in the include
statement or not?

Again, that depends. You can #include any text file you like,
regardless of its name. However, none of the standard headers, such as
I have been tending to, but most of the example code I
find doesn't have it (I know I don't need to, but will other people point at
my code and laugh at me if I do...)

Get some books, or imo you won't get far.

-Mike
 
R

Rolf Magnus

Dale said:
As part of a larger project, I need to be able to count the number of
lines in a file (so I know what to expect). Anyways, I came accross the
following code that seems to do the trick, the only thing is, I'm not 100%
sure what it is doing, or how.

#include<iostream>
#include<fstream>

main(int argc, char *argv[])

Your main() function is missing a return type.
{
using namespace std;
ifstream fin(argv[1]);
int
numlines=count(istreambuf_iterator<char>(fin),istreambuf_iterator<char>(),
'\n');
cout << numlines;
}

I think I've managed to figure most of it out, but I'm not really sure.
First off, what does "using namespace std;" do? Please don't say it puts
you in to the standard name space, what I want to know is what namespace
was I in, and why do I want to be in the std namespace.

You were (and still are) in the global namespace. "using namespace std;"
just means that the names from that namespace are now also available in the
current namespace, so e.g. instead of the need to fully qualify
std::ifstream, you can now just write ifstream, because that name was made
available in the global namespace.
From what I can tell, the count function takes in a start position and an
end position (is this an address in memory or what does it take here),

No, it's an iterator. Iterator types are special classes that usually belong
to container classes. Iterators are similar to pointers in usage, but they
point to a specific element of a container instead of to a specific memory
address. You can use them to iterate (hence the name) over a container by
incrementing them, just like you could use pointers to iterate over an
array by incrementing them.
Such iterators are used in most standard algorithms, so that you can use
them independant of the container type.
There are also iterators for streams, so you can use some of the standard
algorithms with them, too. std::count is one of those algorithms.
and a delimeter, so would that make istreambuf_iterator<char>(fin) the
begining and istreambuf_interator<char>(), the end?
Yes.

Does this make sense. The documentation I can find says that it is an
"Iterator that reads successive characters from the stream buffer for
which it was constructed", but what exactly is an iterator? How would one
generally use one? (sounds like it is something I should know about).

See above.
Is char the amount we're iterating by each time?
Yes.

would istreambuf_iterator<double>(fin) make sense for a binary file full
of doubles (I don't happen to have one to test the behavior with)...
Yes.

Also, a point on style, does one typically include the ".h" in the include
statement or not? I have been tending to, but most of the example code I
find doesn't have it (I know I don't need to, but will other people point
at my code and laugh at me if I do...)

It depends. You always have to provide the full name of the header, and in
the case of the C++ standard headers, those don't end in ".h". However,
most other headers do.
 
D

Dale Atkin

Your main() function is missing a return type.

Thanks, been a while since I've actually written anything in c++, and I'm
just trying to get back in to it.
You were (and still are) in the global namespace. "using namespace std;"
just means that the names from that namespace are now also available in
the
current namespace, so e.g. instead of the need to fully qualify
std::ifstream, you can now just write ifstream, because that name was made
available in the global namespace.

I see, that makes sense, thank you.
No, it's an iterator. Iterator types are special classes that usually
belong
to container classes. Iterators are similar to pointers in usage, but they
point to a specific element of a container instead of to a specific memory
address. You can use them to iterate (hence the name) over a container by
incrementing them, just like you could use pointers to iterate over an
array by incrementing them.
Such iterators are used in most standard algorithms, so that you can use
them independant of the container type.
There are also iterators for streams, so you can use some of the standard
algorithms with them, too. std::count is one of those algorithms.

Thanks, as you may have guessed, most of my background is non object
oriented.
It depends. You always have to provide the full name of the header, and in
the case of the C++ standard headers, those don't end in ".h". However,
most other headers do.

Ahhhh, that explains all those warning messages that I didn't understand,
and hadn't gotten around to figuring out :). Out of curiosity, how long have
the standard headers not had a .h on them?

Thanks for the help, I appreciate it.

Dale
 
D

Dale Atkin

It causes the namespace 'std' to be included in name lookup.

Ahhhhh, slight mis-interpretation on my part. Thank you.
Lacking any namespace definition or reference to one,
the namespace you're working with is the 'global namespace'.

That makes sense.
They're called 'iterators'.

Hence the name of the variable ;)
No delimiters are being used. The '\n' is the character
being searched for and counted.

Sorry I mis-spoke, my brain was on another function when I typed that (the
input I have has to be parsed once I bring it in)
It a method of accessing containers or streams via a common
means.

Makes sense, thank you.
Yes. You need some books. See www.accu.org for peer
reviews and recommendations.

Thanks, as you may have guess from my questions, most of my background is
only incidentally object oriented.
It might. But it depends upon what you really need to do.

Well I don't have anything I need to do, just hypothetical. So what would it
do?
Again, that depends. You can #include any text file you like,
regardless of its name. However, none of the standard headers, such as
<iostream> have .h in their names. Also note that standard headers
need not be actual files (but often are).

Thanks, guess it wasn't just a point of style after all. Thank you for
straightening that out for me.
Get some books, or imo you won't get far.

Actually, I've got some books, but what I've found is that generally I can
look the information up faster online than I can find it in my books
(perhaps they aren't the best books...)

Dale
 
M

Mike Wahler

Dale Atkin said:
Thanks, as you may have guess from my questions, most of my background is
only incidentally object oriented.

Nothing about the code you posted is specifically object-oriented.
Perhaps you're suffering from the same misconception as many:
that C++ is an inherently 'OO' language. It does have built-in
support for it, but doesn't require it. C++ can be and is used
for other than OO programs. Many C++ programs I've written don't
use OO at all. C++ is also often called a 'multi-paradigm language'.
Actually, I've got some books, but what I've found is that generally I can
look the information up faster online than I can find it in my books
(perhaps they aren't the best books...)

Beware, the bulk of the C++ info online is simply incorrect.
There are also many very poor C++ books out there. (Some
publishers seem to be simply trying to take advantage of the
current popularity of C++, but not placing much importance upon
correctness. Which books are you reading?

Anyway, I'm glad you found my remarks helpful.

And have you read the C++ FAQ?:
http://www.parashift.com/c++-faq-lite/
Lots of Good Stuff(tm).

-Mike
 
M

Mike Wahler

I restored the attribution above. It's considered polite to leave that in,
so folks can easily tell who said what.

Hmm, I missed that. Nice to have so many eyes watching all our code. :)
Ahhhh, that explains all those warning messages that I didn't understand,
and hadn't gotten around to figuring out :). Out of curiosity, how long have
the standard headers not had a .h on them?

Standard C++ (ratified in 1998) has never had headers with .h in their names
(except those inherited from C, and those are deprecated in favor of the
'new'
C headers, which have the .h dropped, and a letter 'c' prepended to their
names;
e.g. <stdio.h> is replaced with <cstdio>. Either one is valid, but the
latter
is recommended over the former.)

Pre-standard implementations of C++ did have .h in the header names.

-Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,278
Latest member
BuzzDefenderpro

Latest Threads

Top