【问题标题】:How can I print a vector in a recursive function?如何在递归函数中打印向量?
【发布时间】:2019-03-30 23:12:10
【问题描述】:

我有一个问题:我要编写一个函数,递归地打印向量的元素,因此不允许循环。

我试过这段代码,但它在运行时崩溃:

void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
    if (it == ivec.end())
        return;
    std::cout << *it++ << std::endl;
    print(ivec, it);
}

int main(){

    vector<int> v{
        5, 7, 77, 23, 10, 81
    };

    print(v, v.begin());
}

如果我运行程序,我会看到断言对话框!?

【问题讨论】:

    标签: c++ vector iterator


    【解决方案1】:
    void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
    

    ivec 参数是按值传递的。这两个参数都是按值传递的。通过值传递意味着在函数内部这些是原始参数的副本

    您的main() 调用此递归函数,将其向量及其向量的开始迭代器传递给它。但是,由于所有参数都是按值传递的,因此函数的每次递归迭代都会将迭代器与完全不同的向量的end() 进行比较。未定义的行为。

    您显然忘记通过引用传递向量。第一个参数应该是const std::vector&lt;int&gt; &amp;ivec

    【讨论】:

      【解决方案2】:

      当您调用print 时,您按值传递向量。这意味着它每次都会创建一个全新的向量,但迭代器仍然来自原始向量。因为迭代器来自不同的向量,所以测试it == ivec.end() 总是会失败。

      我们可以通过 const 引用传递 ivec 来解决这个问题:

      void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it) 
      {
          if (it == ivec.end())
              return;
          std::cout << *it++ << std::endl;
          print(ivec, it);
      }
      

      而且代码运行良好!

      【讨论】:

      • 领先我七秒。
      【解决方案3】:

      您必须通过引用传递向量以避免多个副本,因此保证迭代器仅与同一向量的迭代器进行比较,而不与其他迭代器进行比较:

      void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it) {
          if (it == ivec.end())
              return;
          std::cout << *it++ << std::endl;
          print(ivec, it);
      }
      
      int main(){
          vector<int> v{
              5, 7, 77, 23, 10, 81
          };
      
          print(v, v.begin()); // ok
      
          vector<int>::iterator it = v.begin();
          auto v2{ v };
      
          if (it == v.begin())
              cout << "it = v.begin()" << endl;
          if (it == v2.begin()) // causes crash
              cout << "it =v2.begin()" << endl;
      }
      

      【讨论】:

        【解决方案4】:

        无需将两个参数传递给打印函数。如果向量长度为​​零,则不打印任何内容。

        如果向量的长度为 1,则打印该元素。

        如果向量的长度大于 1,则打印一个不包括最后一个字符的较小向量(递归),然后打印最后一个字符。

        是的,这将为每个递归创建一个向量的副本,但我想这对我来说更像是递归。在每个循环上增加一个指针并不像递归。

        #include <iostream>
        #include <vector>
        
        void print(const std::vector<int> vec) {
            if (!vec.size())
                return; 
            else {
                print(std::vector<int>(vec.begin(), vec.end() - 1));
                std::cout << " " << *(vec.end() - 1);
            }
        }
        
        int main(){
        
            std::vector<int> v{
                    5, 7, 77, 23, 10, 81
            };
        
            print(v);
        }
        

        【讨论】:

          【解决方案5】:

          如果您只需要打印向量,我认为更优雅的解决方案是使用迭代器。

          #include <iostream>
          #include <vector>
          
          using namespace std;
          
          void print_vector(vector<int>::iterator it, const vector<int>::iterator &end)
          {
              if(it == end) {
                  cout << '\n';
                  return;
              }
          
              cout << *it << " ";
              print_vector(++it, end);
          }
          
          int main() {
          
              vector<int> v = {1,2,3,4,5,6,7,8,9};
              print_vector(v.begin(), v.end());
          
              return 0;
          }
          

          如果您想将该功能与其他结构重用(可能是为了给朋友或老师留下深刻印象),您可以使用模板。

          #include <iostream>
          #include <set>
          #include <vector>
          
          using namespace std;
          
          template<class TContainer>
          void print_structure(typename TContainer::iterator it, const typename TContainer::iterator end)
          {
              if(it == end) {
                  cout << '\n';
                  return;
              }
          
              cout << *it << " ";
              print_structure<TContainer>(++it, end);
          }
          
          int main() {
          
              vector<int> vi = {1,2,3,4,5,6,7,8,9};
              print_structure<vector<int>>(vi.begin(), vi.end());
          
          
              vector<double> vd = {1.2, 3.4, 5.6, 7.8, 9.0};
              print_structure<vector<double>>(vd.begin(), vd.end());
          
              set<int> si = {10, 10, 10, 10, 20, 20, 20, 20, 30, 30, 30};
              print_structure<set<int>>(si.begin(), si.end());
          
              set<double> sd = {10.10, 10.10, 20.20, 20.20, 30.30, 3.0};
              print_structure<set<double>>(sd.begin(), sd.end());
          
              return 0;
          }
          

          它看起来像火箭筒杀死蚊子吗?是的!但这很疯狂是吗?!

          【讨论】:

            猜你喜欢
            • 2021-05-12
            • 2013-06-02
            • 2023-03-28
            • 1970-01-01
            • 1970-01-01
            • 2020-10-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多