How to pass a vector to a function? - c++

I'm trying to send a vector as an argument to a function and i can't figure out how to make it work. Tried a bunch of different ways but they all give different error messages.
I only include part of the code, since it's only this part that doesn't work.
(the vector "random" is filled with random, but sorted, values between 0 and 200)
Updated the code:
#include <iostream>
#include <ctime>
#include <algorithm>
#include <vector>
using namespace std;
int binarySearch(int first, int last, int search4, vector<int>& random);
int main()
{
vector<int> random(100);
int search4, found;
int first = 0;
int last = 99;
found = binarySearch(first, last, search4, random);
system("pause");
return(0);
}
int binarySearch(int first, int last, int search4, vector<int>& random)
{
do
{
int mid = (first + last) / 2;
if (search4 > random[mid])
first = mid + 1;
else if (search4 < random[mid])
last = mid - 1;
else
return mid;
} while (first <= last);
return -(first + 1);
}

It depends on if you want to pass the vector as a reference or as a pointer (I am disregarding the option of passing it by value as clearly undesirable).
As a reference:
int binarySearch(int first, int last, int search4, vector<int>& random);
vector<int> random(100);
// ...
found = binarySearch(first, last, search4, random);
As a pointer:
int binarySearch(int first, int last, int search4, vector<int>* random);
vector<int> random(100);
// ...
found = binarySearch(first, last, search4, &random);
Inside binarySearch, you will need to use . or -> to access the members of random correspondingly.
Issues with your current code
binarySearch expects a vector<int>*, but you pass in a vector<int> (missing a & before random)
You do not dereference the pointer inside binarySearch before using it (for example, random[mid] should be (*random)[mid]
You are missing using namespace std; after the <include>s
The values you assign to first and last are wrong (should be 0 and 99 instead of random[0] and random[99]

You'll have to pass the pointer to the vector, not the vector itself. Note the additional '&' here:
found = binarySearch(first, last, search4, &random);

You're passing in a pointer *random but you're using it like a reference &random
The pointer (what you have) says "This is the address in memory that contains the address of random"
The reference says "This is the address of random"

Anytime you're tempted to pass a collection (or pointer or reference to one) to a function, ask yourself whether you couldn't pass a couple of iterators instead. Chances are that by doing so, you'll make your function more versatile (e.g., make it trivial to work with data in another type of container when/if needed).
In this case, of course, there's not much point since the standard library already has perfectly good binary searching, but when/if you write something that's not already there, being able to use it on different types of containers is often quite handy.

found = binarySearch(first, last, search4, &random);
Notice the &.

You're using the argument as a reference but actually it's a pointer. Change vector<int>* to vector<int>&. And you should really set search4 to something before using it.

If you use random instead of * random your code not give any error

Related

I am trying to reverse an array using loop in cpp ? but don't know what the problem is?

#include <iostream>
using namespace std;
int* reverse(int arr[],int n){
int rev[100];
int j =0;
for(int i=n-1;i>=0;i--){
rev[j]=arr[i];
j++;
}
return rev;
}
int main() {
int n;
cin>>n;
int arr[100];
for(int i=0;i<n;i++){
cin>>arr[i];
}
cout<<reverse(arr,n);
}
I am trying reverse an array using loops but don't know what the error was it was returning some bin value.
Your rev temporary resides in automatic storage. It means that the object will be gone after the function returns. While C++ allows you to decay rev to an int* and then return said pointer, it does not mean that this returns the object itself. You merely get a pointer to an already destroyed object. Not very useful. In fact, doing anything with this pointer will cause undefined behaviour.
Usually what you want to do is reverse things in-place. That's also how std::reverse works.
So, there are two options. If you have a completely filled c-style array, you could write a reverse function like this:
template <std::size_t N>
void reverse(int (&a)[N]) {
// reverse a from 0 to N-1
}
reverse(a);
Or, if you have an only partially filled array, take a page out of the standard library and reverse a range, denoted by two iterators.
void reverse(int* begin, int* end) {
/* begin points to the first entry, end points one past the last */
}
reverse(a, a+n);
Of course, instead of using c-style arrays, you could use a dynamically growing array such as std::vector, which carries the actual size of the array around for you.

Find minimum and maximum of a long vector

I want to find both the minimum and maximum of a long vector. The following code works, but I need to traverse the vector twice.
I could use an old fashioned for loop, but I wonder if there is an elegant (c++11, std) way of doing it.
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char** argv) {
vector<double> C;
// code to insert values in C not shown here
const double cLower = *min_element(C.begin(), C.end());
const double cUpper = *max_element(C.begin(), C.end());
// code using cLower and cUpper
}
You mean like std::minmax_element?
auto mm = std::minmax_element(std::begin(c), std::end(c));
const double cLower = *mm.first;
const double cUpper = *mm.second;
Note this assumes the range is not empty (as does your existing solution), else the iterator dereferences are Undefined Behaviour.
Also note this is not quite the same as your solution, as max_element returns the first largest element, and minmax_element returns the last largest element. E.g.
1 2 1 2
^ ^
A B
Where A is found by your solution, and B is found by mine. (This is for reasons of stability; Alex Stepanov got the definition of max wrong in the original STL.)

c++: how to determine if a variable is a vector element

I have a method, which i want to execute differently depending on if the passed variable is an element of a vector or not, like for example:
void method(int a){
if (/*a is an element of a vector*/) //do one thing
else //do another thing
}
and then in main:
vector<int> a;
a.pushback(1);
int b = 1;
method(a[0]); // does one thing
method(b); // does the other thing
What is the simplest way to do that?
Well, for all cases this is impossible, because it actually requires your function to look at how it is executed, and there is no such thing in C++. The hated eval() comes to mind.
But in a certain case, when your vector is a global entity, you could pass your variable by link instead of value. Then, you can check if it fits the space between the start and end of the desired vector. This is how it is done(not tested though, but should work)
vector<int> v;
//fill it somewhere somehow
void method(int& a)
{
int* beg = v.data();
int* end = beg + v.size();
int* val = &a;
if ((val >= beg) && (val < end))
{
//it is a part of vector
}
else
{
//it is not a part of vector
{
}
Problem is that you really shouldn't do it this way... As people in the comments said, it DOES look like an XY problem.
An int is an int. An int does not wear a label around its neck, telling everyone where it came from. When an int is passed to a function, there is nothing that specifies where the int originates.
You should take this as an opportunity to learn about iterators, and implement an overloaded method that takes either an
void method(int);
for a parameter, or a
void method(std::vector<int>::iterator iter);
for a parameter (or, perhaps, a const_iterator), and invoke the alternative method() by passing it an iterator to the int in your vector.

IOS C++ forbids comparison between pointer and integer (Not using strings)

I included the "not using strings" part in the title because when I was searching to find an answer on here I saw this problem a lot but it was with people using strings and getting chars mixed up. This is not my issue.
Trying to call an element of a 2D vector and see if it equals a certain number. I'm getting the comparison between pointer/integer error and I don't understand why. Here's my code, any help would be really appreciated.
bool UsedInRow(vector< vector<int> > vec(int n, vector<int> (int n)), int row, int num)
{
int n;
for (int col = 0; col < n; col++)
{
if (vec[row][col] == num)
{
return true;
}
}
return false;
}
Try this:
bool UsedInRow(const vector< vector<int> >& vec, int row, int num) { ... }
The expression you used vector< vector<int> > vec(int n, vector<int> (int n)) is actually a function pointer.
The compiler thinks that you are passing a function pointer.
Instead, pass the vector by reference:
bool UsedInRow(vector< vector<int> > &vec, int row, int num)
As the other answers point out, vec is a function pointer, not a vector.
You're being advised to change vec to a vector, but it's not clear that that's the right solution. There's no ambiguity in your declaration; vec is defined as a parameter of function pointer type.
If that's what you intended, you need to replace the reference to vec inside the function with a function call. For example, you might change
if (vec[row][col] == num)
to
if ((vec(42, something))[row][col] == num)
where something would itself have to be a function pointer, pointing to a function that takes an int argument and returns a vector<int> result.
The declaration of your UsedInRow function is quite complicated, and I can't tell how it's intended to be used.
If vec really should be just a vector, then you can make it one by deleting the (int n, vector<int> (int n)) part of the parameter declaration -- but then I'd have to wonder why you wrote it in the first place.
For a definitive answer, you'd need to explain to us what your UsedInRow function is supposed to do.

Mergesort for strings

I am quite new for C++ programming, and recently wrote a mergesort method to sort some arrays. For my personal test, it works fine for integers and doubles. But when I try to sort strings, it gives me a "sematic issue" error which I am quite confused. The full code is:
#include <iostream>
#include <string>
using namespace std;
template<typename T>
class Sorting{
public:
static void merge(T* a, int left, int mid, int right){
int i=left; int j=mid+1; int k=0;
T t[right-left+1]; //****************ERROR LINE
for(;i<=mid && j<=right;k++){
if(*(a+i)<=*(a+j)){
t[k]=a[i];
i++;
}
else{
t[k]=a[j];
j++;
}
}
for(;i<=mid;i++,k++) t[k]=a[i];
for(;j<=right;j++,k++) t[k]=a[j];
for(i=0;i<k;i++) a[left+i]=t[i];
}
//Mergesort top-level function. Left is starting index, right is ending index
static void mergesort(T* a, int left, int right){
if(left>=right) return;
int mid=left+((right-left)>>1);
mergesort(a, left, mid);
mergesort(a, mid+1, right);
merge(a, left, mid, right);
}
};
int main(){
const int len=5;
string ss[len]={
"Yep",
"Nope",
"5",
"2.5",
"Stackoverflow"
};
double ar[len]={4.2, 3, 5.6, -15, 0};
Sorting<double>::mergesort(ar, 0, 4); for(int i=0; i<len;i++) cout<<ar[i]<<endl;
Sorting<string>::mergesort(ss, 0, 4); for(int i=0; i<len;i++) cout<<ss[i]<<endl;
return 0;
}
And I got a semantic error at that "//**ERROR LINE" like:
Variable length array of non-POD element type 'std::__1::basic_string<char>'
What is this error talking about? How should I modify my code?
In the error message, POD refers to plain old data type
You could use a std::vector of them, i.e.
std::vector<T> t;
t.resize (right-left+1);
You could also make t an array of pointers (i.e. T* t[right-left+1]; and update the code accordingly).
BTW, you are using variable length array, which is a GCC extension that some other compilers don't provide.
But sorting is available in C++ standard library. You'll need to #include<algorithm> and use std::sort on standard C++ containers.
You have a variable length array:
T t[right-left+1];
This is an extension supported by your particular compiler, and not part of the C++ Standard. It doesn't work for complex object types like std::string - hence the error message. You could replace it with a vector:
std::vector<T> t(right - left + 1);
Basile's idea to use pointers is better though - copying std::string objects around is pretty heavyweight (i.e. memory intensive, slow)... you just want to keep track of which a[] elements to move, rather than sorting copies of them then copying them back.