C++ File I/O while loop won't read till end of file

Started by
5 comments, last by blueloon 16 years, 9 months ago
This program reads in two .txt files, manipulates the numbers in them and outputs the result to the screen. the output is accurate but the problem is that both input files are 200+ pages long but the output is only about a hundred lines. If I delete the first few pages of one of the input .txt files and run the program again, I get different output but it still only continues for about 100 lines. the int res is just a feature where the numbers in each file won't be considered if their corresponding timestamps aren't within a few minutes of each other, and the program compares the next line in one file with the same line in the other file. here's example input from corrected.txt: 73.1817322 -145.9081573 20070323065959 73.1817169 -145.9082642 20070323071000 73.1817322 -145.9084015 20070323071958 and from walrus.txt 73.106343 -145.724085 20070317170032 73.106340 -145.724090 20070317170033 73.106363 -145.724057 20070317170034 and here's the program: #include <fstream> #include <iostream> #include <math.h> using namespace std; int main() { double longs1, longs2, lat1, lat2, time, referencetime, distance; double pi, dtor, hdlat, hdlon, rearth, small, dist, bear; pi = 3.141592653589793; dtor = pi/180.; rearth = 6356752.3; small = 0.00000000000001; int res = 120; ifstream in ("corrected.txt"); ifstream in2 ("walrus.txt"); cout << "timestamp" << " " << "distance (m)" << " " << "bearing (degrees from true north)" << '\n'; cout.precision(14); while (! in.eof()){ in >> lat1 >> longs1 >> referencetime; while (! in2.eof() ) { in2 >> lat2 >> longs2 >> time; //compute distance between 1 and 2 using haversine formula double latr = (lat1-lat2)*dtor; double longr = (longs1-longs2)*dtor; double a = asin(sin(latr/2)*sin(latr/2)+cos(lat1*dtor)*cos(lat2*dtor)*sin(longr/2)*sin(longr/2)); double c; if (a < 0) { c = sqrt(1-a); } else { c = sqrt(a); } double d = 2*rearth*c; bear = sin((90-lat2)*dtor)*sin((longs2-longs1)*dtor)/(sin(d)+small); bear = asin(bear); if (lat2 < lat1) { if (longs1 < longs2) bear = pi-bear; if (longs2 < longs1) bear = 0-pi-bear; } bear = bear/dtor; if (time < referencetime+res && time > referencetime-res) { cout << time << " " << d << " " << bear << '\n'; break; } else { } } } return 0; }
Advertisement
well, what happens is you read a value from the first file, in. Then you read every value from in2 and compare it against in until in2 reaches the end of file. Then you go back and read the next value from in. After that you enter the while loop only to find out that you are still at the end of the file. Yup, you never reset your position to the beginning of the file. That's probably your culprit.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Quote:Original post by nobodynews
well, what happens is you read a value from the first file, in. Then you read every value from in2 and compare it against in until in2 reaches the end of file. Then you go back and read the next value from in. After that you enter the while loop only to find out that you are still at the end of the file. Yup, you never reset your position to the beginning of the file. That's probably your culprit.


hmm, judging by initial test runs it would instead scan in2.txt until a timestamp within the resolution was found, then bump down to the next line in both in.txt and in2.txt and do likewise until eof, not repeatedly go through the entire in2.txt for every line in in.txt. shouldn't the break in

if (time < referencetime+res && time > referencetime-res) {

cout << time << " " << d << " " << bear << '\n';
break;
}

break the inner while loop?
Dont use while( !fstream.eof() ), as the end of file flag is only set *after* you read the end of the file. Prefer instead:

while (in >> lat1 >> longs1 >> referencetime){     while (in2 >> lat2 >> longs2 >> time ) {         // etc ...     }}


Note this forms primitive error checking too (did we read 3 objects successfully?).
Quote:Original post by blueloon
Quote:Original post by nobodynews
well, what happens is you read a value from the first file, in. Then you read every value from in2 and compare it against in until in2 reaches the end of file. Then you go back and read the next value from in. After that you enter the while loop only to find out that you are still at the end of the file. Yup, you never reset your position to the beginning of the file. That's probably your culprit.


hmm, judging by initial test runs it would instead scan in2.txt until a timestamp within the resolution was found, then bump down to the next line in both in.txt and in2.txt and do likewise until eof, not repeatedly go through the entire in2.txt for every line in in.txt. shouldn't the break in

if (time < referencetime+res && time > referencetime-res) {

cout << time << " " << d << " " << bear << '\n';
break;
}

break the inner while loop?


I didn't see that break statement, my mistake

edit: I still stand by my original response, mostly... I'm sure the reason you aren't getting a large output is because your conditions are too rare to occur. That is, the odds of two time stamps being that close together are pretty slim.

Look at the text file itself and do what the computer does, except only look at the time stamps. It reads the first time stamp from 'in' and then goes through 'in2' until it finds a time stamp within 120 minutes of 'in'. But there probably aren't many entries from 'walrus.txt' that are +-120 of 20070323065959 and the ones that Are... are probably near each other. Also, do the time stamps always increase, or is there some backtracking going on?

Think of this simple example where we check for +- 0.5:
position: 1    2    3    4    5    6    7    ...  48     ...  3481 (end)file 1:   0.6, 2.5, 2.8, 3.1, 3.9, 4.0, 4.6, ..., 203.9, ...  54.1file 2:   0.8, 0.9, 100, 130, 161, 192, 193, ..., 2.8,   ..., 200


Read in values form position 1 in both files, Match! Go to position 2, no match, so increase position of file 2. No match, increase position of file 2. No matches until file 1 is in position 2 and file 2 is in position 48 when file 1 finally goes to position 3. Eventually, file 2's position will be at 3481, but because it only found, say, 50 matches file 1 is only in position 50. Because file2 is in eof state, it never enters the inner while loop and you never compare anything again.

I don't know what you're actually hoping to achieve so I can't tell what you should change.



[Edited by - nobodynews on June 26, 2007 8:45:23 PM]

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

In the currently empty else part, you could output info about the data, that was not considered. Let's say: time, referencetime, res. Write it to another out stream or mark the then two types of output with different starting signs for easy scanning. That way you would better see what the filtering really does and then decide what needs to be fixed.
"Always code as if the guy who ends up maintaining, or testing your code will be a violent psychopath who knows where you live."
Quote:Original post by nobodynews
or is there some backtracking going on?


thanks for your help everybody, I've found the source of error and it wasn't the program. there was indeed some backtracking happening in the timestamps of one of the input files. this wasn't expected. basically, everything runs smooth when time moves forward top to bottom in both input files but the output stops when a timestamp jumps to an earlier value. luckily, fixing bugs in the input file algorithms isn't my problem!

This topic is closed to new replies.

Advertisement