#c #vector #iterator
#c #вектор #итератор
Вопрос:
Здесь у меня проблема: я должен написать функцию, которая печатает элементы вектора рекурсивно, поэтому цикл не допускается.
Я пробовал этот код, но он вылетает во время выполнения:
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());
}
Если я запускаю программу, я получаю диалоговое окно утверждения!?
Ответ №1:
void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
ivec
Параметр передается по значению. Оба этих параметра передаются по значению. Передача по значению означает, что внутри функции это копии исходных параметров.
Ваш main()
вызывает эту рекурсивную функцию, передавая ей свой вектор и начальный итератор своего вектора. Однако, поскольку все параметры передаются по значению, каждая рекурсивная итерация функции сравнивает итератор с end()
совершенно другим вектором. Неопределенное поведение.
Вы, очевидно, забыли передать вектор по ссылке. Первым параметром to должно быть const std::vector<int> amp;ivec
.
Ответ №2:
При вызове print
вы передаете вектор по значению. Это означает, что каждый раз создается совершенно новый вектор, но итератор по-прежнему исходит из исходного вектора. Поскольку итератор исходит из другого вектора, тест it == ivec.end()
всегда завершается неудачей.
Мы можем исправить это, просто передав ivec
по ссылке const:
void print(const std::vector<int>amp; ivec, std::vector<int>::const_iterator it)
{
if (it == ivec.end())
return;
std::cout << *it << std::endl;
print(ivec, it);
}
И код работает отлично!
Комментарии:
1. Опередил меня на семь секунд.
Ответ №3:
Вы должны передавать вектор по ссылке, чтобы избежать множественных копий, таким образом, итератор гарантированно сравнивается с итераторами одного и того же вектора, но не с другими’:
void print(const std::vector<int>amp; 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:
Нет необходимости передавать два аргумента функции 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);
}
Ответ №5:
Если вам просто нужно распечатать вектор, я думаю, гораздо более элегантным решением было бы использовать итераторы.
#include <iostream>
#include <vector>
using namespace std;
void print_vector(vector<int>::iterator it, const vector<int>::iterator amp;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;
}
Похоже ли это на базуку для уничтожения комаров? Конечно, это так! Но это довольно безумно, да?!