#c #for-loop #vector
#c #для цикла #вектор
Вопрос:
Я хочу пройти через заданный вектор целых чисел и найти целое число, значение следующего и предыдущего целых чисел которого равно 0.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> sample = { 0,3,0 };
for (int i : sample)
{
if (sample[i - 1] == sample[i 1] == 0)
{
cout << "hello";
}
}
}
Тем не менее, я продолжаю получать сообщение об ошибке «векторный индекс вне диапазона». Я думаю, это потому, что, когда i
равно 0, sample[-1]
не существует, то же самое с i = 2
.
Есть ли простое решение для этого?
Комментарии:
1. Вы имели в виду использовать цикл на основе индекса, например
for (size_t i = 1; i < sample.size() - 1; i)
?2. Вы неправильно понимаете диапазон
for
.i
является значениемsample
, а не индексом. То есть значенияi
будут0
,3
, и0
, соответственно, не0
,1
, и2
. Однако ваше подозрение, что попытка доступаsample[-1]
неверна, вполне обосновано, и когда вы переписываете код для использования индексов, вы должны позаботиться о том, чтобы избежать этого.3. Ваше объяснение неверно.
i
присваивается0
,3
,0
, а не0
,1
,2
, поэтому использование его в качестве индекса вsample[i]
не делает того, что вы думаете.4.
i
не является значением от 0 до size-1. Это не индекс.i
выполняется ли итерация текущего значения. Тогда значенияi
в этом случае будут0
3
0
равны . Кроме того, ваша логика ошибочна, поскольку она предполагает, что каждый элемент является предыдущим и последующим элементом. Если бы этоi
был индекс, вы бы проверяли индексы out of bounds, когдаi
это первый или последний индекс в векторе.5. Ранжированные циклы for, к сожалению, не позволяют вам использовать доступ к индексу элемента; Вы могли бы использовать итераторы, но не уверены, что вы уже узнали о них; в противном случае может работать «стандартный» цикл для цикла через индекс.
if (sample.size() > 2u) { for (auto p1 = sample.begin(), p2 = p1 2; p2 != sample.end(); p1, p2) { if (*p1 == 0 amp;amp; *p2 == 0) { std::cout << "hello"; } }}
Ответ №1:
Здесь вы сталкиваетесь с двумя проблемами.
Во-первых, используя обозначение цикла range-for, переменная i
соответствует значениям массива 0, 3 и 0. Не их индексы.
Вторая проблема заключается в том, что если вы выполняете итерацию от индекса 0 до конца, вы будете проверять индексы -1
и 3
, которые находятся за пределами вектора.
Вот код, который решает проблему двумя способами, первый использует индексы, а второй использует итераторы. Для второго вы эффективно обрабатываете p
как указатель на текущий элемент в списке. Я сделал список немного длиннее, чтобы привести больше примеров. Он выводит целые 2
числа и 5
окружен нулями.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> sample = { 0, 3, 6, 0, 2, 0, 5, 0 };
for(int i = 1; i < sample.size() - 1; i ){
if(sample[i-1] == 0 amp;amp; sample[i 1] == 0)
cout << "integer " << sample[i] << " surrounded by 0n";
}
for(std::vector<int>::iterator p = sample.begin() 1; p != sample.end() - 1; p ){
if(*(p-1) == 0 amp;amp; *(p 1) == 0)
cout << "integer " << *p << " surrounded by 0n";
}
}
Для второго примера std::vector<int>::iterator
часто заменяется на auto
более короткое.
Ответ №2:
Этот диапазон основан на цикле for
for (int i : sample)
{
if (sample[i - 1] == sample[i 1] == 0)
{
cout << "hello";
}
}
не имеет смысла, потому что в качестве индексов вектора используются значения вектора.
Цикл for, основанный на диапазоне, не подходит для такой задачи.
Вы можете использовать, например, стандартный алгоритм std::adjacent_find
.
Вот демонстрационная программа.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<int> v = { 0, 1, 0, 2, 0, 3, 0 };
auto condition = []( const auto amp;a, const auto amp;b )
{
return a != 0 amp;amp; b == 0;
};
if ( not v.empty() )
{
for ( auto current = std::next( std::begin( v ) ), last = std::end( v );
( current = std::adjacent_find( current, std::end( v ), condition ) ) != last;
std::advance( current, 2 ) )
{
if ( *std::prev( current ) == 0 )
{
std::cout << *prev( current ) << ", "
<< *current << ", "
<< *std::next( current ) << 'n';
}
}
}
return 0;
}
Вывод программы
0, 1, 0
0, 2, 0
0, 3, 0
Ответ №3:
В range-for
цикле i
устанавливается значение каждого элемента в массиве. Для него НЕ задан индекс каждого элемента, как вы предполагаете в настоящее время.
Вместо этого вам нужно использовать цикл на основе индексов:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> sample = ...;
if (sample.size() > 2)
{
for (size_t i = 1; i < sample.size()-1; i)
{
if (sample[i-1] == 0 amp;amp; sample[i 1] == 0)
{
cout << sample[i] << endl;
}
}
}
}
В противном случае вместо этого используйте цикл на основе итератора:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> sample = ...;
if (sample.size() > 2)
{
for (auto iter = sample.begin() 1; iter != sample.end()-1; iter)
{
if (*(iter-1) == 0 amp;amp; *(iter 1) == 0)
{
cout << *iter << endl;
}
}
}
}
Комментарии:
1.
if (sample.size() > 2)
в 1-м примере не требуется.2. @Eugene поскольку для корректной работы цикла требуется не менее 3 элементов, имеет смысл проверить это заранее. По крайней мере, код требует
if (sample.size() > 0)
илиif (!sample.empty())
для обеспечения тогоsample.size()-1
, чтобы это не переполнялось, иначе код будет иметь неопределенное поведение .