I am creating a recursive formula to add up all the elements in a vector. The problem them I'm having is that my result is not adding to the vector results so it always returns 0. I have tried static_cast to turn it into an int but I'm still not able to figure it out. Here's my code:
long vectorSum(const std::vector<int>& data, unsigned int position) {
int ret = 0;
if(position == data.size()-1) {
return ret;
} else {
ret += data[position];
return vectorSum(data, position+1);
}
}
I am calling the function like this:
std::vector<int> test1;
for(int i = 0; i < 10; i++) {
test1.push_back(i);
}
cout << vectorSum(test1, 0) << "\n";
This is not correct:
ret += data[position];
return vectorSum(data, position+1);
The new value of ret (+= data[position]) isn't being used anywhere or passed back to the caller.
Remeber: ret is strictly local to each invocation of vectorSum(). It doesn't exist outside of your vectorSum(); it's being set to "0" every time you invoke vectorSum().
long vectorSum(const std::vector<int>& data, unsigned int position) {
if(position == data.size())
return 0;
else
return data[position]+vectorSum(data, position+1);
}
Then call it as
int sum=vectorSum(data,0);
Normally, one adds to the value of a recursive call. You are not doing that. In your code, it will keep calling with a modified position until it hits the terminating condition, then that return 0; goes all the way back up to the caller.
long vectorSum(const std::vector<int>& data, unsigned int position) {
int ret = 0;
if(position == data.size()-1) {
return ret;
} else {
ret += data[position]; //this line has no affect on the result!
return vectorSum(data, position+1); //you don't accumulate anything
//this will always return 0
}
}
Instead, you want to add the current value plus the value from the recursive call:
long vectorSum(const std::vector<int>& data, unsigned int position) {
if(position == data.size()-1) {
//terminating condition, return 0
return 0;
} else {
//add current value plus value from processing the rest of the list
return data[position] + vectorSum(data, position+1);
}
}
As a side note: recursion is a great tool, but it can easily be misused by applying it to problems that already have better and more elegant solutions. For this, something like std::accumulate would probably be the most "natural" solution for C++.
Related
I am trying to write a recursive function for linear search in an array which also returns the first index at which the element is found.
int linearSearch(int *A, int size, int val)
{
if(size>0)
{
if(*A==val)
{
cout<<val<<" is found in the array!";
return i;
}
else
{
linearSearch(A+1,size-1,val);
i++;
}
}
else
{
cout<<val<<" is not there in the array!";
return -1;
}
}
However, when I am trying to catch the valued returned in the main function, value of size is returned instead of -1 in the case when the element is not present in the array. I am not able to figure out why is that happening.
Try this. I added a couple of comments in the code so you can understand it better.
/* i is the initial position. When you are making a call to linearSearch it should be set to 0 */
int linearSearch(int *A, int size, int val, int i)
{
/* When you reach end of the array and havent found value, then return -1 */
/* Every recursive function should have an exit condition */
if(i == size)
return -1;
/* when we found a value return the index */
if (A[i] == val)
return i;
else
/* If not then move to the next value in the array by incrementing index and recurse */
return linearSearch(A, size, val, i + 1);
}
I am new to programming and have an exercise in which I create a function to check whether an array of type char hold particular values.
Here is my function:
bool arrCheck(char n[],char pos1,char pos2,char pos3,int size)
{
int n1,n2,n3;
for (int i=0;i<size;i++)
{
if (n[i]==pos1)
{
n1=1;
}
if (n[i]==pos2)
{
n2=1;
}
if (n[i]==pos3)
{
n3=1;
}
}
if ((n1==1)&&(n2==1)&&(n3==1))
{
return true;
}
}
here is my test program:
int main()
{
char a[5]={'6','1','a','a','a'};
if (arrCheck(a,'1','6','9',5))
{
cout<<"true\n";
}
}
I thought the result is supposed to be false but all I got is true. What did I do wrong?
n1, n2 and n3 are default-initialized and they have indeterminate values at first. Initialize them before checking their values. Also do not forget to return something even when the condition is false.
Try this:
bool arrCheck(char n[],char pos1,char pos2,char pos3,int size)
{
int n1=0,n2=0,n3=0;
for (int i=0;i<size;i++)
{
if (n[i]==pos1)
{
n1=1;
}
if (n[i]==pos2)
{
n2=1;
}
if (n[i]==pos3)
{
n3=1;
}
}
return (n1==1)&&(n2==1)&&(n3==1);
}
Using boolto store boolean values and using const to mark that the contents of array won't be changed may be better .
bool arrCheck(const char n[],char pos1,char pos2,char pos3,int size)
{
bool n1=false,n2=false,n3=false;
for (int i=0;i<size;i++)
{
n1=n1||(n[i]==pos1);
n2=n2||(n[i]==pos2);
n3=n3||(n[i]==pos3);
}
return n1&&n2&&n3;
}
1) Use a bool variable instead of three int variable
2) Initialize it (You have not initialized the int variable and they have random garbage value)
3) Also add else condition to return false value (Your code is not returning false).
4)Also print false in main function using else condition.
Hope this helps you..!
THE CODE IS ALRIGHT. You just forgot to add some statements and this is causing the error (it might or might not have been silly on your part).
Your definition of the function arrCheck() is incomplete. It returns true if a certain condition is fulfilled but what if it isn't? In that case, you must return false. But in your code, false is never returned. So firstly, you've gotta add an else statement after the last if statement in the arrCheck() method to this:
if((n1==1)&&(n2==1)&&(n3==1)){
return true;
}
else{
return false; //this has to be added
}
It can now return false if such a case is encountered.
Also, you must display "false" in the main method if arrCheck() returns false. You are recommended to add an else statement after the if statement in the main() method. See the modification below:
if (arrCheck(a,'1','6','9',5))
{
cout<<"true\n";
}
else{
cout<<"false\n"; //it must show false;
}
Once you correct these, your code will produce the correct output.
P.S. This answer serves as an elaboration of the answer earlier submitted by #KUSHAGRA GUPTA.
int n1,n2,n3;
This line leads to undefined behaviour because you do not initialise the variables yet attempt to read from them later on even if not all of them have been assigned a value:
if ((n1==1)&&(n2==1)&&(n3==1))
Fix the undefined behaviour by initialising the variables to 0:
int n1 = 0;
int n2 = 0;
int n3 = 0;
There is another case of undefined behaviour when your function does not state what to return if the condition is not true. Fix this, too:
if ((n1==1)&&(n2==1)&&(n3==1))
{
return true;
}
else
{
return false;
}
Or simply:
return (n1==1)&&(n2==1)&&(n3==1);
change that line to like this.int n1= 0,n2= 0,n3 = 0;
because when uninitialized these variable have garbage values.
bool arrCheck(char n[],char pos1,char pos2,char pos3,int size)
{
int first = 0,second = 0, third = 0;
for (int i=0;i<size;i++) {
if (n[i]==pos1) {
first = 1;
} else if (n[i]==pos2) {
second = 1;
} else if (n[i]==pos3) {
third = 1;
}
}
if( first+ second + third == 3)
return true;
else
return false;
}
Can someone please explain with a simple example what precisely is the difference between calling and returning a recursive function in c++?
Here is my code which seeks to find a character in a string recursively. It works fine when I just call find(); the function displays an integer value, But, when I code return find(letter,word), it gives the correct result as either a 1 or 0. Thanks
bool find(char f,string str)
{
static int len = str.length() - 1;
static int count = 1;
if (len<0)
{
return false;
}
else
{
if (str[len] == f)
{
return true;
}
else
{
len--;
return find(f, str);
}
}
}
You don't return the function you return the result of the call.
Here a basic example of recursion :
unsigned int factorial(unsigned int n)
{
if (n == 0)
return 1;
return n * factorial(n - 1);
}
If we call the function with n == 2 the program will do:
1) factorial (2) => return 2 * factorial(1); // It calls factorial with n == 1, do the multiplication and then return the result.
2) factorial(1) => return 1 * factorial(0); // same here with n == 0
3) factorial(0) => return 1; // from here the program will come back from the calls with the results
4) factorial(1) => return 1 * 1; => return 1;
5) factorial(2) => return 2 * 1; => return 2;
Few other things : be aware that your code will only work once as you use static int len, and count is a useless variable.
The function signature indicates a return value, so you need to embed the function call in a return statement for a value to be returned by the function, especially when neither of the if-conditionals are true.
Consider the following code (a variant of what the OP provided):
#include <iostream>
using namespace std;
int find(char f,string str) {
static int len = str.length() - 1;
static int count = 1;
int temp = 0;
if (len < 0) {
cout << count << "\n";
return -99;
}
else
if ( str[len] == f) {
return len;
}
len--;
count++;
temp = find( f, str );
cout << temp << "\n";
return temp;
}
int main() {
char ch = 'z';
int res = find(ch,"I");
if (res < 0) {
cout << "Letter '" << ch << "' was not found";
}
return 0;
}
See demo
Note that find() has a return value of -99 when the letter is not found. That value is captured by temp in find() and the function then returns the value of temp.
Now, consider main() -- its signature also indicates a return value, although it is discarded. If you attempt to execute the code without returning some kind of an integer in main(), the execution will be flawed.
So, whether you use a function recursively or not, if the function's signature indicates a return value then you need to return a value of the expected type. Since find() may return -99 or the position of the found letter, when it executes it will evaluate as one of those two values which will be returned by means of the return statement.
I am writing two functions in a program to check if a string has an assigned numeric code to its structure array or if the given numeric code has an assigned string in the same structure array. Basically, if I only know one of the two, I can get the other. I wrote the following:
int PrimaryIndex::check_title_pos(std::string title) {
bool findPos = true;
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
} else {
return -1;
}
}
std::string PrimaryIndex::check_title_at_pos(int pos) {
bool findTitle = true;
if (findTitle) {
for (int p = 1; p <= 25; p++) {
if (my_list[p].tag == pos) {
return my_list[p].title;
}
}
} else {
return "No title retrievable from " + pos;
}
}
However, it says not all control paths have a return value. I thought the else {} statement would handle that but it's not. Likewise, I added default "return -1;" and "return "";" to the appropriate functions handling int and string, respectively. That just caused it to error out.
Any idea on how I can keep this code, as I'd like to think it works but cant test it, while giving my compiler happiness? I realize through other searches that it sees conditions that could otherwise end in no returning values but theoretically, if I am right, it should work fine. :|
Thanks
In the below snippet, if s iterates to 26 without the inner if ever evaluating to true then a return statement is never reached.
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
}
I have following code:
std::vector<std::string> GetSameID(std::vector<string>& allFiles, int id) {
std::vector<std::string> returnVector;
for(std::vector<string>::iterator it = allFiles.begin(); it != allFiles.end(); ++it) {
if(GetID(*it) == id) {
int index = (*it).find("_CH2.raw");
if(index > 0) {
continue; //this works
}
if(0 < ((*it).find("_CH2.raw"))) {
continue; //this doesn't
}
string ext = PathFindExtension((*it).c_str());
if(ext == ".raw") {
returnVector.push_back(*it);
}
}
}
return returnVector;
}
My issue is, why is the if(0 < ((*it).find("_CH2.raw"))) not working that way? My files are named
ID_0_X_0_Y_128_CH1.raw
ID_0_X_0_Y_128_CH2.raw
(different ID, X and Y, for Channel 1 and Channel 2 on the oscilloscope).
When I do it the long way around (assign index, and then check index), it works, I don't understand though why the short version, which is more readable imo, is not working.
According to http://en.cppreference.com/w/cpp/string/basic_string/find, string::find() returns a size_t -- which is an unsigned type -- so it can never be less-than zero.
When it doesn't find something, it returns string::npos, which is also an unsigned type, but when you shove it into an int (implicitly converting it) it becomes a negative value -- this is why your first set of code works.