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.
Related
I am trying to create a sorting function with the parameters being a pointer of a list and I am trying to access an element of the given list. Hopefully this code speaks for the problem better than I can:
void bubbleSort(std::vector<int> *L) {
unsigned int i = 0; int temp;
while(isSorted(*L)) {
if(i==L->size()-1) {
i = 0;
}
if(i<L[i]/*<-ERROR here.*/) {
temp = L[i+1]; // ERROR HERE
L[i+1] = L[i]; // ERROR HERE
L[i] = temp; // ERROR HERE
}
}
}
You don't need to painfully dereference every individual use of L (and indeed doing so is error-prone, as you've demonstrated by missing one in your answer).
Instead, just write:
void bubbleSort(std::vector<int> *Lptr) {
auto &L = *Lptr;
and keep the rest of the code the same.
NB. It would be even better to change the function itself, to
void bubbleSort(std::vector<int> &L) {
as it should have been written in the first place, but I'm assuming there's some artificial reason you can't do that.
The function accepts a pointer to an object of type std::vector<int>.
void bubbleSort(std::vector<int> *L) {
To access the original vector using the pointer, you can write either *L or L[0]. That is, both expressions yield an lvalue reference of type std::vector<int> & to the vector.
To get the i-th element of the vector using the subscript operator through the pointer, you can write either (*L)[i] or L[0][i],
However, in this if statement:
if(i<L[i]/*<-ERROR here.*/) {
You are trying to compare the variable i of type unsigned int to the object L[i] of type std::vector<int>. When i is not equal to 0, this yields a non-existent object of the vector type.
It seems you mean something like the following instead:
if ( (*L)[i] < (*L)[i+1] ) {
or:
if ( L[0][i] < L[0][i+1] ) {
or, vice versa:
if ( L[0][i+1] < L[0][i] ) {
Depending on whether the vector is sorted in ascending or descending order.
Pay attention to the fact that there is no sense in declaring the parameter as a pointer to a std::vector<int>. The function would be much clearer and readable if it accepted the vector by reference instead:
void bubbleSort(std::vector<int> &L) {
In this case, the if statement would look like this:
if ( L[i] < L[i+1] ) {
Although I prefer to change the source code as other answer. But, for this question, you can use ->at() function to access the element in a vector pointer.
if(i<L->at(i)) {
temp = L->at(i+1);
L->at(i+1) = L->at(i);
L->at(i) = temp;
}
I have a function, as such:
void foo(int checkInt, vector<int> vect, int x) {
EXECx = x;
EXECcheckInt = checkInt;
if (EXECcheckInt > 0) {
//do something to vect
} else {
Timer.rset();
}
}
As can be seen, vect is left alone unless checkInt is above 0. So, if I want to pass checkInt 0, then it seems like I wouldn't have to worry about vect.
Therefore it would seem to me that I need some dummy value to go into this function for vect, so what value would work, or do I need to pass a dummy vector? My idea was to just pass 0, but I'm guessing that wouldn't work.
I tried to cast it, as in foo(0,(vector<int>)0,0), but I was surprised that when I tried to print out vect, it just showed up as empty (no 0 inside it), with the function written as so:
void foo(int checkInt, vector<int> vect, int x) {
for (auto i = vect.begin(); i != vect.end(); ++i)
std::cout << *i << ' ';
}
How should I go about this?
I'm working with C++98.
The code looks like the function decides whether the vector is used or not but what you want to do suggests that it is the caller who decides if the vector is used or not. Who is it really? I think you have a design problem, fix that then you dont need to cast a 0 to a vector anymore. (eg make two functions, one taking a vector, the other taking no vector as parameter)
Anyhow, you may want to look at std::optional which is only available since C++17, but it might give you some inspiration on how to handle such situation in a clean way. The "dirty" way is to pass a pointer and then check if it is a nullptr inside the function.
Your casts does not create a vector filled with 0 but a vector with size 0.
Change the function declaration to accept a reference of the vector to avoid copying memory unnecessarily like so:
void foo(int checkInt, vector<int>& vect, int x)
If you already have a vector object then you can pass that even if it is not used. If you need to construct a dummy vector then you can call the function like this:
vector<int> v;
foo (0, v, x);
You could provide an overload that can be called without the vector. You can refactor the common part into a subfunction:
void foo(int checkInt, vector<int> vect, int x) {
if (checkInt > 0) {
bar(checkInt, x);
//do something to vect
} else {
foo(checkInt, x);
}
}
void foo(int checkInt, int x) {
assert(checkInt <= 0); // maybe unnecessary. depends on what you need
bar(checkInt, x);
Timer.rset();
}
void bar(int checkInt, int x) {
EXECx = x;
EXECcheckInt = checkInt;
}
// with vect
foo(checkInt, vect, x);
// without vect
foo(0, 0);
but I was surprised that when I tried to print out vect, it just showed up as empty (no 0 inside it)
It's unclear why that surprises you. As per documentation, the constructor of vector that accepts an integer creates that many elements into the constructed vector. A vector with 0 elements is empty.
Note that you probably should reconsider whether you would want to pass the vector by value. Are you sure that you need a copy?
I apologize if this question has already been answered (I tried searching around, but couldn't find anything quite the same, and similar questions' solutions didn't work), but how do I pass an object (in this case, a vector of objects) and have the function edit those values without returning anything?
Example:
void incVector(std::vector<int> vec)
{
for (auto l = 0; l < int(vec.size()); l++)
{
vec[l]++;
}
}
int main()
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
for (auto l = 0; l < int(vec.size()); l++)
{
std::cout << vec[l]; //Output: "12"
}
incVector(vec);
for (auto l = 0; l < int(vec.size()); l++)
{
std::cout << vec[l]; //Output: "12"
//This output should be "23"
}
}
Obviously, what I'm actually using this for is much more complex, but this is enough of an example to get the point of what I'm trying to do across. In the actual project, it's a rabbit hole of different functions, some of which return things while others don't, so having it simply return the vector isn't an option.
I have tried making incVector accept a reference to a vector, a pointer to a vector, a pointer to a reference to a vector, and a pointer to a pointer to a vector (which are solutions that seemed to work for other similar questions) but none of those are working for me.
EDIT:
God, I feel stupid. I swear I'd tried using a reference before and it didn't work. Yet now, trying it again works just fine. Sorry! ^^;
you pass the vector by value, thus modifications are purely local:
change prototype of your function to:
void incVector(std::vector<int> &vec)
to pass by reference and get the one from main modified
Take the argument by reference. You can also use a modern for-loop.
void incVector(std::vector<int>& vec)
{
for (auto& l : vec)
{
++l;
}
}
But you don't actually need to do any of this. Applying an operation on each element of the vector can be done easily using a standard algorithm (std::for_each) and a lambda function that takes a reference to the vector's element:
#include <algorithm>
// ...
std::for_each(vec.begin(), vec.end(), [](int& l){ ++l; });
for_each is going to call the lambda for each element in the vector and pass it as the argument. Since you take the argument by reference (int&), incrementing it will increment the actual element contained in the vector.
The key point to take away from this however, is that when you want to give a new name to an object that already exists, you use a reference. Those are declared with & before their identifier:
int i = 0;
int &i_ref = i;
Here, i_ref is a reference to i, meaning it's just another name for i. Modifying i_ref is the same as modifying i.
The same applies to function arguments. If a function argument is a reference, it means it's another name for the object that was passed to the function. Modifying the reference is the same as modifying the object that was passed to the function.
I got this library of mathematical routines ( without documentation ) to work on some task at college. The problem I have with it is that all of its functions have void return type, although these functions call one another, or are part of another, and the results of their computations are needed.
This is a piece of ( simplified ) code extracted from the libraries. Don't bother about the mathematics in code, it is not significant. Just passing arguments and returning results is what puzzles me ( as described after code ) :
// first function
void vector_math // get the (output) vector we need
(
double inputV[3], // input vector
double outputV[3] // output vector
)
{
// some variable declarations and simple arithmetics
// .....
//
transposeM(matrix1, matrix2, 3, 3 ); // matrix2 is the result
matrixXvector( matrix2, inputV, outputV) // here you get the result, outputV
}
////////
// second function
void transposeM // transposes a matrix
(
std::vector< std::vector<double> > mat1, // input matrix
std::vector< std::vector<double> > &mat2, // transposed matrix
int mat1rows, int mat1columns
)
{
int row,col;
mat2.resize(mat1columns); // rows
for (std::vector< std::vector<double> >::iterator it=mat2.begin(); it !=mat2.end();++it)
it->resize(mat1rows);
for (row = 0; row < mat1rows; row++)
{
for (col = 0; col < mat1columns; col++)
mat2[col][row] = mat1[row][col];
}
}
////////
// third function
void matrixXvector // multiply matrix and vector
(
std::vector< std::vector<double> > inMatrix,
double inVect[3],
double outVect[3]
)
{
int row,col,ktr;
for (row = 0; row <= 2; row++)
{
outVect[row]= 0.0;
for (ktr = 0; ktr <= 2; ktr++)
outVect[row]= outVect[row] + inMatrix[row][ktr] * inVect[ktr];
}
}
So "vector_math" is being called by the main program. It takes inputV as input and the result should be outputV. However, outputV is one of the input arguments, and the function returns void. And similar process occurs later when calling "transposeM" and "matrixXvector".
Why is the output variable one of the input arguments ? How are the results being returned and used for further computation ? How this kind of passing and returning arguments works ?
Since I am a beginner and also have never seen this style of coding, I don't understand how passing parameters and especially giving output works in these functions. Therefore I don't know how to use them and what to expect of them ( what they will actually do ). So I would very much appreciate an explanation that will make these processes clear to me.
EXTRA :
Thank you all for great answers. It was first time I could barely decide which answer to accept, and even as I did it felt unfair to others. I would like to add an extra question though, if anyone is willing to answer ( as a comment is enough ). Does this "old" style of coding input/output arguments have its name or any other expression with which it is referred ?
This is an "old" (but still popular) style of returning certain or multiple values. It works like this:
void copy (const std::vector<double>& input, std::vector<double>& output) {
output = input;
}
int main () {
std::vector<double> old_vector {1,2,3,4,5}, new_vector;
copy (old_vector, new_vector); // new_vector now copy of old_vector
}
So basically you give the function one or multiple output parameter to write the result of its computation to.
If you pass input parameters (i.e. you don't intend to change them) by value or by const reference does not matter, although passing read only arguments by value might be costly performance-wise. In the first case, you copy the input object and use the copy in the function, in the latter you just let the function see the original and prevent it from being modified with the const. The const for the input parameters is optional, but leaving it out allows the function to change their values which might not be what you want, and inhibits passing temporaries as input.
The input parameter(s) have to be passed by non-const reference to allow the function to change it/them.
Another, even older and "C-isher" style is to passing output-pointer or raw-arrays, like the first of your functions does. This is potentially dangerous as the pointer might not point to a valid piece of memory, but still pretty wide spread. It works essentially just like the first example:
// Copies in to int pointed to by out
void copy (int in, int* out) {
*out = in;
}
// Copies int pointed to by in to int pointed to by out
void copy (const int* in, int* out) {
*out = *in;
}
// Copies length ints beginning from in to length ints beginning at out
void copy (const int* in, int* out, std::size_t length) {
// For loop for beginner, use std::copy IRL:
// std::copy(in, in + length, out);
for (std::size_t i = 0; i < length; ++i)
out[i] = in[i];
}
The arrays in your first example basically work like pointers.
Baum's answer is accurate, but perhaps not as detailed as a C/C++ beginner would like.
The actual argument values that go into a function are always passed by value (i.e. a bit pattern) and cannot be changed in a way that is readable by the caller. HOWEVER - and this is the key - those bits in the arguments may in fact be pointers (or references) that don't contain data directly, but rather contain a location in memory that contains the actual value.
Examples: in a function like this:
void foo(double x, double output) { output = x ^ 2; }
naming the output variable "output doesn't change anything - there is no way for the caller to get the result.
But like this:
void foo(double x, double& output) { output = x ^ 2; }
the "&" indicates that the output parameter is a reference to the memory location where the output should be stored. It's syntactic sugar in C++ that is equivalent to this 'C' code:
void foo(double x, double* pointer_to_output) { *pointer_to_output = x ^ 2; }
The pointer dereference is hidden by the reference syntax but the idea is the same.
Arrays perform a similar syntax trick, they are actually passed as pointers, so
void foo(double x[3], double output[3]) { ... }
and
void foo(double* x, double* output) { ... }
are essentially equivalent. Note that in either case there is no way to determine the size of the arrays. Therefore, it is generally considered good practice to pass pointers and lengths:
void foo(double* x, int xlen, double* output, int olen);
Output parameters like this are used in multiple cases. A common one is to return multiple values since the return type of a function can be only a single value. (While you can return an object that contains multiple members, but you can't return multiple separate values directly.)
Another reason why output parameters are used is speed. It's frequently faster to modify the output in place if the object in question is large and/or expensive to construct.
Another programming paradigm is to return a value that indicates the success/failure of the function and return calculated value(s) in output parameters. For example, much of the historic Windows API works this way.
An array is a low-level C++ construct. It is implicitly convertible to a pointer to the memory allocated for the array.
int a[] = {1, 2, 3, 4, 5};
int *p = a; // a can be converted to a pointer
assert(a[0] == *a);
assert(a[1] == *(a + 1));
assert(a[1] == p[1]);
// etc.
The confusing thing about arrays is that a function declaration void foo(int bar[]); is equivalent to void foo(int *bar);. So foo(a) doesn't copy the array a; instead, a is converted to a pointer and the pointer - not the memory - is then copied.
void foo(int bar[]) // could be rewritten as foo(int *bar)
{
bar[0] = 1; // could be rewritten as *(bar + 0) = 1;
}
int main()
{
int a[] = {0};
foo(a);
assert(a[0] == 1);
}
bar points to the same memory that a does so modifying the contents of array pointed to by bar is the same as modifying the contents of array a.
In C++ you can also pass objects by reference (Type &ref;). You can think of references as aliases for a given object. So if you write:
int a = 0;
int &b = a;
b = 1;
assert(a == 1);
b is effectively an alias for a - by modifying b you modify a and vice versa. Functions can also take arguments by reference:
void foo(int &bar)
{
bar = 1;
}
int main()
{
int a = 0;
foo(a);
assert(a == 1);
}
Again, bar is little more than an alias for a, so by modifying bar you will also modify a.
The library of mathematical routines you have is using these features to store results in an input variable. It does so to avoid copies and ease memory management. As mentioned by #Baum mit Augen, the method can also be used as a way to return multiple values.
Consider this code:
vector<int> foo(const vector<int> &bar)
{
vector<int> result;
// calculate the result
return result;
}
While returning result, foo will make a copy of the vector, and depending on number (and size) of elements stored the copy can be very expensive.
Note:
Most compilers will elide the copy in the code above using Named Return Value Optimization (NRVO). In general case, though, you have no guarantee of it happening.
Another way to avoid expensive copies is to create the result object on heap, and return a pointer to the allocated memory:
vector<int> *foo(const vector<int> &bar)
{
vector<int> *result = new vector<int>;
// calculate the result
return result;
}
The caller needs to manage the lifetime of the returned object, calling delete when it's no longer needed. Faililng to do so can result in a memory leak (the memory stays allocated, but effectively unusable, by the application).
Note:
There are various solutions to help with returning (expensive to copy) objects. C++03 has std::auto_ptr wrapper to help with lifetime management of objects created on heap. C++11 adds move semantics to the language, which allow to efficiently return objects by value instead of using pointers.
I would like to know how to prototype a function that returns a array which also takes in an array. after prototyping the array how can i implement it
is this correct?
coffee* getData(*coffe);
int main() {
coffee cf[256];
coffee FinalCoffee[256];
FinalCoffee=getData(cf);
}
coffee getData(coffee objcf[]) {
for(int i=0;i<SIZE;i++) {
objcf[i].brand="nescafe";
}
return coffee;
}
Plsease do advice me on this. i need to be able to get back array so that i can pass the updated array to another function to process it.
Your code doesn’t even have matching declaration and function definition. This doesn’t work.
But the following does:
std::vector<coffee> getData(std::vector<coffee> const& objs) {
std::vector<coffee> result;
// Do something to fill result
return result;
}
But if, as in your example, you want to manipulate the original array, rather than returning a new one, then it makes more sense to not have a return value at all, and to pass the argument as a non-const reference:
void manipulateData(std::vector<coffee>& objs) {
for (auto& obj : objs)
obj.brand = "nescafe";
}
As a rule of thumb, try to avoid C arrays in favour of C++ standard library containers. This will make your life much, much easier.
You can do this in C++. References to the rescue. Ugly syntax ahead, typedefs are recommended:
#include <iostream>
using namespace std;
template<size_t N>
int (&f(int(&A)[N])) [N] {
for(auto& i: A) i +=10;
return A;
}
int main() {
int A[3] = {1,2,3};
auto& AA = f(A);
for(auto i: AA) cout << i << "\n";
}
But as, Konrad Rudolph noted, you actually do not need return anything from f(), your array is modified in place. And your function can be much simpler:
void f(int (&A)[N])
To start with, the declaration (prototype) and the definition (implementation) of the function headers are different:
coffee* getData(*coffe);
Versus
coffee getData(coffee objcf[])
The last one doesn't even return a pointer.
As for your question, your prototype says that getData returns a pointer but you assign it to an array. This will not work. Instead declare FinalCoffee as a pointer:
coffee cf[256];
coffee* FinalCoffee;
FinalCoffee=getData(cf);
However you don't really need that. When getData modifies the array you pass as argument, then those modifications will be in the cf array too as arrays are passed as references.