Have no idea why this problem is so hard for me. Iteratively, this is cake but as soon as the stack unwinds it destroys my entire function.
It finds the needle correctly and gives the function a value of true if it finds it. However, it keeps reverting back to false as soon as the call stack is unwound. Does anyone know how to remedy this or what I'm doing wrong with my code?
Here is what I have so far...
bool mySubStr(char * needle, char * haystack)
{
int needleLength = strlen(needle);
int haystackLength = strlen(haystack);
bool found = false;
if(needleLength < haystackLength)
{
if(strncmp(haystack, needle, needleLength) == 0)
{
found = true;
}
else
{
mySubStr(needle, haystack + 1);
}
}
return found;
}
You need to return the result of the recursive call to mySubStr(..):
bool mySubStr(char * needle, char * haystack)
{
int needleLength = strlen(needle);
int haystackLength = strlen(haystack);
if(needleLength > haystackLength)
return false;
if(strncmp(haystack, needle, needleLength) == 0)
{
return true;
}
return mySubStr(needle, haystack + 1);
}
In your implementation, you were calling the function recursively but were discarding the result:
else
{
mySubStr(needle, haystack + 1);
}
}
return found;
So in effect, unless the needle happened to be right at the beginning, your function would always return false.
Related
I've been trying to get a better understanding of recursive functions, and I was working on a problem trying to figure out why it wasn't working properly.
I want it to go through the array, and when it finds a 0, to return true.
But the function stills return true when there's no zero.
Here is my code:
bool containZero(int randomArray[], int length)
{
if(randomArray[length] == 0)
return true;
else
{
return containZero(randomArray, length - 1);
}
}
Your algorithm is not handling the possibility that the array may not actually contain a zero. You need to stop iterating when the end of the array is reached.
You are also accessing the array out of bounds from the very 1st iteration, and also if no zero is found.
Not only that, but there is no branch of your recursion logic that ever returns false. Your return statements are always returning true.
Try this instead:
// this searches backwards...
bool containZero(int randomArray[], int length)
{
if (length <= 0)
return false;
--length;
if (randomArray[length] == 0)
return true;
return containZero(randomArray, length);
}
Online Demo
Alternatively:
// this searches forwards...
bool containZero(int randomArray[], int length)
{
if (length <= 0)
return false;
if (randomArray[0] == 0)
return true;
return containZero(randomArray+1, length-1);
}
Online Demo
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++.
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;
}
}
}
my knowledge is limited, writing in C++ for 2 months
In this function string code is recursively decrements chars until the base case "" is found. I want to prune some paths before the base case is found, and for some string code a path to the base case will not be found. For the prune I want to compare an attribute in the path with parameter int time. This searches a trie made of 'nodeT'
struct charT {
char letter;
nodeT *next;
};
struct nodeT {
bool isOperation;
bool isCode;
int time;
Vector<charT> alpha;
};
nodeT *root
usage:
string code = "12345";
int time = convertToEpoch(20120815); //my epoch function
containsCode(code, time)
bool containsCode(string code, int time)
{
if(root == NULL) return false;
else return containsCodeHelper(root, code, time);
}
bool containsCodeHelper(nodeT *w, string code, int time)
{
if(code == "") //base case: all char found
return w->isCode;
else {
if (w->isOperation && w->time != time) return false; //case 2: time check OK <- at a midpoint in the path
for(int i = 0; i < w->alpha.size(); i++) { //Loop through the leaf
if (w->alpha[i].letter == code[0]) //case 3: leaf exists
return containsCodeHelper(w->alpha[i].next, code.substr(1), time);
}
}
return false; //if no path
}
This function worked well before adding the time check prune, it now loops, returns false if outside time but then starts again with the candidate string code from char location 0.
Questions: 1) Is a nested return false kicking the recursion back to the next call for loop, 2) should the time prune be placed in the for loop with a logical return false or return 'path', 3) is this more fundamentally messed-up and I need to learn a C++ concept <- please explain if yes.
Also, the posted function is a simplified version of the actual function - there is a modifier to time and a 'step over' path that I left out. In past question I found that these 'addons' distract from the question.
after some reworking it now functions fine - possibly it always did; I changed to read attribute return w->isCode to return true, that seemed to be the biggest issue - I will debug the trie constructor and see if it is setting the attribute at the end of each path.
boolcontainsCodeHelper(nodeT *w, string code, int time)
{
if(code == "") //base case: all char found
return true;
else {
if ( w->isOperation && (!((w->begin-wag) <= time && time <= (w->end+wag) ) && time != 9999 ) )
return false; //case 2: time
else {
for(int i = 0; i < w->alpha.size(); i++) { //Loop through all of the children of the current node
if (w->alpha[i].letter == word[0])
return containsCodeHelper(w->alpha[i].next, word.substr(1), time, wag);
else if (word[0] == 'ΕΎ') //step over '0' all subnodes
if (containsCodeHelper(w->alpha[i].next, word.substr(1), time, wag))
return true;
}
}
}
return false; //if char is missing - meaning the exact code is not there - terminates garbage subnode paths
}
I don't see any difference between having return false; at the end and leaving it out. Also still confused as why the special case needs if( bool fn()) return true; rather than just return ( bool fn()); i found that solution through trial and error with help from another stack overflow thread