how to swap 2 variables using recursion - c++

i've tried to swap 2 variables using recursion.So i passed them by reference and nothing change in the main frame. But inside the function scope it works...Can anyone explain me how this code works inside the stack and if is there any other solution to swap varibles using recursion?
#include <iostream>
void swap(int &a, int &b) {
if (a>b)
{
swap(b,a);
}
}
int main()
{
int x = 10;
int y = 8;;
swap(x, y);
std::cout << x << ' ' << y;
return 0;
}

Simply switching the parameters in the recursive call doesn't actually swap the values of the variables in the caller, or anywhere else. There's no (sensible) way to write this recursively because swapping isn't a recursive procedure. Recursion is used when you're traversing a data structure with multiple elements, like an array or a tree, or you're manipulating numbers repeatedly over time, as in a Fibonacci sequence.
But here, there's no repeated decision to be had. All it is is "swap if a > b, otherwise don't", which is a simple if, plus one of the normal swapping approaches you described:
#include <iostream>
void swap_if_greater(int &a, int &b) {
if (a > b) {
std::swap(a, b);
}
}
int main() {
int x = 10;
int y = 8;
swap_if_greater(x, y);
std::cout << x << ' ' << y; // => 8 10
}
Note that I've renamed the function. swap implies an unconditional swap, but that's not what the function does. The function ensures the lower value will be in the first argument, so it's been renamed to swap_if_greater to reflect that. If you do want an unconditional swap, use std::swap.

Related

Why can't functions change vectors when they can change arrays?

I am trying to move from arrays to vectors in cpp for problem-solving and its overall benefits. I am facing some issues here even though this logic works on arrays.
#include <iostream>
#include <vector>
using namespace std;
void PrintArray(vector<int> v) { // O(n)
for (int i=0; i<v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
void LF1(vector<int> A) { // O(n)
int temp = A[0],i;
for (i=0; i<A.size()-1; i++)
A.at(i) = A.at(i+1);
A.at(i)=temp;
// PrintArray(A); <-- shows updated array here
}
void LF(vector<int> A, int d) {
d = d % (A.size());
cout << "d%n: " << d << endl;
for (int j=0; j<d; j++)
LF1(A);
PrintArray(A);
}
int main(int argc, char const *argv[]) {
vector<int> A;
int d;
for(int i=1; i<6; i++)
A.push_back(i);
PrintArray(A);
cout << "Enter number of Left rotations to perform : ";
cin >> d;
LF(A,d);
return 0;
}
Problem 1: When I am calling LF1 inside of LF it returns the same array without rotating but when I write the code for LF1 inside of LF it seems to rotate.
Problem 2: The PrintArray() prints the rotated array only when called from LF1() or just immediately after its code when written (instead of calling LF1()) in LF() when causes it to print the array d times. Where d is the required rotations.
Regarding what you're doing wrong...you are passing the vectors by value. You don't expect changes to an integer to affect it in the caller when you pass it as a value...
void SomeFunction(int i) {
i = i + 1;
printf("Inside SomeFunction %d\n", i); // changed, 11
}
int i = 10;
SomeFunction(i);
printf("Outside SomeFunction %d\n", i); // unchanged, 10
...if you wanted to see a change, you would have to pass a pointer, such as int *pi, and then update it as *pi = *pi + 1;
The same principle applies to vectors and other C++ classes. If you just pass it as a value, the whole vector is copied. (Well, if it needs to be, a temporary could just be reused). But for now think of it as being copied: just as there's a difference between passing an integer and a pointer-to-an-integer, there's a difference between a vector and a pointer-to-a-vector.
You could pass a pointer to the vector if you intend to change it...or... C++ offers another tool called the reference, where references are very much like pointers but with a few differences. If you just changed your arguments to vector<int> &A then your code should work, because the arrays would be "passed by reference" instead of getting copied when they are "passed by value", so changes would take effect. If you don't want a function to need to be able to modify an array but still want to avoid the copy, pass by const reference, e.g. const vector<int> &A (e.g. this is what your PrintArray() should use).
You might not want to get too hung up on the details of references for now, other than thinking of it as a "convenient kind of pointer where you don't have to put the * on all the places you want to dereference". But in case you want to know more specifics:
What are the differences between a pointer variable and a reference variable in C++?
I am facing some issues here even though this logic works on arrays.
And this is probably the source of your confusion. Which comes from the fact that C-style arrays decay into pointers under the hood:
Passing an Array by reference in C
I think that's something that it's reasonable to be confused by, given that other types (such as integers and vectors) don't. It's just a quirk of C, that C++ inherited. So when C++11 wanted to clean that up, a wrapper class called std::array was introduced:
https://embeddedartistry.com/blog/2017/6/28/an-introduction-to-stdarray
https://en.cppreference.com/w/cpp/container/array
But C++ also has an algorithm to do rotation...
So if you want to see a good example of how this would be done, it's a place to start:
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> v{1, 2, 3, 4};
std::rotate(v.begin(), v.begin() + 1, v.end());
for (auto &i : v)
std::cout << i << " ";
std::cout << "\n";
}
That will get you 2 3 4 1. The documentation has other examples, read through:
https://en.cppreference.com/w/cpp/algorithm/rotate

Using Arrays in functions in C++

I am a student who is doing an assignment for C++ and I have encountered something I am very unfamiliar with. I have an int array with no size but a list of numbers. After it's creation, there is a function call inside a function that has that array as a parameter with an index in it.
For example:
for (int x = 0; x < CAPACITY, x++)
functionCall(array[x]);
Now I am supposed to create a function so the call can work. However when I make my function:
void functionCall(int array[]);
It does not work because it cannot turn an int to an int[].
I guess my question is, how am I supposed to get that list of numbers created originally by the array if I have to call it in my function as if it isn't an array.
Right now if I just put as an int but not an array like it wants me to do it just gives me the number 5 but not any of the numbers in the array. For example:
void functionCall(int array);
Sincere thank you for anything and I apologize if this sounds confusing.
functionCall(array[x]);
This passes the xth element in the array to the function, so a single int.
array[2] = 5;
functionCall(array[2]); // This is the same as functionCall(5);
So in the function, you get the current element of the array. Not the array itself.
You cannot get the list inside the function, because you only give a single element of that list each time you call it.
Taking a wild guess, I suspect you are looking for something like the MCVE below:
#include <iostream>
void functionCall(int v) {
std::cout << v << " ";
}
void func(int array[], size_t CAPACITY) {
for (size_t x = 0; x < CAPACITY; x++)
functionCall(array[x]);
}
int main() {
int list[] = { 1,2,3,4,3,0, 42 };
func(list, std::distance(std::begin(list), std::end(list)));
return 0;
}

The rationale of C++ disallowing array of functions?

What is the underlying rationale (technical or conceptual) that C++ does not allow defining array of function type? E.g.
using fn_t = int(int);
fn_t ary[2]; // ERROR (ref: ISO/IEC-14882 [dcl.array])
Given two random functions I just made up:
int a( int x, int y )
{
return x * y;
}
int b( int x, int y )
{
int result = 0;
for (int xi = 1; xi <= x; xi++)
for (int yi = y; yi > 0; yi--)
result += xi * xi;
return result;
}
How do you suggest I put them in an array?
I could compile them, I suppose, then just have an array of max( sizeof(a’s bytecode), sizeof(b’s bytecode) ). But now I have some additional considerations:
Where does this array go?
Some processors can run code from anywhere in memory. Some cannot.
What about security attributes for the code?
What about relocation considerations?
How do I call this function?
Can I use the processor’s usual calling conventions?
Or will this require extra behind-the-scenes magic?
What happens when I want a pointer to the array?
What happens if I move the array and then call the pointer?
What about exceptions and other abnormal signal considerations?
This is just the tip of the iceberg. There are a lot of technical considerations to doing this kind of thing.
Which leads to the main consideration:
What advantage would this give over pointers to functions?
With a pointer to a function, I can do everything I otherwise wanted to do:
int (*fs)(int,int)[] = { a, b };
int x = fs[0]( 10, 10 );
int y = fs[1]( 10, 10 );
The language is designed with several goals — two of the most important being simplicity and flexibility.
Doing what you would reduces both simplicity and flexibility for everyone: compiler writers, compilers themselves, runtime management, speed, safety, etc.
EDIT:
tl;dr Because it offers no advantage over pointers or references to functions, but plenty of drawbacks.
What is the underlying rationale (technical or conceptual) that C++ does not allow defining array of function type?
What is a function? It's just some code at an address. Conceptually it's a singleton, since there is no reasonable way to copy one or allocate one on the heap. Why would you? It already exists. It has a name, and that name yields a function pointer - the address of the code.
There is a concept of a 'function object', which is more equivalent to the 'first class function' of high level languages like python or javascript.
But under the hood it's modelled as a structure containing the address of code (a function pointer) and some state.
There are a few ways to create an array of functions: (this code is c++14)
#include <functional>
#include <iostream>
int a(int i) {
std::cout << "called a with " << i << std::endl;
return i;
}
int b(int i) {
std::cout << "called b with " << i << std::endl;
return i + 1;
}
int c(int i) {
std::cout << "called c with " << i << std::endl;
return i + 2;
}
int main()
{
// make life easier by creating a typedef
using raw_fptr = int (*)(int);
// an array of function pointers
raw_fptr raw_ptrs[] =
{
a, b, c
};
// a typedef of a std::function object
using fobject = std::function<int(int)>;
// an array of function objects
fobject fobjects [] = {
&a, // can capture a function pointer
[](int i) -> int { // or a lambda
return b(i);
},
std::bind(&c, std::placeholders::_1) // or a binder
};
for (auto&& f : raw_ptrs)
f(0);
for (auto&& f : fobjects)
f(1);
}

Unwanted value changes in 1D and 2D arrays returning a value from a function in c++ code

I have a multi-file program that reads data from a file and stores the values in various arrays. The size of the arrays is not known during the compiling. After the values are stored, I use another function to determine the maximum and minimum of each array and return the max/min. Before the "return maximum" statement, the values in the array are correct. After "return maximum", the values are changed or erased.
Here is some of the code including one of the 2D arrays and one of the 1D arrays (there are a few more of those but I removed them so there's less code for you to look at)
**EDITED:
FunctionValues.h: ** removed destructor block
class FunctionValues
{
//define variables, set up arrays of unknown size
public:
float **xvel;
int *imax;
int vessels;
int tot_gridpt;
public:
//Constructor -- initialization of an object performed here
FunctionValues(): xvel(NULL), imax(NULL) {}
//Destructor
~FunctionValues() {
}
void read_function(string filename);
};
FunctionValues.cpp: (this reads a file with some imax values, vessel numbers and velocities and stores them in the appropriate arrays, the other includes are also there) All the arrays made are stored in FunctionValues myval object
#include "FunctionValues.h"
using namespace std;
void FunctionValues::read_function(string filename)
{
std::ifstream myfile(filename.c_str());
//acquire variables
myfile >> vessels; //number of vessels
imax = new int[vessels];
//... code reading the file and storing them, then imax and some other values are multiplied to get int tot_gridpt
xvel = new float *[vessels];
for (int i = 0; i < vessels; i++)
{
xvel[i] = new float[tot_gridpt];
}
//arrays filled
for (int i = 0; i < limiter; i++)
{
myfile >> xvel[count][i];
}
}
Gridpts.cpp: ** range() arguments and parameters
#include "FunctionValues.h"
#include "Gridpts.h"
using namespace std;
// forward declarations
float range(float **velocities, const FunctionValues *myval, int num);
void Gridpts::create_grid(FunctionValues *myval, int ptsnum)
{
//find range, 1 for max, 0 for min from smooth wall simulation results rounded to the nearest integer
float maximum = range(myval->xvel, &myval, 1);
float minimum = range(myval->xvel, &myval, 0);
}
range.cpp: ** arguments changed to pass by pointer
float range(float **velocities, const FunctionValues *myval, int num)
{
if (num == 1)
{
float maximum = 0;
for (int round = 0; round < myval->vessels; round++)
{
for (int count = 0; count < myval->tot_gridpt; count++)
{
if (velocities[round][count] > maximum)
{
maximum = velocities[round][count];
}
}
}
maximum = ceil(maximum);
return maximum;
}
main.cpp:
corner_pts.create_grid(&myval, ptsnum);
This is where the error occurs. cout << "CHECKPOINT: " << myval.xvel[0][0] before "return maximum;" gives -0.39032 which is correct. After "return maximum", causes nothing to be printed and then the program crashes when trying run range() again using the xvel array. Similarly for myval.imax[0].
I apologize for copying in so much code. I tried to only include the essential to what is happening with the array. I have only started programming for about a month so I'm sure this is not the most efficient way to write code but I would greatly appreciate any insight as to why the arrays are being changed after returning a float. Thank you in advance for your time. (And if I have broken any rule about posting format, please let me know!)
So your program crashes when you call range() the second time. Therefore, your issue is most likely there.
Your program is crashing because you are taking your FunctionValues parameter by value, which is then destroyed at the end of the scope of the function, since it is local to the function.
// issue with myval being taken as a copy
float range(float **velocities, FunctionValues myval, int num)
{
//...
} // destructor for local function arguments are called, including myval's destructor
Explanation
Your function parameter FunctionValues myval is taken by copy. Since you have no copy constructor defined, this means that the default copy behavior is used. The default copy behavior simply copies the object data from the supplied argument at the call site.
For pointers, since they hold addresses, this means that you are copying the addresses of those pointers into an object local to the range() function.\
Since myval is local to the range() function, its destructor is called at the end of the scope of the function. You are left with dangling pointers; pointers holding the memory addresses of memory that you have already given back to the free store.
Simplified example of your error:
#include <iostream>
class X
{
public:
X() : p{ new int{ 0 } }
{
}
~X()
{
std::cout << "Deleting!" << std::endl; // A
delete p; // B
}
private:
int* p;
};
void func(X param_by_value) // C
{
// ...
}
int main()
{
X x; // D
func(x); // E
func(x); // F
}
You have variable x (D). You use it to call the function func() (E).
func() takes a parameter of type X by value, for which the variable name is param_by_value (C).
The data of x is copied onto param_by_value. Since param_by_value is local to func(), its destructor is called at the end of func().
Both x and param_by_value have an int* data member called p that holds the same address, because of 3..
When param_by_value's destructor is called, we call delete on param_by_value's p (B), but x's p still holds the address that was deleted.
You call func() again, this time the same steps are repeated. x is copied onto param_by_value. However, this time around, you try to use memory that has been given back to the free store (by calling delete on the address) and (luckily) get an error. Worse yet, when main() exits, it will attempt to call x's destructor again.
You need to do some research into function parameters in C++. Passing by value, passing by reference, passing by pointer, and all of those combined with const.
As user #MichaelBurr points out, you should also look up the rule of three (and rule of five).
I'm just wondering why you opted not to use functionality like std::max/min_element in and std::valarray/vector to allocate a contiguous chunk of memory?
Worse case scenario, if you're a fan of the explicit nature of 2d arrays x[a][b] you could create a basic matrix:
template <typename T>
class Matrix {
public:
Matrix(std::valarray<int>& dims) : dims(dims) {}
Matrix(std::valarray<int>& dims, std::valarray<T>& data) : dims(dims), data(data) {}
std::Matrix<T> Matrix::operator[](int i) {
auto newDims = std::valarray<int>(dims[1], dims.size() - 1);
auto stride = std::accumulate(std::begin(newDims), std::begin(newDims) + newDims.size(), 1, [](int a, int b){ return a * b; })
auto newData = std::valarray<T>(data[i * stride], data.size() - (i * stride));
return Matrix<T>(newDims, newData);
}
protected:
std::valarray<T> data;
std::valarray<int> dims;
}
I think more reliance on the standard libraries for their correctness will likely solve any memory access/integrity issues.

Change given function parameter within the function c++

I wrote an function called swap to swap given two elements within the function. But when I use it in another function, it doesn't work. How to get it work?
#include <iostream>
using namespace std;
void swap(int *a, int * b){
int temp=*a;
*a=*b;
*b=temp;
}
void sum(int x, int y){
int *a;
a = &x;
int *b;
b=&x;
swap(a,b);
//cout << x << endl << y << endl;
}
int main(){
int a=0, b=1;
//swap(a,b);
sum(a,b);
cout << a << endl << b << endl;
return 0;
}
b=&x;
should be
b=&y;
Also, you are swapping local copies. sum should be:
void sum(int& x, int& y)
Also, this already exists. It's called std::iter_swap.
You probem not in swap, but in sum function, you pass x an y by value and modify and swap copyies of values later to fix this you need to change void sum(int x, int y){ to void sum(int& x, int& y){ this will leads to x and y being passed by reference so that sum will be able to update them.
I guess by 'wrong' you mean the output of the last cout doesn't show 'a' and 'b' as you'd expect. But you're passing them to 'sum' by value.
I assume you are just learning about pointers and references.
Your function swap swaps the contents of two pointers. Note that you have put in using namespace std and std also has a swap function so I would suggest removing that from your source, albeit yours will be a closer match if you pass in pointers to ints.
Your function called sum is a clear misnomer as it doesn't actually sum or add anything, it tries to do a swap by calling the pointer version.
To fix your particular bug, it would have to take its parametesr by reference, and b should point to y, not x.
x and y are passed by value to sum so swap is working on a local copy not the actual variables from main. You will also need to modify sum and your call to swap:
void sum(int &x, int &y)
^ ^
{
// other code
swap(&x,&y);
^ ^
}
If you leave you call to swap like this:
swap(x,y);
you will actually call std::swap. I am going to assume you will be adding more code to sum otherwise the name is not consistent with what it does.