-3

In part of my code, I am using push_back to form a vector from a txt file:

while (!layerf.eof()) {             
    for (int i=0; i<kl.nlyr+1; i++) {
        std::getline(layerf,line);
        depth = atof(line.c_str()) - kl.depth;
        hlyr.push_back(depth);
    }
}

Let say I input {1,2,3,4}.

later, I need to find a value given as zz lies between which two element of the above vector hlyr, using the following part:

std::vector<double>::iterator loc;

loc = std::upper_bound (hlyr.begin(), hlyr.end(), zz);

Now the problem is hlyr.end is giving me nonsense value, 2 e-98, which is like it has not been intialized! My vector size is fine, even when I look at the vector in "watch' window in visual studio everything is right, but vector end is something nonsense.

If I resize the above vector to 4 nothing changes. But if I resize to 3, it will delete the last cell from the vector, and then the vector.end() will show 4! It seems vector.end is pointing to one cell after vector.size!

Is there an easy fix? I want to use it with the find algorithm I have.

sabbahillel
  • 4,357
  • 1
  • 19
  • 36
MSN
  • 13
  • 2
  • 4
    http://en.cppreference.com/w/cpp/container/vector/end – juanchopanza Mar 09 '16 at 20:46
  • Yes, that's *exactly* what `std::vector::end` does! – BoBTFish Mar 09 '16 at 20:48
  • 2
    http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – Karoly Horvath Mar 09 '16 at 20:48
  • Your question makes it sound like you are using hlyr.end() outside of the upper_bound. You may need to show more code. – kfsone Mar 09 '16 at 21:01
  • Your use of the C++ standard library is wrong, as explained already. However, I'd like to add an advise: Most standard library implementations have a diagnostic mode which you should use for development. With that mode activated, you will pay a performance penalty but get various checks. Dereferencing past-the-end iterators is one error that gets detected by this diagnostic mode. – Ulrich Eckhardt Mar 09 '16 at 21:18

3 Answers3

2

end() on every STL collection is the iterator past the end of the collection; dereferencing it as you are doing is undefined behaviour.

You can do this to get an iterator to the last element in the vector, if the vector is not empty:

auto last = hylr.end();
--last;

If it is empty, more undefined behaviour!

"undefined behaviour" is standards-language for: you don't get to complain if it doesn't do what you want.

Phil Willoughby
  • 1,649
  • 12
  • 16
1

It is normal with iterators for end to reference an illegal element, this allows it to be used as a way to express "not in this container". It also allows you to write:

for (auto it = v.begin(); it != v.end(); it++)

if end was valid, you wouldn't be able to do the above.

In the case of a vector, it returns an iterator that references the first element beyond the end of the current vector. With your upper_bound call you simply need to check for end as an indicator that your value is above anything in the vector.

auto loc = std::upper_bound (hlyr.begin(), hlyr.end(), zz);
if (loc == hlyr.end())
    // there was nothing > zz in the vector
kfsone
  • 23,617
  • 2
  • 42
  • 74
-2

hi you can define the variable depondon type that you needed and save the (hlyr.push_back(depth);) in it for example: {int x = hlyr.push_back(depth); }