简体   繁体   中英

Learning recursion: How can I locate a substring index within a string without using find?

I have a recursive function to find the starting index of a substring within a string. I am learning to use recursion, so the find function is not allowed. I believe I have met most of the conditions. This function is supposed to find the correct index in the string. If it is blank it returns -1.

Here is the real problem. If I enter a string "nothing" and search for "jax" it doesn't return -1. I don't understand why. Any help please? Here is the code:

The user would enter string s and t passed into below:

int index_of(string s, string t)
{
    int start = 0;
    int len2 = t.length();
    int index = 0;

    if (s == "")
    {
        return -1;
    }
    else if (s.substr(1).length() <= t.length())
    {
        return -1;
    }
    else if ( s.substr(start, len2) == t)
    {
        return index;
    }
    else
    {
        index ++;
        return index + index_of(s.substr(1), t);
    }
    return -1;
}

There are several problems -- some minor ones, and some quite important ones.

  1. You have two variables, start and index , to indicate "the current position", but one would be enough.

  2. index can only be 0 or 1. Therefore, the way it is currently written, you could easily get rid of index and start altogether.

  3. Important: When, during the final recursion, the end of the string is reached, you return -1 to the previous recursive call. Then, because of the way the recursive calls are done, you add 1 and return that to the previous call, and so forth. The value finally returned is the -1 plus the length of the string. That is why you get strange results.

  4. This comparison

     if (s.substr(1).length() <= t.length()) 

    does not make much sense.

Taking all of this into account, here is an improved version:

#include <iostream>
#include <string>

int index_of(
  const std::string &s,
  const std::string &t,
  const size_t index)
{
  int len2  = t.length();

  if ((s.length() - index) < t.length())
    return -1;
  else if (s.substr(index,len2) == t)
    return index;
  else
    return index_of(s,t,index + 1);
  return -1;
}

/** Overloading, so you can call index_of with just
    two arguments */
int index_of(const std::string &s, const std::string &t)
{
  return index_of(s,t,0);
}

/** Some test cases. */
int main()
{
  std::cout << index_of("hello","ello") << std::endl;
  std::cout << index_of("nothing","jax") << std::endl;
  std::cout << index_of("hello","llo") << std::endl;
  std::cout << index_of("hello","lo") << std::endl;
  std::cout << index_of("hello","o") << std::endl;
  std::cout << index_of("hello","hel") << std::endl;
}

The best way to learn how to debug problems like this is to work them out on paper. Your example is small enough that it shouldn't take too long. It's pretty clear that you're going to fall into your else case in the first few steps because the strings don't match. So we have:

index_of("nothing", "jax"):
    index++;  // index is now 1
    return 1 + index_of("othing", "jax");
index_of("othing", "jax"):
    index++;  // index is now 1
    return 1 + index_of("thing", "jax");
etc.

Does that help?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM