Segmentation fault trying to dereference an iterator - c++

I'm trying to find the maximum value of a vector using std::max_element. When I run the program I get a segmentation fault that I believe is to do with std::end going over the end of the vector? I've tried changing it to std::end(tempdata)-1) but to no avail.
auto max = std::max_element(std::begin(tempdata), std::end(tempdata));
std::ofstream maxcurrent("maxcurrent.txt", std::ios::app);
maxcurrent << v << std::setw(15) << *max << std::endl;
Having looked at this answer I don't see why mine isn't working.

It won't work when max is std::end(tempdata) which can occurs if your tempdata is empty.
Iterator to the greatest element in the range [first, last). If several elements in the range are equivalent to the greatest element, returns the iterator to the first such element. Returns last if the range is empty.
source

Related

Set_Intersection with repeated values

I think the set_intersection STL function described here: http://www.cplusplus.com/reference/algorithm/set_intersection/
is not really a set intersection in the mathematical sense. Suppose that the examples given I change the lines:
int first[] = {5,10,15,20,20,25};
int second[] = {50,40,30,20,10,20};
I would like to get 10 20 20 as a result. But I only get unique answers.
Is there a true set intersection in STL?
I know it's possible with a combination of merges and set_differences, btw. Just checking if I'm missing something obvious.
I would like to get 10 20 20 as a result. But I only get unique answers. Is there a true set intersection in STL?
std::set_intersection works how you want.
You probably get the wrong answer because you didn't update the code properly. If you change the sets to have 6 elements you need to update the lines that sort them:
std::sort (first,first+5); // should be first+6
std::sort (second,second+5); // should be second+6
And also change the call to set_intersection to use first+6 and second+6. Otherwise you only sort the first 5 elements of each set, and only get the intersection of the first 5 elements.
Obviously if you don't include the repeated value in the input, it won't be in the output. If you change the code correctly to include all the input values it will work as you want (live example).
cplusplus.com is not a good reference, if you look at http://en.cppreference.com/w/cpp/algorithm/set_intersection you will see it clearly states the behaviour for repeated elements:
If some element is found m times in [first1, last1) and n times in [first2, last2), the first std::min(m, n) elements will be copied from the first range to the destination range.
Even the example at cplusplus.com is bad, it would be simpler, and harder to introduce your bug, if it was written in idiomatic modern C++:
#include <iostream> // std::cout
#include <algorithm> // std::set_intersection, std::sort
#include <vector> // std::vector
int main () {
int first[] = {5,10,15,20,20,25};
int second[] = {50,40,30,20,10,20};
std::sort(std::begin(first), std::end(first));
std::sort(std::begin(second), std::end(second));
std::vector<int> v;
std::set_intersection(std::begin(first), std::end(first),
std::begin(second), std::end(second),
std::back_inserter(v));
std::cout << "The intersection has " << v.size() << " elements:\n";
for (auto i : v)
std::cout << ' ' << i;
std::cout << '\n';
}
This automatically handles the right number of elements, without ever having to explicitly say 5 or 6 or any other magic number, and without having to create initial elements in the output vector and then resize it to remove them again.
set_intersection requires both ranges to be sorted. In the data you've given, second is not sorted.
If you sort it first, you should get your expected answer.

unexpected output from C++ multiset lower_bound

Wondeirng why below code returns 1? I never insert 1 into the multiset container.
#include <iostream>
#include <set>
int main ()
{
std::multiset<int> mymultiset;
std::multiset<int>::iterator itlow;
mymultiset.insert(-3);
itlow = mymultiset.lower_bound (3);
std::cout << *itlow << endl; // output 1
return 0;
}
mymultiset.lower_bound(3) returns the lowest location in the container where 3 could go, and that's at the end of the container. So itlow is equal to mymultiset.end(), and it is not dereferenceable. std::cout << *itlow has undefined behavior.
You are trying to get an Iterator which his lower bound is 3, and your maximum value is -3. So you've got an end iterator, which his value is undefined.
You should use multiset::begin() as your Iterator, or put something like itlow = mymultiset.lower_bound (-4); which is not very gentle.
Hi to clarify my understanding
I have one multiset which contains 1 and 5.
mset.insert(1);
mset.insert(5);
auto it = s.lower_bound(6);
cout<<*it<<endl;
Now, from the above answer, I will be getting 2 since that is the location where the value 6 can fit inside the container. Am I right?
Next, if I search for the value 4, I am getting 5.
Here I don't think the iterator has reached the mset.end().
Am I right?
Thanks

Both set::find and std::find fail to find only some double elements in a set

I am developing a big code base and wanted to use set-s from the STL to store double elements. I just ran some tests and found something very weird.
Here's my source code
#include <iostream>
#include <set>
#include <numeric>
#include <algorithm>
int main()
{
double iter = 0.001;
int count = 0;
std::set<double> S;
while(count < 10)
{
S.insert(iter);
std::cout << "Inserted element is " << iter << std::endl;
iter += 0.001;
count++;
}
for (std::set<double>::iterator i = S.begin(); i != S.end(); i++)
{
double element = *i;
std::cout << "The element in the set is " << element << std::endl;
}
std::cout << "The count of the element to be found is " << S.count(0.009) << std::endl;
if (S.find(0.008) != S.end())
std::cout << "set::find found it!" << std::endl;
else
std::cout << "set::find didn't find it!" << std::endl;
if (std::find(S.begin(), S.end(), 0.009) != S.end())
std::cout << "std::find found it!" << std::endl;
else
std::cout << "std::find didn't find it!" << std::endl;
return 0;
}
Now, the weird part is that both set::find and std::find are able to find all elements until 0.008 but cannot find anything after that.
The output I get for the above code is shown below:
Inserted element is 0.001
Inserted element is 0.002
Inserted element is 0.003
Inserted element is 0.004
Inserted element is 0.005
Inserted element is 0.006
Inserted element is 0.007
Inserted element is 0.008
Inserted element is 0.009
Inserted element is 0.01
The element in the set is 0.001
The element in the set is 0.002
The element in the set is 0.003
The element in the set is 0.004
The element in the set is 0.005
The element in the set is 0.006
The element in the set is 0.007
The element in the set is 0.008
The element in the set is 0.009
The element in the set is 0.01
The count of the element to be found is 0
set::find found it!
std::find didn't find it!
Notice that I have asked set::find to find 0.008 while I have asked both count and std::find to count and find 0.009 respectively. I just wanted to know why I'm seeing such an anomaly.
It is also worth mentioning that both the find functions have absolutely no problems finding integer elements. I was wondering if this is a double issue. Even if that's the case, I'm not sure why it is able to find a few elements but not all.
I'm not sure what causes this error but if it's of any use I work on Mac OS X 10.10.3 with gcc 4.9.2.
Yes it's a double "issue" - when you successively add 0.001 to iter, rounding errors can accumulate such that the resultant value doesn't match what you might expect (e.g. your hardcoded 0.008).
Because set is sorted, you may want to use e.g. lower_bound to find a nearby element, then check using some tolerance for differences. For example, checking that the absolute difference between the found and expected values is less than an epsilon amount. There are hundreds of questions on S.O. about how exactly to implement the comparison... e.g. here.
Another issue specific to the use of floating point numbers in set is that you may not get inserts deemed duplicates when you expect them too, or on the other hand insert may refuse to insert two values that you didn't expect to be duplicates, as the rounding errors during their generation has left them identical. It's also possible for the order of two extremely similar values to be reversed compared to what you'd mathematically expect given perfectly accurate calculations.

Find which element is not sorted in a list

I have a list filled with the numbers 3, 7, 10, 8, 12. I'd like to write a line that will tell me which element in the list is not sorted (in this case it is the 4th element). However, the code I have right now tells me the value of the 4th element (8). Is there a way I can rewrite this to tell me it's the 4th element rather than the number 8?
Here is the code I have now:
list<int>::iterator i;
if (!is_sorted(myList.begin(), myList.end())) {
i = is_sorted_until(myList.begin(), myList.end());
cout << *i << endl;
}
The first thing I should say, is that if you care about numerical position, you should be using a random access container, such as std::vector. Then your job would be simple:
// calling is_sorted is a waste if you're about to call is_sorted_until
auto i = is_sorted_until(my_vector.begin(), my_vector.end());
if (i != my_vector.end())
cout << (i - my_vector.begin());
If you must use a list, and you still need the position, then you should write your own algorithm which provides this information. It really shouldn't be that hard, it's just a for loop comparing each element to the one that precedes it. When you find one which compares less than the one which procedes it, you've found your element. Just keep an integer count alongside it, and you're good.
The obvious way would be to simply search for an element that's less than the element that preceded it.
int position = 1;
auto prev = myList.begin(), pos=std::next(prev, 1);
while (pos != myList.end() && *prev < *pos) {
++position;
++prev;
++pos;
}
You could use a standard algorithm instead, but they seem somewhat clumsy for this situation.
Does this help?
std::is_sorted_until()
From http://www.cplusplus.com/reference/algorithm/is_sorted_until/:
Find first unsorted element in range
Returns an iterator to the first element in the range [first,last) which does not follow an ascending order.
The range between first and the iterator returned is sorted.
If the entire range is sorted, the function returns last.
The elements are compared using operator< for the first version, and comp for the second.

C++ Segmentation fault with vector

In below code, I'm trying to display Daily Report with the total Sale. Output is correct but exit with segmentation fault. How do I solve this pls?
Output is
Date Total Sales
03Nov13 745
13Jan14 538
Segmentation fault (core dumped)
Code:
for (int index=0;index<stockVector.size();index++)
{
if ( stockVector[index].getTransDate() == stockVector[index+1].getTransDate())
{
int totalSum = ((stockVector[index].getQtyPurchase() * stockVector[index].getUnitPrice()) +
(stockVector[index+1].getQtyPurchase() * stockVector[index+1].getUnitPrice()));
cout << stockVector[index].getTransDate() << "\t\t" << totalSum << endl;
}
}
This is my data in text file which has been stored in vector.
ProductID:Description:Price:Qty:Transaction Date
003:Calendar:5:104:03Nov13
079:Revlon Foundation:5:45:03Nov13
005:MacBook Pro:3500:1:10Jan14
010:NesCafe Latte:1:9:1Jan14
095:Lipton Tea:5:95:13Jan14
096:Milk Tea:3:21:13Jan14
066:Samsung Note 3:450:1:23Jan14
088:HP Mouse:23:100:24Jan14
In your loop, you're using an index (index+1 in the condition) that can reference an element beyond the last element of the vector (when index reaches stockVector.size() - 1). Dereferencing a pointer (which stockVector does when its operator[] is called) at a location beyond the end of an array is undefined behaviour, so anything can happen (including getting a correct result and then crashing).
To solve this, simply clamp the loop to stockVector.size() - 1:
for (int index=0;index<stockVector.size() - 1;index++)
{
// ...
You may however have to evaluate whether this solution is adequate for the last element of your vector.
stockVector[index+1]
That will obviously go past the end of the vector when index reaches size() - 1.
If you need to peek at the next element you will need to verify that you don't go past the end of the vector and you will also need to figure out what to do when you reach the last element and/or have an odd number of elements.