如何在递归函数中打印矢量?

时间:2019-03-30 23:12:10

标签: c++ vector iterator

我在这里有一个问题:我要编写一个函数,该函数以递归方式打印矢量的元素,因此不允许循环。

我尝试了这段代码,但在运行时崩溃:

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());
}

如果我运行该程序,则会显示断言对话框!?

5 个答案:

答案 0 :(得分:2)

void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {

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

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

您显然忘记了通过参考传递矢量。的第一个参数应为const std::vector<int> &ivec

答案 1 :(得分:1)

调用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);
}

代码正常工作!

答案 2 :(得分:1)

您必须通过引用传递向量,以便避免重复,从而保证将迭代器与同一向量的迭代器进行比较,而不能与其他向量进行比较:

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;
}

答案 3 :(得分:0)

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

如果向量的长度为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);
}

答案 4 :(得分:0)

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

#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;
}

杀死蚊子看起来像火箭筒吗?就是这样!但这是非常疯狂的吗?!