code crashes when using auto loop - c++

I am sorting a vector using a swap function.
When I use the loop:
for (int i = 0; i < vec.size(); i++)
code runs fine but when I use:
for (auto const &i:vec)
it crashes!
Error in ./run': free(): invalid next size (fast): 0x0000000001df0c20
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <vector>
#include <array>
template <class T>
void myswap(T &a,
T &b)
{
T temp = a;
a = b;
b = temp;
}
int main() {
const int N = 5;
std::vector<int> vec = {112,32,11,4,7};
std::cout << "\nInit\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
int j;
for (auto const &i:vec)
//for (int i = 0; i < vec.size(); i++)
{
j = i;
while (j > 0 && vec[j] < vec[j-1])
{
myswap(vec[j], vec[j-1]);
j--;
}
}
std::cout << "\n\nFinal\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
std::cout << "\n";
return 0;
}

Answer already in the comments to the question (range based loop iterates over the values, not the indices), but for illustration, try this:
std::vector<std::vector<int>> v;
int j;
for(auto const& i : v)
{
j = v;
}
You will quickly discover that this piece of code does not compile – a good compiler will show you an error like this one (from GCC):
error: cannot convert 'std::vector<std::vector<int> >' to 'int' in assignment
What you now could do would be the following:
std::vector<std::vector<int>> v;
for(auto const& i : v)
{
std::vector<int> const& vv = v; // assign a reference
std::vector<int> vvv = v; // make a COPY(!)
}
Pretty self-explaining, isn't it?

it may be due to auto const try like this const auto and also you are using j in while loop instead of i you change it to j in while or change for(const auto &j:vec)
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <vector>
#include <array>
template <class T>
void myswap(T &a,
T &b)
{
T temp = a;
a = b;
b = temp;
}
int main() {
const int N = 5;
std::vector<int> vec = {112,32,11,4,7};
std::cout << "\nInit\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
int j;
for (const auto &j:vec)
//for (int j = 0; j < vec.size(); j++)
{
while (j > 0 && vec[j] < vec[j-1])
{
myswap(vec[j], vec[j-1]);
j--;
}
}
std::cout << "\n\nFinal\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
std::cout << "\n";
return 0;
}

From the way you use swap, it is intended for j to represent a valid index of vec. Now i is not an index, but it is a value instead. When you assign j=i, then j contains 112 which is clearly out of bounds.
The way ranged loop works is that i takes the value vec[0], vec[1], vec[2] ... at each iteration.
Read here to learn about ranged loop.

Related

How to Print whole array inside square brackets rather then printing every single value?

In the following code I want to print the whole array instead of printing each single value. Can we do that? I'm familiar with python where we append values but I can't find that in C++. So how to get desired result. What if I have to print it using printf?
#include <iostream>
using namespace std;
int *name(){
static int n[5];
for(int i=0;i<5;i++){
n[i]=i;}
return n;}
int main(){
int *p;
p=name();
for(int i=0;i<5;i++){
cout<<*(p+i)<<endl;}
return 0;
desired output should be -
[0,1,2,3,4]
#include <iostream>
using namespace std;
int *name() {
static int n[5];
for (int i = 0; i < 5; ++i)
n[i] = i;
return n;
}
int main()
{
int *p;
p = name();
cout << '[';
for (int i = 0; i < 5; ++i)
cout << *(p+i) << (i != 4 ? ',' : ']');
}
Or, if you want to encapsulate the array-printing into a general function:
#include <iostream>
#include <string>
using namespace std;
std::string PrintArray(int* array, size_t size) {
std::string answer = "[";
for (size_t i = 0; i < size; ++i) {
answer += std::to_string(array[i]);
answer += (i < size-1) ? "," : "]";
}
return answer;
}
int* name() {
static int n[5];
for (int i = 0; i < 5; i++) {
n[i] = i;
}
return n;
}
int main() {
int* p;
p = name();
cout << PrintArray(p, 5) << endl;
return 0;
}
I usually end up overloading operator<< for the desired type, but your mileage may vary.
#include <iostream>
#include <vector>
template <class InputIt>
std::ostream& print_impl(std::ostream& os, InputIt first, InputIt last)
{
os << '[';
if (first != last)
{
os << *first;
while ( ++first != last )
os << ", " << *first;
}
return os << ']';
}
template <class T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v)
{
return print_impl(os, v.cbegin(), v.cend());
}
template <class T, size_t N>
std::ostream& operator<<(std::ostream& os, T const (&a)[N])
{
return print_impl(os, std::cbegin(a), std::cend(a));
}
int main()
{
std::vector<int> a{1, 2, 3, 4, 5};
std::cout << a << '\n';
float b[] = {3.14f, -0.1f, 2.0f};
std::cout << b << '\n';
}

How to print to the console after every swap using any sorting algorithm?

In my Intro to Computer Science class I am beginning to learn the basics of sorting algorithms. So far, we have gone over Bubble, Selection, and Insertion Sort.
After class today, the instructor has requested us to "enhance" the program by adding code to print out the vector/array after every swap during the sorting. I am at a complete loss as to how I would make this happen. I'm thinking something like :
if (swapped) { cout << vec << " "; }
but without even trying, I'm certain this wouldn't work. Any help is very much appreciated. Here's my code so far:
#include <string>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> createVec(int n) {
unsigned seed = time(0);
srand(seed);
vector<int> vec;
for (int i = 1; i <= n; ++i) {
vec.push_back(rand() % 100 + 1);
}
return vec;
}
void showVec(vector<int> vec) {
for (int n : vec) {
cout << n << " ";
}
}
void bubbleSort(vector<int> &vec) {
int n = vec.size();
bool swapped = true;
while (swapped) {
swapped = false;
for (int i = 1; i <= n-1; ++i) {
if (vec[i-1] > vec[i]) {
swap(vec[i-1], vec[i]);
swapped = true;
}
}
}
}
void selectionSort(vector<int> &vec) {
int n = vec.size();
int maxIndex;
for (int i = 0; i <= n-2; ++i) {
maxIndex = i;
for (int j = i+1; j <= n-1; ++j) {
if (vec[j] < vec[maxIndex]) {
maxIndex = j;
}
}
swap(vec[i], vec[maxIndex]);
}
}
int main()
{
vector<int> numbers = createVec(20);
showVec(numbers);
cout << endl;
//bubbleSort(numbers);
selectionSort(numbers);
showVec(numbers);
return 0;
}
For example in the called function selectionSort substitute this statement
swap(vec[i], vec[maxIndex]);
for the following statement
if ( i != maxIndex )
{
swap(vec[i], vec[maxIndex]);
showVec( vec );
cout << endl;
}
Also the function showVec should declare the parameter as having a constant referenced type
void showVec( const vector<int> &vec) {
for (int n : vec) {
cout << n << " ";
}
}

Split an array at a specific value C++

Say I have an array like this:
int arr [9] = {2,1,5,8,9,4,10,15,20}
How can you split the array at a certain value threshold? So say int 8 is our splitting value, the end result would be two separate arrays (or a 2d array if you want to give that a shot) that in this example would be arr1 [4] = {1,2,4,5} and arr2 [5] = {8,9,10,15,20}. arr1 stores all the values in arr that are below 8 and and arr2 stores all the values in arr that are 8 and above.
I haven't been able to locate sufficient documentation or examples of this being done and I think array manipulation and splitting is worth having examples of.
Use std::partition, or if you want to maintain the relative order and not sort the data, std::stable_partition.
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
int pivot = 8;
int arr [9] = {2,1,5,8,9,4,10,15,20};
// get partition point
int *pt = std::stable_partition(arr, std::end(arr), [&](int n) {return n < pivot;});
// create two vectors consisting of left and right hand side
// of partition
std::vector<int> a1(arr, pt);
std::vector<int> a2(pt, std::end(arr));
// output results
for (auto& i : a1)
std::cout << i << " ";
std::cout << '\n';
for (auto& i : a2)
std::cout << i << " ";
}
Live Example
If you can use C++11 then this is one way of using the standard library:
Using a partition_point: (edited the example from the link)
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::array<int, 9> v = {2,1,5,8,9,4,10,15,20};
auto is_lower_than_8 = [](int i){ return i < 8; };
std::partition(v.begin(), v.end(), is_lower_than_8 );
auto p = std::partition_point(v.begin(), v.end(), is_lower_than_8 );
std::cout << "Before partition:\n ";
std::vector<int> p1(v.begin(), p);
std::sort(p1.begin(), p1.end());
std::copy(p1.begin(), p1.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\nAfter partition:\n ";
std::vector<int> p2(p, v.end());
std::sort(p2.begin(), p2.end());
std::copy(p2.begin(), p2.end(), std::ostream_iterator<int>(std::cout, " "));
}
Which prints:
Before partition:
1 2 4 5
After partition:
8 9 10 15 20
I'm working on a solution with loops. This is a work in progress. Let me know what you think.
void splitarr(int arr[], int length) {
int accu = 0;
int accu2 = 0;
int splitter = rand() % 20;
for (int i = 0; i < length; i++) {
if (i != splitter) {
accu++;
}
}
int arr1[accu];
for (int i = 0; i < length; i++) {
if (i != splitter) {
arr1[i] = i;
}
}
for (int i = 0; i < length; i++) {
if (i == splitter) {
accu2++;
}
}
int arr2[accu2];
for (int i = 0; i < length; i++) {
if (i == splitter) {
arr2[i] = i;
}
}
}

Is there a way to pass an object's field implicitly to a function in C++

Suppose I have an object
class Obj {
public:
int a;
int b;
int c;
}
And an array of objects
Obj o[N];
I want to copy each Obj.a into an int array and I know other languages allow me to make a function that might look like this in C++
int & fun(Obj os[], T key, int N){
int a[N];
for (int i=0; i<N; i++) {
a[i] = os[i].key;
}
return a;
}
Is there any reusable way to do this in C++? For reference, Obj's code can't be modified.
This is what the std::transform function is for. All you need to provide is a function to get the desired element from an Obj. This example shows how to do it with std::mem_fn:
#include <algorithm>
#include <functional>
#include <iterator>
#include <iostream>
struct Obj { int a, b, c; };
int main() {
Obj o[3] = {{1, 2, 3}, {11, 22, 33},{111, 222, 333}};
int a[3];
std::transform(std::begin(o), std::end(o),
std::begin(a),
std::mem_fn(&Obj::a));
for (auto e : a)
std::cout << e << ' ';
std::cout << std::endl;
};
Output:
1 11 111
This can all be wrapped up in a helper function to allow the caller to set the attribute to extract. But note if you really want a function to return an array, you'll need to use a copyable type such as std::array or std::vector. In C++ plain arrays are not copyable so can't be returned by value from a function.
Here's a slightly modified version of your code:
#include <cstddef>
#include <iostream>
using std::size_t;
struct Obj {
int a;
int b;
int c;
};
static void fun(const Obj *os, size_t N, int Obj::*const key) {
for (size_t i = 0; i < N; i++) {
std::cout << os[i].*key << '\n';
}
}
int main() {
Obj o[] = { {1, 2, 3}, {4, 5, 6} };
fun(o, sizeof o / sizeof o[0], &Obj::b);
}
I changed the return type of fun because your version doesn't typecheck. For demonstration purposes fun simply outputs the elements.
The key here is that you can abstract over class fields by using member pointers.
You can use pointer-to-member syntax:
#include <iostream>
#include <memory>
struct Obj {
int a;
int b;
};
std::unique_ptr<int[]>
fn(Obj* os, size_t N, int Obj::*member)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = os[i].*member;
}
return arr;
}
int main() {
Obj os[] { { 1, 10 }, { 2, 20 } };
auto a1 = fn(os, 2, &Obj::a);
auto a2 = fn(os, 2, &Obj::b);
for (size_t i = 0; i < 2; ++i) {
std::cout << i << ": " << a1[i] << ", " << a2[i] << '\n';
}
}
Demo: http://ideone.com/cQMyh3
Or you could use a lambda.
#include <iostream>
#include <memory>
struct Obj {
int a;
int b;
};
std::unique_ptr<int[]>
fn(Obj* os, size_t N, std::function<int(const Obj&)> keyFn)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = keyFn(os[i]);
}
return arr;
}
int main() {
Obj os[] { { 1, 10 }, { 2, 20 } };
auto a1 = fn(os, 2, [](const Obj& o){ return o.a; });
auto a2 = fn(os, 2, [](const Obj& o){ return o.b; });
for (size_t i = 0; i < 2; ++i) {
std::cout << i << ": " << a1[i] << ", " << a2[i] << '\n';
}
}
http://ideone.com/9OvTzl
Or the more generic:
template<typename KeyFn>
std::unique_ptr<int[]>
fn(Obj* os, size_t N, KeyFn keyFn)
{
auto arr = std::make_unique<int[]>(N);
for (size_t i = 0; i < N; ++i) {
arr[i] = keyFn(os[i]);
}
return arr;
}
Other changes to consider:
Use a standard container, e.g. vector or array to house your Obj's,
Consider passing iterators over the ranges rather than a pointer and a size,
Using range library you may simply do
for (int e : objs | ranges::v3::view::transform(&Obj::a)) {
std::cout << e << " ";
}
Demo
A possible transcription of your example in C++ could be:
#include <functional>
int* fun(Obj os[], std::function<int(Obj)> get_key, int N){
int* a = new int[N];
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
Use:
func(os, [](Obj obj){return obj.a;}, N);
You must declare a dynamic array because the size is variable. But with a raw pointer, you may obtain memory leak or segmentation fault. A version with managed pointers (only working in C++14):
#include <memory>
#include <functional>
std::unique_ptr<int[]> fun(Obj os[], std::function<int(Obj)> get_key, int N){
std::unique_ptr<int[]> a = std::make_unique(N);
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
Or with stl container (no memory allocation):
#include <vector>
#include <functional>
std::vector<int> fun(Obj os[], std::function<int(Obj)> get_key, int N){
std::vector<int> a(N);
for (int i=0; i<N; i++) {
a[i] = get_key(os[i]);
}
return a;
}
But it's often a bad idea to "translate" from one language to another ;)

How to use std::sort to sort an array in C++

How to use standard template library std::sort() to sort an array declared as
int v[2000];
Does C++ provide some function that can get the begin and end index of an array?
In C++0x/11 we get std::begin and std::end which are overloaded for arrays:
#include <algorithm>
int main(){
int v[2000];
std::sort(std::begin(v), std::end(v));
}
If you don't have access to C++0x, it isn't hard to write them yourself:
// for container with nested typedefs, non-const version
template<class Cont>
typename Cont::iterator begin(Cont& c){
return c.begin();
}
template<class Cont>
typename Cont::iterator end(Cont& c){
return c.end();
}
// const version
template<class Cont>
typename Cont::const_iterator begin(Cont const& c){
return c.begin();
}
template<class Cont>
typename Cont::const_iterator end(Cont const& c){
return c.end();
}
// overloads for C style arrays
template<class T, std::size_t N>
T* begin(T (&arr)[N]){
return &arr[0];
}
template<class T, std::size_t N>
T* end(T (&arr)[N]){
return arr + N;
}
#include <algorithm>
static const size_t v_size = 2000;
int v[v_size];
// Fill the array by values
std::sort(v, v + v_size);
In C++11:
#include <algorithm>
#include <array>
std::array<int, 2000> v;
// Fill the array by values
std::sort(v.begin(), v.end());
If you don't know the size, you can use:
std::sort(v, v + sizeof v / sizeof v[0]);
Even if you do know the size, it's a good idea to code it this way as it will reduce the possibility of a bug if the array size is changed later.
You can sort it std::sort(v, v + 2000)
#include<iostream>
using namespace std;
void main()
{
int a[5];
int temp = 0;
cout << "Enter Values: " << endl;
for(int i = 0; i < 5; i++)
cin >> a[i];
for(int i = 0; i < 5; i++)
for(int j = 0; j < 5; j++)
if(a[i] > a[j])
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
cout << "Asending Series" << endl;
for(int i = 0; i < 5; i++)
{
cout << endl;
cout << a[i] << endl;
}
for(int i = 0; i < 5; i++)
for(int j = 0; j < 5; j++)
if(a[i] < a[j])
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
cout << "Desending Series" << endl;
for(int i = 0;i < 5; i++)
{
cout << endl;
cout << a[i] << endl;
}
}
you can use sort() in C++ STL. sort() function Syntax :
sort(array_name, array_name+size)
So you use sort(v, v+2000);
It is as simple as that ... C++ is providing you a function in STL (Standard Template Library) called sort which runs 20% to 50% faster than the hand-coded quick-sort.
Here is the sample code for it's usage:
std::sort(arr, arr + size);
//sort by number
bool sortByStartNumber(Player &p1, Player &p2) {
return p1.getStartNumber() < p2.getStartNumber();
}
//sort by string
bool sortByName(Player &p1, Player &p2) {
string s1 = p1.getFullName();
string s2 = p2.getFullName();
return s1.compare(s2) == -1;
}
With the Ranges library that is coming in C++20, you can use
ranges::sort(arr);
directly, where arr is a builtin array.
sort() can be applied on both array and vector in C++ to sort or re-arrange elements .
1. C++ sort() in case of a vector:
// importing vector, algorithm & iostream
using namespace std;
int main()
{
vector v = {5,4,3,2,8}; // depending on your vector size
sort(v.begin(), v.end());
cout<<v[1]; //testing the sorted element positions by printing
return 0;
}
2. C++ sort() in case of an array:
// including algorithm & iostream
using namespace std;
int main() {
int array[] = {10, 35, 85}; // array size 2000 in your case
int n = sizeof(array)/sizeof(array[0]);
sort(array, array+3);
cout<<array[0];
return 0;
}
Note: Both the above snippets were tested with modern C++ versions (11,17 & 20) before posting here .
sorting method without std::sort:
// sorting myArray ascending
int iTemp = 0;
for (int i = 0; i < ARRAYSIZE; i++)
{
for (int j = i + 1; j <= ARRAYSIZE; j++)
{
// for descending sort change '<' with '>'
if (myArray[j] < myArray[i])
{
iTemp = myArray[i];
myArray[i] = myArray[j];
myArray[j] = iTemp;
}
}
}
Run complete example:
#include <iostream> // std::cout, std::endl /* http://en.cppreference.com/w/cpp/header/iostream */
#include <cstdlib> // srand(), rand() /* http://en.cppreference.com/w/cpp/header/cstdlib */
#include <ctime> // time() /* http://en.cppreference.com/w/cpp/header/ctime */
int main()
{
const int ARRAYSIZE = 10;
int myArray[ARRAYSIZE];
// populate myArray with random numbers from 1 to 1000
srand(time(0));
for (int i = 0; i < ARRAYSIZE; i++)
{
myArray[i] = rand()% 1000 + 1;
}
// print unsorted myArray
std::cout << "unsorted myArray: " << std::endl;
for (int i = 0; i < ARRAYSIZE; i++)
{
std::cout << "[" << i << "] -> " << myArray[i] << std::endl;
}
std::cout << std::endl;
// sorting myArray ascending
int iTemp = 0;
for (int i = 0; i < ARRAYSIZE; i++)
{
for (int j = i + 1; j <= ARRAYSIZE; j++)
{
// for descending sort change '<' with '>'
if (myArray[j] < myArray[i])
{
iTemp = myArray[i];
myArray[i] = myArray[j];
myArray[j] = iTemp;
}
}
}
// print sorted myArray
std::cout << "sorted myArray: " << std::endl;
for (int i = 0; i < ARRAYSIZE; i++)
{
std::cout << "[" << i << "] -> " << myArray[i] << std::endl;
}
std::cout << std::endl;
return 0;
}
Use the C++ std::sort function:
#include <algorithm>
using namespace std;
int main()
{
vector<int> v(2000);
sort(v.begin(), v.end());
}
C++ sorting using sort function
#include <bits/stdc++.h>
using namespace std;
vector <int> v[100];
int main()
{
sort(v.begin(), v.end());
}
you can use,
std::sort(v.begin(),v.end());