how to convert 'std::vector<double>' to 'double' in initialization - c++

I'm trying to make quicksort program. I just couldn't understand why and how this error is coming. I've tried every method online but I'm unable to catch the issue. If I'm doing this with array in place of vector, I'm getting correct output but with vector error is coming.
My errors are:
.\quicksort.cpp:7:28: error: cannot convert 'std::vector<double>' to 'double' in initialization
double pivot = values[end];
.\quicksort.cpp:10:19: error: no match for 'operator<=' (operand types are 'std::vector<double>' and 'double')
if (values[i] <= pivot) {
How to convert the vector<double> to double then?
Here's my code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int partition(vector<double> *values, int start, int end) {
double pivot = values[end];
int pIndex = start;
for (int i=start; i<end; i++) {
if (values[i] <= pivot) {
swap(values[i], values[pIndex]);
pIndex++;
}
}
swap(values[pIndex], values[end]);
return pIndex;
}
void quicksort(vector<double> *values, int start, int end) {
if (start<end) {
int pIndex;
pIndex = partition(values, start, end);
quicksort(values, start, pIndex-1);
quicksort(values, pIndex+1, end);
}
}
int main() {
int n;
cin >> n;
vector<double> values(n);
for (int i = 0; i < n; i++) {
cin >> values[i];
}
quicksort(values, 0, n-1);
for (int j=0; j<n; j++) {
cout<<values[j]<<" ";
}
return 0;
}
How to rectify these errors?

References not pointers
int partition(vector<double>& values, int start, int end) {
void quicksort(vector<double>& values, int start, int end) {
If you used a pointer (but you shouldn't) the correct code would be
double pivot = (*values)[end];
Pointers are not the same as the things they are pointing to, you have to use * or -> to get at the object that a pointer points to. You don't have to do this with references.

You have a C++ compiler so use it, send Reference to your object instead of pointer:
void quicksort(vector<double> &values, const int start, const int end);
int partition(vector<double> &values, const int start, const int end)
And your compile time error gone, with pointer to the object you need to call your function like this:
quicksort(&values, 0, n - 1);
Because you need it's address (actually your pointer need it).
And you need to use operator[] of std::vector which is first need to get std::vector object from pointer to it:
double pivot = (*values)[end];
As you see it's ugly and could be complex, So it's better to use References instead of pointer in those situations.

Your partition and quicksort functions take pointers as parameters not reference values.
Your functions should be declared as such:
int partition(vector<double> &values, int start, int end)
void quicksort(vector<double> &values, int start, int end)
The reason you are getting the error is that since the values parameter is a pointer when you use the array accessor ([i]) it assumes that values is an array of vectors and returns a vector not a double.

you should pass vector<double>& to your function instead of vector<double>*, i.e. pass by reference instead of pass by pointer. If passing by pointer, then you need to access the elements of the vector with ->[index].

Related

Problem with function which create and return pointer to dynamic vector

I have to crate a function which gets a reference to int array as one of arguments. This function should creates a dynamic vector and returns its pointer.
When I compile this code I got err: "No matching function for call to 'func'".
I have no idea what's wrong.
Immediately, I would like to ask if I removed the dynamic vector from the memory correctly or should I write it differently?
#include <iostream>
#include <vector>
using namespace std;
vector<int> *func(int &, int);
int main() {
const int arrSize = 5;
int arr[arrSize] = {1, 3, 5, 7, 9};
vector<int> *ptr_vec = func(arr, arrSize);
delete ptr_vec;
}
vector<int> *func(int &arr, int size){
auto *newVec = new vector<int>;
for(int i = 0; i < size; i++) newVec[i].push_back(arr+i);
return newVec;
}
Thanks in advance
The first parameter of the function is a reference to a scalar object of the type int
vector<int> *func(int &, int);
You need to write
vector<int> *func( const int *, int);
Also in the for loop you have to write
for(int i = 0; i < size; i++) newVec->push_back(arr[i]);
In fact the for loop is redundant. Your function could look simpler as for example
vector<int> * func( const int *arr, int size )
{
return new std::vector<int> { arr, arr + size };
}
Pay attention to that there is no great sense to define the vector dynamically. The function can be declared and defined the following way
vector<int> func( const int *arr, int size )
{
return { arr, arr + size };
}

sorting array and matching other array and getting error

I'm trying to write a program where I write information of people like: name,minutes and seconds.I need to sort people by the time. I can't understand how to sort minutes and dont lose other array sequence order- name and second. they just stay standing where they stood.Also I get error because something wrong with sort
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
struct people{
string name;
int min;
int sec;
};
int main()
{
int temp;
struct people z[6];
for(int i=0; i<6; i++)
{
cin>>z[i].name;
cin>>z[i].min;
cin>>z[i].sec;
}
sort(z.min,z.min +6);
cout<<endl;
for(int i=0; i<6; i++)
{
cout<<z[i].name<<" "<<z[i].min<<" "<<z[i].sec<<endl;
}
return 0;
}
I am getting this error:
error: request for member 'min' in 'z', which is of non-class type 'people [6]'
std::sort() expects two iterators as parameters - the first one being the initial position of the sequence to be sorted and the second the final position. That's why your code does not compile.
In order to sort the array you either have to define an operator< in your class/struct or supply a comparison function as the third parameter to sort().
You could define an operator < as follows in the struct people:
bool operator < (const people &p)
{
return min < p.min;
}
and call and cal sort like this:
sort(z, z + 6);
Alternatively you could define a function comp as follows (after the definition of struct people):
bool comp(const people &p1, const people &p2) { return (p1.min < p2.min); }
and call sort() like this:
sort(z, z + 6, comp);

template function to find subarray in C++

#include <iostream>
#include <string>
using namespace std;
template <class T> int IsSubArr(T& a, int a_len, T& b, int b_len)
{
int i,j;
bool found;
int k;
T& s=a,l=b;
int s_len = (a_len < b_len) ? a_len : b_len; // find the small array length
if (s_len == a_len) // check to set pointers to small and long array
{
s = a;
l = b;
}
else
{
s = b;
l = a;
}
for (i = 0; i <= a_len-s_len; i++) //loop on long array
{
found = true;
k=i;
for (j=0; j<s_len; j++) // loop on sub array
{
if (s[j] != l[i])
{
found = false;
break;
}
k++;
}
}
if (found)
return i;
else
return -1;
}
/******* main program to test templates ****/
int main()
{
int array[5] = {9,4,6,2,1};
int alen = 5;
int sub_arr[3] = {6,2,1};
int slen = 3;
int index= 0;
index = IsSubArr(array,alen,sub_arr,slen);
cout << "\n\n Place of sub array in long array: " << index;
cout << endl;
return 0;
}
for this line of code:
index = IsSubArr(array,alen,sub_arr,slen);
i get error:
Error 1 error C2782: 'int IsSubArr(T &,int,T &,int)' : template parameter 'T' is ambiguous
please help to resolve this issue ?
Since array[a] and array[b] where a != b are 2 different types, you'll need 2 type templates args.
A work around would be to use pointers.
+ template <class T> int IsSubArr(T* a, int a_len, T* b, int b_len)
+ T* s = a; T*l = b;
You defined the first and the third parameters as references
template <class T> int IsSubArr(T& a, int a_len, T& b, int b_len)
^^^^ ^^^^
and pass as arguments for these parameters two arrays with different types
int array[5] = {9,4,6,2,1};
int sub_arr[3] = {6,2,1};
//...
index = IsSubArr(array,alen,sub_arr,slen);
^^^^^ ^^^^^^^
The first argument has type int[5] and the third argument has type int[3]
So the compiler is unable to deduce the referenced type T.
If you are going to use arrays with the function then you could declare it like
template <class T, size_t N1, size_t N2>
int IsSubArr( T ( &a )[N1], T ( &b )[N2] );
Or you could use pointers instead of the references to arrays
template <class T> int IsSubArr( T *a, size_t a_len, T *b, size_t b_len );
Take into account that this declaration within the function
T& s=a,l=b;
is also wrong. It is equivalent to the following declarations
T& s=a;
T l=b;
That is the first declaration declares a reference to an array while the second declaration declares an array and tries to initialize it with another array. However arrays do not have a copy constructor and the compiler will issue one more error. And you may not reassign a reference.
You should know that there is standard algorithm std::search declared in header <algorithm> that can do the job you want to do with your function.
It's because array and sub_arr are two different types. array is of type int[5] while sub_arr is of type int[3]. The array dimensions are part of the type.
Either change the function to use two different templates arguments, one for each array, or use pointer (e.g. T*)
There's also another error, that you will continue to have if you keep using arrays and two different template arguments, and that is that you can't change references. Once you have assigned to the variable s and l in the function, those can't be made to reference anything else. The latter assignments of the s and l variables will fail because there you try to assign the arrays to each other, which you can not do, you can only copy arrays.
If you use pointers instead, then this won't be a problem.

Quicksort function with vector object C++

I'm trying to convert this function to use a vector object instead of an integer array.
The vector object looks like this:
std::vector<Heltal *> htal;
The Heltal class contains a private integer named heltal.
How would I sort the htal vector using the function below?
void Array::Sort(int a[], int first, int last)
{
int low = first;
int high = last;
int x = a[(first+last)/2];
do {
while(a[low] < x) {
low++;
}
while(a[high] > x) {
high--;
}
if(low<=high) {
std::swap(a[low],a[high]);
low++;
high--;
}
} while(low <= high);
if(first < high)
Array::Sort(a,first,high);
if(low < last)
Array::Sort(a,low,last);
}
The correct solution is to ditch your custom sort and use std::sort from <algorithm>. This will pretty much be guaranteed to be faster and more optimal in almost every case. Then you just have:
#include <algorithm>
...
std::vector<Heltal *> htal;
...
// sort by pointer value
std::sort(htal.begin(), htal.end());
If you want to sort by object value rather than pointer value, either use std::vector<Heltal> instead of std::vector<Heltal *> (which is almost certainly what you should be doing anyway), or pass a comparison function to std::sort.
Example using C++11 lambda for this:
std::sort(htal.begin(), htal.end(), [](Heltal *a, Heltal *b) { return *a < *b; });

C++ passing an array pointer as a function argument

I'm trying to use pointers of arrays to use as arguments for a function which generates an array.
void generateArray(int *a[], int *si){
srand(time(0));
for (int j=0;j<*si;j++)
*a[j]=(0+rand()%9);
} //end generateArray;
int main() {
const int size=5;
int a[size];
generateArray(&a, &size);
return 0;
} //end main
But when I compile this this message appears:
cannot convert `int (*)[5]' to `int**' for argument `1' to `void generateArray(int**, int*)'
You're over-complicating it - it just needs to be:
void generateArray(int *a, int si)
{
for (int j = 0; j < si; j++)
a[j] = rand() % 9;
}
int main()
{
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}
When you pass an array as a parameter to a function it decays to a pointer to the first element of the array. So there is normally never a need to pass a pointer to an array.
int *a[], when used as a function parameter (but not in normal declarations), is a pointer to a pointer, not a pointer to an array (in normal declarations, it is an array of pointers). A pointer to an array looks like this:
int (*aptr)[N]
Where N is a particular positive integer (not a variable).
If you make your function a template, you can do it and you don't even need to pass the size of the array (because it is automatically deduced):
template<size_t SZ>
void generateArray(int (*aptr)[SZ])
{
for (size_t i=0; i<SZ; ++i)
(*aptr)[i] = rand() % 9;
}
int main()
{
int a[5];
generateArray(&a);
}
You could also take a reference:
template<size_t SZ>
void generateArray(int (&arr)[SZ])
{
for (size_t i=0; i<SZ; ++i)
arr[i] = rand() % 9;
}
int main()
{
int a[5];
generateArray(a);
}
You do not need to take a pointer to the array in order to pass it to an array-generating function, because arrays already decay to pointers when you pass them to functions. Simply make the parameter int a[], and use it as a regular array inside the function, the changes will be made to the array that you have passed in.
void generateArray(int a[], int si) {
srand(time(0));
for (int j=0;j<*si;j++)
a[j]=(0+rand()%9);
}
int main(){
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}
As a side note, you do not need to pass the size by pointer, because you are not changing it inside the function. Moreover, it is not a good idea to pass a pointer to constant to a parameter that expects a pointer to non-constant.
I'm guessing this will help.
When passed as functions arguments, arrays act the same way as pointers. So you don't need to reference them. Simply type:
int x[]
or
int x[a]
. Both ways will work. I guess its the same thing Konrad Rudolf was saying, figured as much.
This is another method . Passing array as a pointer to the function
void generateArray(int *array, int size) {
srand(time(0));
for (int j=0;j<size;j++)
array[j]=(0+rand()%9);
}
int main(){
const int size=5;
int a[size];
generateArray(a, size);
return 0;
}