【问题标题】:How to find string position within another string in C recursively?如何递归地在C中的另一个字符串中查找字符串位置?
【发布时间】:2014-03-23 17:46:15
【问题描述】:

我们有一个任务来创建带有两个字符串参数的递归函数,原型应该是这样的

int instring(char* word, char* sentence);

如果我们调用函数

instring("Word", "Another Word"); 

它应该有以下返回值:

  • 如果找到该单词,它将返回在以下位置找到该单词的位置
  • 如果找不到该单词,它将返回 -1

我可以使用保存位置的第三个参数来做到这一点,但不幸的是,我们不允许使用超过 2 个参数。

所以问题是如何让它发挥作用? 到目前为止,这是我想出的:

int instring(char* word, char* sentence) {
    if (*word == '\0') {
        return 0;
    } else if (*word != '\0' && *sentence == '\0') {
        return -1;
    } else {
        if (*word == *sentence) {
            instring(word+1, sentence+1);
        } else {
            instring(word, sentence+1);
        }
    }
}

如果可以找到“单词”,我得到 0,否则我得到 -1。由于我无法跨函数调用存储任何值,因此我无法获得“单词”字符串的开始位置。 除了外部变量并且只有两个输入字符串之外,还有其他方法可以获取位置吗?

【问题讨论】:

  • 当您递归调用instring() 时,您应该return 其结果(将值“传递”回顶部)。
  • @Cornstalks 我做了这样的事情:return 1+instring(word, *(sentence)); 但在有字符串的情况下,我只是得到全长。你是这个意思吗?我无法理解它......
  • @Kevin 好的,很有趣。我曾用“strlen”尝试过,但没有像我预期的那样工作。我的函数不会在每次执行时都调用“strlen”吗?
  • 你能在函数体内使用循环吗?我可以想到一种简单的方法,它使用循环和递归调用......
  • 我认为您必须担心您的递归方案在"Wrong parts of the data" 中找到"Word";当方案找到W时,会在"rong parts of the data"中递归查找"ord",跳过r后会找到o,然后在parts中找到r,然后@ 987654336@data。因此,您必须在返回成功之前检查递归调用的返回值是否为 0。您在将比赛的正确位置传递回调用函数时也存在问题。

标签: c string recursion


【解决方案1】:

我不认为这些是特别优雅的解决方案,但是问题也不是很优雅(标准解决方案是迭代的,递归不是最优的)。这是一个效率相当低的纯递归解决方案(无迭代):

#include <stdio.h>

static int const debug = 0;

static int instring(char const *word, char const *sentence)
{
  int rc;
  if (debug)
    printf("-->> [%s] in [%s]\n", word, sentence);
  if (*word == '\0')
    rc = 0;
  else if (*sentence == '\0')
    rc = -1;
  else if (*word != *sentence || (rc = instring(word+1, sentence+1)) != 0)
  {
    if ((rc = instring(word, sentence+1)) >= 0)
      rc++;
  }
  if (debug)
    printf("<<-- [%s] in [%s] = %d\n", word, sentence, rc);
  return rc;
}

int main(void)
{
  char word[] = "Word";
  char str1[] = "Another Word";
  char str2[] = "Wrong parts of the data";
  char str3[] = "A Word Or Two";

  printf("Search for [%s] in [%s] at offset %d\n",
         word, str1, instring(word, str1));
  printf("Search for [%s] in [%s] at offset %d\n",
         word, str2, instring(word, str2));
  printf("Search for [%s] in [%s] at offset %d\n",
         word, str3, instring(word, str3));
  return 0;
}

如果您设置debug = 1;,您就会明白为什么它效率低下。它使用变量rc 来简化调试跟踪。

这是一种更有效的替代方法,因为它使用迭代来限制第一个字符匹配时的搜索。不难看出如何去除剩余的递归(它是简单的尾递归)留下一个完全迭代的解决方案,这是解决这个问题的正常方法。

#include <stdio.h>

static int instring(char const *word, char const *sentence)
{
  int rc;
  if (*word == '\0')
    return 0;
  if (*sentence == '\0')
    return -1;
  if (*word == *sentence)
  {
    int i;
    for (i = 1; word[i] != '\0' && word[i] == sentence[i]; i++)
      ;
    if (word[i] == '\0')
      return 0;
  }
  if ((rc = instring(word, sentence+1)) >= 0)
    rc++;
  return rc;
}

int main(void)
{
  char word[] = "Word";
  char str1[] = "Another Word";
  char str2[] = "Wrong parts of the data";
  char str3[] = "A Word Or Two";

  printf("Search for [%s] in [%s] at offset %d\n",
         word, str1, instring(word, str1));
  printf("Search for [%s] in [%s] at offset %d\n",
         word, str2, instring(word, str2));
  printf("Search for [%s] in [%s] at offset %d\n",
         word, str3, instring(word, str3));
  return 0;
}

样本输出:

Search for [Word] in [Another Word] at offset 8
Search for [Word] in [Wrong parts of the data] at offset -1
Search for [Word] in [A Word Or Two] at offset 2

两个版本的测试代码都可以改进(通过检查结果是否符合预期,使用测试函数而不是写出这么多代码三次,也许使用循环扫描测试数据。

【讨论】:

    【解决方案2】:
    int instring( char* word, char* sentence ){
        int lenw = strlen(word);
        int lens = strlen(sentence);
        if(lenw > lens) return -1;
    
        if(strncmp(sentence, word, lenw)==0)
            return 0;
        else {
            int ret = instring(word, sentence + 1);
            if(ret < 0)
                return ret;
            return 1 + ret;
        }
    }
    

    【讨论】:

      【解决方案3】:
      int len1 = strlen(word);
      int len2 = strlen(sentence);
      int n,k=0;
      
      for(int i =0;i<len2;i++){
      n =i;
        while(sentence[n] == word[k] && n<len2){
            if(k==len1 && ( n==len2 || sentence[n+1] ==' ')
              return i;//if word found return the position in the original string//
              n++;
              k++;
       }
      k =0;
      while(sentence[i] != ' ' && i<len2) //go to next word//
      i++;
      }
      return -1;
      

      【讨论】:

      • 谢谢你的回答,但不幸的是我不得不使用递归函数。
      猜你喜欢
      • 2015-05-13
      • 1970-01-01
      • 2019-09-22
      • 2014-05-06
      • 2016-01-27
      • 2016-10-02
      • 1970-01-01
      • 2011-05-30
      • 2012-08-03
      相关资源
      最近更新 更多