【问题标题】:How to capture a string into variable in a recursive function?如何将字符串捕获到递归函数中的变量中?
【发布时间】:2009-11-10 02:54:29
【问题描述】:

我试图打印几个向量成员的所有可能组合。为什么 下面的函数没有像我预期的那样返回字符串?

#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;

string EnumAll(const vector<vector<string> > &allVecs, size_t vecIndex, string
        strSoFar)
{
    string ResultString;
    if (vecIndex >= allVecs.size())
    {
        //cout << strSoFar << endl;
        ResultString = strSoFar;
        //return ResultString;
    }
    for (size_t i=0; i<allVecs[vecIndex].size(); i++) {
        strSoFar=EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
    }
    ResultString = strSoFar; // Updated but still doesn't return the string.
    return ResultString;  

}


int main  ( int arg_count, char *arg_vec[] ) {

    vector <string> Vec1;
          Vec1.push_back("T");
          Vec1.push_back("C");
          Vec1.push_back("A");

    vector <string> Vec2;
          Vec2.push_back("C");
          Vec2.push_back("G");
          Vec2.push_back("A");

    vector <string> Vec3;
          Vec3.push_back("C");
          Vec3.push_back("G");
          Vec3.push_back("T");


     vector <vector<string> > allVecs;

     allVecs.push_back(Vec1);
     allVecs.push_back(Vec2);
     allVecs.push_back(Vec3);




     string OutputString = EnumAll(allVecs,0,"");

     // print the string or process it with other function.
     cout << OutputString << endl;  // This prints nothing why?

     return 0;
}

预期的输出是:

TCC
TCG
TCT
TGC
TGG
TGT
TAC
TAG
TAT
CCC
CCG
CCT
CGC
CGG
CGT
CAC
CAG
CAT
ACC
ACG
ACT
AGC
AGG
AGT
AAC
AAG
AAT

【问题讨论】:

  • 你的代码输出到底是什么?
  • RNA 应该是 U,而不是 T。这看起来像 DNA。

标签: c++ string function recursion


【解决方案1】:

您递归调用 EnumAll,但忽略了它返回的字符串。您必须决定如何聚合这些字符串 - 或者您将如何处理它们。

【讨论】:

  • @JL:好的。我想我需要一个向量来聚合它们。但是我在哪里/如何做到这一点?
  • 嗯,EnumAll 是返回单个字符串还是字符串向量?如果是单个字符串,您将如何分隔各个项目?换行?如果它是一个向量,它可能会让生活更轻松——除非你必须知道如何将一个向量的字符串值(从 EnumAll 的递归调用返回)连接到本地返回值(另一个向量)的末尾。
【解决方案2】:

您的函数没有返回任何内容,因为您的最后一次调用没有返回任何内容,因为没有 return 和函数的结尾。

编辑: 您可以做的一件事是每次在return 之前将ResultString 插入到全局向量中。最后,您的所有结果都将在此向量中可用。

【讨论】:

  • @SH:感谢您的回复,但我已经添加了退货,但它仍然没有给出结果。 (见我的更新)。
  • 好吧,这又是一个问题,反正返回是空的,因为你没有初始化 ResultString
【解决方案3】:

这是另一种解决方案。这不希望您传递除初始向量之外的任何内容:

int resultSize( vector< vector<string> > vector ){
 int x=1;
 for( int i=0;i<vector.size(); i++ )
  x *= vector[i].size();
 return x;
}

vector<string> enumAll(const vector< vector<string> > allVecs )
{
 //__ASSERT( allVecs.size() > 0 );
 vector<string> result;
 if( allVecs.size() == 1 ){
  for( int i=0 ; i< allVecs[0].size(); i++){
   result.push_back( allVecs[0][i] );
  }
  return result;
 }
 for( int i=0; i<allVecs[0].size(); i++ ){
  for( int j=0; j<resultSize( vector< vector<string> >(allVecs.begin()+1, allVecs.end() ) ); j++){
   result.push_back( allVecs[0][i] + enumAll(vector< vector<string> >(allVecs.begin()+1, allVecs.end() ))[j] );//enumAll on each tempVector is called multiple times. Can be optimzed.
  }
 }
}

这种方法的优点: 就递归而言,这是非常可读的。它具有易于识别的递归基本步骤以及递归本身。它的工作原理如下:递归的每次迭代都从 n-1 个向量中枚举所有可能的字符串,而当前步骤只是枚举它们。

这种方法的缺点: 1. enumAll() 函数被多次调用返回相同的结果。 2. 堆栈使用量很大,因为这不是尾递归。

我们可以通过执行以下操作来修复 (1.),但除非我们消除尾递归,否则我们无法摆脱 (2.)。

vector<string> enumAll(const vector< vector<string> > allVecs )
{
 //__ASSERT( allVecs.size() > 0 );
 vector<string> result;
 if( allVecs.size() == 1 ){
  for( int i=0 ; i< allVecs[0].size(); i++){
   result.push_back( allVecs[0][i] );
  }
  return result;
 }
 const vector< vector<string> > tempVector(allVecs.begin()+1, allVecs.end() );
 vector<string> tempResult = enumAll( tempVector );// recurse
 int size = resultSize( tempVector );
 cout << size << " " << tempResult.size() << endl;
 for( int i=0; i<allVecs[0].size(); i++ ){
  for( int j=0; j<size; j++){
   result.push_back( allVecs[0][i] + tempResult[j] );
  }
 }
}

【讨论】:

    【解决方案4】:

    您的第二次返回也应该以某种方式累积 strSoFar。比如:

    for (size_t i=0; i<allVecs[vecIndex].size(); i++)
    {
        strSoFar = EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
    }
    ResultString = strSoFar;
    return ResultString;
    

    【讨论】:

    • @Kyle:我尝试了您的建议,但仍然无法打印。我在您的帖子中遗漏了什么吗?
    • @neversaint 好吧,我说了“类似”的话,不完全是。此外,您应该取消注释第一个 return 语句,或者将 ResultString 传递给递归函数,否则您编辑的代码将不会做任何事情。
    【解决方案5】:

    您提供的代码崩溃了。在以下行中,请注意您将超出 vecIndex 的限制。循环中没有检查它。此外,在上面的 if 条件下,您也不重置 vecIndex。所以你会遇到访问冲突。

    strSoFar = EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
    

    要修复它,要么在 if() 中保留 vecIndex,要么使用以下 for 语句:

    for (size_t i=0; i<allVecs[vecIndex].size() && vecIndex < allVecs.size(); i++){...}
    

    编辑:但是,这还没有给出正确的输出。

    【讨论】:

      【解决方案6】:

      您的函数确定了所有正确的组合,但由于您没有正确聚合它们而丢失了它们。

      我看到你问了同样的问题here。我假设您现在正在寻找一种将输出恢复到顶层的方法,以便您可以从那里处理它。

      然后问题归结为您如何汇总输出。您正在使用字符串,但正在寻找多行数据。这个有无限的答案..这里是一个使用矢量容器的答案。

      #include <iostream>
      #include <vector>
      #include <fstream>
      #include <sstream>
      using namespace std;
      
      void printAll(const vector<string> data);
      
      void EnumAll(const vector<vector<string> > &allVecs, size_t vecIndex, vector<string>&allStr, string strSoFar)
      {
          if (vecIndex >= allVecs.size())
          {
            allStr.push_back(strSoFar);
            return;
          }
          for (size_t i=0; i<allVecs[vecIndex].size(); i++)
            EnumAll(allVecs, vecIndex+1, allStr, strSoFar+allVecs[vecIndex][i]);
      }
      
      
      int main  ( int arg_count, char *arg_vec[] ) {
      
          vector <string> Vec1;
                Vec1.push_back("T");
                Vec1.push_back("C");
                Vec1.push_back("A");
      
          vector <string> Vec2;
                Vec2.push_back("C");
                Vec2.push_back("G");
                Vec2.push_back("A");
      
          vector <string> Vec3;
                Vec3.push_back("C");
                Vec3.push_back("G");
                Vec3.push_back("T");
      
      
           vector <vector<string> > allVecs;
      
           allVecs.push_back(Vec1);
           allVecs.push_back(Vec2);
           allVecs.push_back(Vec3);
      
      
      
           vector<string> allStr;
           EnumAll(allVecs,0,allStr,"");
      
           // print the string or process it with other function.
           printAll(allStr);
      
           return 0;
      }
      
      void printAll(const vector<string> data)
      {
        vector<string>::const_iterator c = data.begin();
        while(c!=data.end())
          {
            cout << *c << endl;
            ++c;
          }
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-09
        相关资源
        最近更新 更多