I wanted to use the sort() in the algorithm library in C++. I could find examples for sorting vectors only, thus I am trying to initialize a vector by an initialized array. When executing I am getting a segmentation fault and couldn't figure out what is wrong here in the code I wrote.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n,k,packet[1000],min=0;
scanf("%d",&n);
scanf("%d",&k);
for (int i = 0; i < n; ++i)
{
scanf("%d",&packet[i]);
cout<<i<<endl;
}
cout<<"debug";
vector<int> packets(packet,packet+n);
vector<int>::iterator start,stop;
sort(packets.begin(),packets.begin()+n);
min=*(packets.begin())- *(packets.end());
cout<<min;
for (vector<int>::iterator it=packets.begin(); it!=packets.end()-k; ++it)
{
printf("%d ",*it );
if((*(it+k) - *it)<min)
{
start=it;
stop=it+k;
}
}
printf("%d\n",*stop- *start );
return 0;
}
*(packets.end())
packets.end() returns an iterator to the element, following the last element of the vector.
Attempting to derefenrence it causes Undefined Behavior.
The comments explain that you can use sort with an array just fine (if you look at http://en.cppreference.com/w/cpp/algorithm/sort you'll see that sort takes two arguments that: -RandomIt must meet the requirements of ValueSwappable and RandomAccessIterator.. Plain pointers fulfill this requirement).
In your example, the segfault happens because you try to dereference a valid but undereferencable iterator (the iterator returned by 'end()' in: min=*(packets.begin())- *(packets.end());. Basically it returns an iterator that points to after the last element of the vector. If you want to get an iterator to the last element, you can use rbegin() but of course you need to make sure that the vector is not empty first).
You could have seen this quite easily by running your code under a debugger, you'd see that the segmentation fault had nothing to do with the call to sort
Related
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a, b;
cin>>a;
vector<int> numbers;
for(int i=0; i<a; i++)
{
cin>>b;
numbers.push_back(b);
}
int c,d,e;
cin>>c;
numbers.erase(numbers.begin()+c-1);
cin>>d>>e;
numbers.erase(numbers.begin()+d-1, numbers.end()+e);
cout<<numbers.size();
for(int x : numbers)
cout<<x<<" ";
return 0;
}
Hello everyone,
I am learning c++ and writing a very simple program, but this code is giving "Segmentation Fault" as error. I really could not figure out why this is happening.
Thank you.
This line
numbers.erase(numbers.begin()+d-1, numbers.end()+e);
cannot be correct. Incrementing the end iterator never gets you a valid iterator. It is not quite clear what you want to do, but if you want to erase elements in the range of indices [d,e) then that would be
numbers.erase(numbers.begin()+d, numbers.begin()+e);
Note: No +1 needed on the first, because the first is inclusive. And you get an iterator to the e-th element by incrementing the begin iterator not the end iterator (well... I assume the common 0-based counting, ie the "first" element is the 0th element ;).
Also, as mentioned in comments, you should check if the user entered values are in range, before calling erase. erase does no bounds-checking. If you pass invalid iterators your get undefined behavior.
I have a trouble in understanding the behaviour of transform function if used with back_inserter.
#include <algorithm>
using namespace std;
int main()
{
vector<int> a{1,2,4};
transform(begin(a), end(a), back_inserter(a), [](auto e){ cout << e << "-" ;
return e;});
return 0;
}
In the above program, I get the output as 1-0-4. I am not able to understand how this 0 is coming?
Please see live example cpp.sh/6vpzk
This code does vector::push_back while iterating over it using its iterators. vector::push_back invalidates all existing iterators causing undefined behaviour, and that is where that 0 comes from (it can be any other number, since the behaviour is undefined).
You should probably use for_each or range for loop.
This question already has answers here:
Iterator invalidation rules for C++ containers
(6 answers)
Closed 5 years ago.
#include <iostream>
#include <vector>
#include <algorithm>
#include <time.h>
#include <iomanip>
using namespace std;
bool isEven(int n)
{
return n%2 == 0;
}
int main()
{
srand(time(NULL));
vector<int> myVec;
for(int i = 0; i < 20; i++)
{
myVec.push_back(rand() % 100);
}
while(1)
{
vector<int>::iterator q = std::find_if(myVec.begin(), myVec.end(), isEven);
cout << *q << endl;
if(q == myVec.end())
{
myVec.erase(q);
break;
}
else
myVec.erase(q);
}
return 0;
}
This code is giving segmentation fault. The above code is to remove all the even numbers from the vector using find_if and erase function
Please help. Any help will be highly appreciated.
EDIT: I have edited it to make sure that iterator will be valid always.
Still it is giving segmentation fault.
std::vector::erase invalidates all iterators to and after the point of erasure. You can't continue using that iterator, not to increment it, use it to access the vector, or even compare it to end().
The correct algorithm to use is std:remove_if. Unlike the name implies, it will only move all even items of the vector "to the back", without invalidating any iterators. It will return an iterator to the start of this sub-range, which you can then just feed to the appropriate erase overload (the one that accepts a pair of iterators).
This has been used so much in code that it's even named "the erase-remove idiom".
When using the erase(it); function the iterator changes so you need to set the iterator again to the new one returned by the erase function.
In your code, you are checking for the end if(q == myVec.end()) and then using erase this will throw an error as.end() does not point to data, and to be able to erase an item from the vector the iterator needs to be valid. So by changing if(q == myVec.end()) to if(q == (myVec.end()-1)) it will allow you to delete the last element in case of been a pair.
I was trying to solve a problem which involved producing all the permutations of a set of numbers. The idea seemed simple enough (code below), but I keep getting segmentation faults. Can anyone tell me what I'm doing wrong?
void permute(set<int>& s, vector<int>& v) {
if(s.empty()) {
// read the permutation in v.
return;
}
set<int>::iterator i;
for(i = s.begin(); i != s.end(); i++) {
int x = *i;
s.erase(i);
v.push_back(x);
permute(s, v);
v.pop_back();
s.insert(x);
}
}
To produce all permutations in C++ use std::next_permutation. The problem here is that you cannot permutate the set, because the ordering is preset by the key comparator operator (in your case the less than operator). What you can do is store your values in a non associative container and then have a go.
#include <set>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
void permut(std::set<int> const &inp, std::vector<int> &all_permutations)
{
vector<int> tmp(inp.size());
copy(inp.begin(), inp.end(), tmp.begin());
vector<int> all_permutations;
do
{
copy(tmp.begin(), tmp.end(), back_inserter(all_permutations));
} while (std::next_permutation(tmp.begin(), tmp.end()));
}
The permute() function calls itself recursively while iterating over the mutable containers and making changes. This violates iterator validity promises.
You might try something based on std::next_permutation()
I have not gone into the precise behaviour you can expect from a set, but it seems pretty clear that the things you are doing inside the for loop are enough to make the iterator invalid. I would suggest redesigning things so that you have two sets, and work through one (which starts off full) while generating the permutation in the other (which starts off empty).
i'm trying to use algorithm lib & vector lib to first copy a set of numbers from an array into a vector then printing it using iteration, where is the problem of my code?
and one thing is that i chose 2 way to do this iteration first using vec.begin() ; vec.end() method & the other one is for (i = 0 ; i < vec.capacity() ; i++)
both facing errors.
what should i do?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int intArray[] = {5,6,8,3,40,36,98,29,75};
vector<int> vecList(9);
//vector<int>::iterator it;
copy (intArray, intArray+9,vecList);
//for(it = vecList.begin() ; it != vecList.end() ; it++)
for (int it = 0 ; it < vecList.capacity() ; it++)
{
cout<<*it<<endl;
}
system("pause");
return 0;
}
There are several improvements possible.
You confuse iterators with indices. An iterator it is a glorified pointer into the vector, that you need to derefence by typing *it. An index i is an offset from the beginning of the vector and saying vecList[i] will give you that element.
The initialization of the vector is best done using initializer lists (C++11), rather than reading from an array.
You need to loop to vecList.size(). The capacity of the vector is the size of the allocated storage space for the elements of the vector container. Looping is best done with a ranged-for loop as shown by Kerrek SB, or a std::for_each + a lambda expression, or a regular for loop as you did. In that case however, it's best to get into the habit of doing it != vecList.end() (instead of using <) and doing ++it instead of it++.
Note that I also used auto to avoid writing the explicit iterator type. It's also a good habit to get into using auto wherever you can.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
// initialize vector with a list of elements
vector<int> vecList {5,6,8,3,40,36,98,29,75};
// loop from begin() to end() of vector, doing ++it instead of it++
for (auto it = vecList.begin(); it != vecList.end(); ++it)
{
cout<<*it<<endl;
}
// the pause command is better done by setting a breakpoint in a debugger
return 0;
}
Output on Ideone (this uses the g++ 4.5.1 compiler, it's best to upgrade to at least that version to take advantage of C++11 features).
The problem is that you're confusing indexes and iterators.
w/ index:
for (int i = 0 ; i < vecList.size() ; it++)
{
cout<<vecList[i]<<endl;
}
w/ iterators
for (std::vector<int>::const_iterator it = vecList.begin() ; i != vecList.end() ; it++)
{
cout<<*it<<endl;
}
A. you need to iterate on vecList.size() not vecList.capacity() which mean how much memory the vector is reserving for himself (not how much of it is in use).
B. you tried to use the integer index it as an iterator with the call to *it, you should check Luchian Grigore answer for the right way to do it.
This isn't an answer, but I wanted to show how modern C++ allows you to do away with lots of the brittle dependencies on details:
int intArray[] = {5,6,8,3,40,36,98,29,75};
std::vector<int> vecList(std::begin(intArray), std::end(intArray));
for (int i : vecList) { std::cout << i << std::endl; }
Using iterators and algorithms idiomatically, you can often remove any explicit mention of details such as lengths of arrays, thus making your code more robust.
Typo mistake use : copy (intArray, intArray+9,vecList.begin());
so,
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
int main()
{
int intArray[] = {5,6,8,3,40,36,98,29,75};
vector<int> vecList(9);
vector<int>:: iterator it;
copy (intArray, intArray+9,vecList.begin());
for (it=vecList.begin();it!=vecList.end(); it++)
{
cout<<*it<<endl;
}
system("pause");
return 0;
}