Как я могу напечатать вектор в рекурсивной функции? - PullRequest
1 голос
/ 31 марта 2019

У меня проблема здесь: я должен написать функцию, которая печатает элементы вектора рекурсивно, поэтому цикл не допускается.

Я попробовал этот код, но он вылетает во время выполнения:

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

Если я запускаю программу, я получаю диалоговое окно подтверждения!?

Ответы [ 4 ]

2 голосов
/ 31 марта 2019
void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {

Параметр ivec передается по значению. Оба эти параметра передаются по значению. Передача по значению означает, что внутри функции это копии исходных параметров.

Ваш main() вызывает эту рекурсивную функцию, передавая ей свой вектор и начальный итератор своего вектора. Однако, поскольку все параметры передаются по значению, каждая рекурсивная итерация функции сравнивает итератор с end() совершенно другого вектора. Неопределенное поведение.

Вы, очевидно, забыли передать вектор по ссылке. Первый параметр должен быть const std::vector<int> &ivec.

1 голос
/ 31 марта 2019

Вы должны передать вектор по ссылке, чтобы избежать нескольких копий, поэтому итератор гарантированно будет сравниваться с итераторами одного и того же вектора, а не с другими:

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;
}
1 голос
/ 31 марта 2019

Когда вы звоните print, вы передаете вектор по значению.Это означает, что он каждый раз создает совершенно новый вектор, но итератор все еще исходит из исходного вектора.Поскольку итератор происходит из другого вектора, тест it == ivec.end() всегда будет неудачным.

Мы можем это исправить, просто передав 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);
}

И код работает отлично!

0 голосов
/ 31 марта 2019

Нет необходимости передавать два аргумента функции печати. Если вектор нулевой длины, ничего не печатать.

если вектор имеет длину 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...