reset streampos pointer

I open a file and run through it to see how many lines it has. Then i want to reset the position pointer and start over at the beginning. I have code that accomplishes the reset, but it's ugly. I would like to understand why and if there's a better way.

Here's code that works.

ifstream inputFile(FileName,ios::in);
i=0;
streampos strmPos, strmBeg; //stream pointers
strmBeg = inputFile.tellg();
inputFile.getline(inputBuffer,200);
do
{
inputFile.getline(inputBuffer,200);
i++;
}while(!inputFile.eof());

Uint iNumRows = i;
inputFile.seekg(strmBeg);
inputFile.seekg(strmBeg);
strmPos = inputFile.tellg();

Notice the 2nd and 3rd line up from the bottom are exactly the same. With only one seekg(strmBeg) it does not reset properly. The first call resets _Myoff from -1 (error condition) to 0, but does not reset _Fpos. The second call resets _Fpos. (_Myoff and _Fpos are members of streampos)

This works but seems kinda ugly. What is going on? Is there a better way to do this?
Something like this should work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ifstream fin( FileName );
if( !fin ){
    //Handle error
}

size_t numLines = 0;
string str;
while( getline( fin, str )){
    ++numLines;
}

fin.clear(); // clear bad state after eof
fin.seekg( 0 );

// Should be readable again from beginning. 

It shouldn't work at all. [edit] mikebow's shouldn't work... [/edit]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
using namespace std;

...

ifstream inputFile( FileName );
inputFile >> noskipws;

unsigned long linecount = count(
  istream_iterator <char> ( inputFile ),
  istream_iterator <char> (),
  '\n'
  ) +1;

inputFile.clear();  // this is what you missed...
inputFile.seekg( 0 );

// now you can read from the file normally
...

Don't forget, when you hit EOF or any other error, inputFile.good() is no longer true... you must reset it to good before you mess with it more.

Hope this helps.
Last edited on
guys,
thanks so much. your code is sooo much cleaner than mine. completely resolves my question and gives me something to aspire to.
Duoas:

unsigned long linecount = count(
istream_iterator <char> ( inputFile ),
istream_iterator <char> (),
'\n'
) +1;

You don't want the +1 there.

I'd like to recommend my code as not only more flexible (you could ignore blank lines easily, for instance), but as also possibly faster!
Hammurabi
Bull, and Bull.

Where do y'all get this crap?


1. The number of lines in a file **is** number of newlines plus one.
If you want to start quibbling about the number of lines you want to consider countable, then that is entirely different.

2. How could playing with a string every line be faster than simply counting occurrences of a given character?

The only advantage your technique has over mine is that you can play with the individual lines of text -- which requires you to actually look at them. Were that the OP's intention, then I would have suggested exactly what you did.

So don't be arrogant.
In normal human communication, if I put the following into a file with a newline after each, I would have a file with 3 lines in it. There's no "quibbling" about it.

1
2
3
one
two
three


So don't be arrogant.

I assume you're talking to yourself there, since I certainly was not "arrogant"!!!

(You really are in a bad mood today.)

EDIT: A quit timing shows that "my" code (I would say the simple code) beats "your" code by just a bit, as I suspected.
Last edited on
Hammurabi: I agree with Duoas (about the line counting). If you're putting a linebreak after each, you have 4 lines, not 3. It's only 3 if you ignore the last (empty) line.

1
2
3
4
one
two
three
 


This is how virtually every text editor on the planet counts lines. While this may not be how it is in "normal human communication", it certainly is how it is in "normal computer line counting communication", and is expected behavior pretty much everywhere.
Last edited on
By your reasoning an empty file has one line, which may not be the behavior the OP is looking for. But as always it depends on the specifics of the app.
It is arrogant of you to tell me what I mean.
It is arrogant of you to make broad claims of superiority without any data to support it.
Arrogance comes from presumption -- which you did a lot of. BTW, I really don't like that 'edit' button.


However, I concede that the string version is significantly faster. This stumped me a bit, but it seems that it is simply that the fstream can read individual characters faster than the user using int fstream::get() can.

I can only get comparable performance using fstream::getline(). I have no idea what is going on behind the scenes to make a char-by-char read so slow for the programmer but not for the STL...

Alas.
It is arrogant of you to tell me what I mean.

You are truly insane. I did no such thing.

It is arrogant of you to make broad claims of superiority without any data to support it.

I didn't do that either. I said exactly this: "I'd like to recommend my code as not only more flexible (you could ignore blank lines easily, for instance), but as also possibly faster!" Notice the word "possibly"?

BTW, I really don't like that 'edit' button.

This suggests that I changed something, which I did not. I merely added the timing result.

The only reason I can think of for you to have exploded like a 14-year-old is that I sent you a PM about a missing brace in some code from one of your previous posts, which you arrogantly ignored.

And talk about arrogance and lack of data:
The only advantage your technique has over mine is that you can play with the individual lines of text


It is pathetic that people like Duoas cannot simply admit when they've been an idiot. I'm still waiting for your apology for your unprovoked attack in this thread.
Last edited on
Now, now, fellas, can we get back on topic?

By your reasoning an empty file has one line
It does! Hit ctrl+N on Notepad++ or any other text editor with line numbers on the margin and see for yourself.

This is mainly a classic fence post error. Newlines are not line terminators, they are line separators. Notice the term "new line"; they represent the beginning of a new line (the BOF is the first beginning of line). Compare the following strings:
One line:
(BOF)""
One line:
(BOF)"string"

Two lines:
(BOF)"string"
"\n"

Two lines:
(BOF)"string"
"\nstring"

Three lines:
(BOF)"string"
"\nstring"
"\n"


As for the performance difference, I'd blame the iterators' overhead. Have you tried reading the whole stream into a buffer and using pointers?
Last edited on
Sorry helios and mikebow...

Hammurabi -- I took your comments as an unprovoked attack. I'll admit I was a bit testy, but your language is inflammatory. You addressed it directly at me. Geez.

1) "You don't want the +1 there." -- This isn't telling me what I meant to write?
2) Adding the word "possibly" means nothing. Either prove your method is superior (which I have already kindly conceded to you) or don't make claims about code superiority.
3) PM - read the stupid thread again. Shall I change it back to remove thanks for your PM?

I've been reconciliatory enough. But here again: thanks for showing me what a loser, unenlightened programmer I am and how poorly I respond to "unprovoked attacks". Sorry I acted like a 14-year old. I'm off to get a life.


Fooey.

I really am sorry for exploding. I don't take negative commentary well -- it is something I am still working on personally. I've been having a lot of stress lately and it just occurred to me that I've misread Hammurabi's post as a personal offense: "Duoas: you meant this and my code is better."

Alas, now I do feel about two inches tall.
I feel bad now too. Rereading the thread I see what you mean, but I really didn't mean anything by it. It was kind of like saying "let's race", which is what I should've said. It wasn't a personal challenge in any sense, and I was just lazy not doing the timings before posting.

And I guess counting lines is not as straightforward as I thought. If a newline always indicates another (even if empty) line, then obviously the number of newlines + 1 is correct. One might add a special case, however, to count a file of zero size as having zero lines.
Yay! We both feel bad!
/me stupid sheepish grin

We could race, but I've already timed them. You win by a factor of 5 to 7 1/2. LOL.
I'm learning the hard way that STL algorithms aren't always the best answer...
Topic archived. No new replies allowed.