Проверка границ итератора на превышение размера вектора

Мой вопрос отличается, потому что я не ищу range-3v решения. Кроме того, я специально спрашивал, как решить проблему со вторым циклом for. Я уже принял ответ ниже моего вопроса. Поскольку мне не нужен второй цикл for, они показали мне, как использовать один индекс, добавляя к нему 1 для нечетных итераций. Это решило мою проблему!


Я пишу функцию, которая будет принимать вектор, предполагая, что он имеет четную длину элементов; В моей функции я создаю два временных вектора из исходного вектора, где их элементами являются {0,2,4,6,...} и {1,3,5,7,...} соответственно. Затем я добавляю соответствующие индексированные элементы и сохраняю результаты в свой вектор результатов.

Вот моя функция:

void sumElementPairsFromVector(const std::vector<int>& values, std::vector<int>& result)
{
    using It = std::vector<int>::const_iterator;
    std::vector<int> temp1, temp2;

    // First lets divide the original vector into two temp vectors
    for (It it1 = values.cbegin(); it1 != values.cend(); it1 += 2)
        temp1.push_back(*it1);

    for (It it2 = values.cbegin() + 1; it2 != values.cend() ; it2 += 2)
        temp2.push_back(*it2);

    // Add each corresponding vector and store that into our results.
    for (std::size_t i = 0; i < values.size() / 2; i++)
        result[i] = temp1[i] + temp2[i];
}

Вот как я его использую:

int main() 
{         
    std::vector<int> values{ 1,2,3,4,5,6 };
    for (auto i : values)
        std::cout << i << " ";
    std::cout << '\n';

    std::vector<int> results;

    sumElementPairsFromVector(values, results);
    for (auto i : results)
        std::cout << i << " ";
    std::cout << '\n';

    return 0;
}

Ожидаемый результат должен быть:

1 2 3 4 5 6
3 7 11

Утверждение отладки не выполняется в этой строке кода из функции:

for (It it2 = values.cbegin() + 1; it2 != values.cend(); it2 += 2 )

Я знаю, что вызывает ошибку; на последней итерации после того, как он увеличивается на 2 и проверяет, проходит ли it2 != values.cend() конец вектора. Как это исправить?

Можно ли использовать Ranges v3? Код будет намного понятнее и менее подвержен ошибкам.

Igor R. 01.06.2019 16:54

@ИгорьР. Ну, я пытаюсь оставаться в рамках текущего стандарта банкомата. Как только я заставлю эту функцию работать правильно, я планирую превратить ее в шаблонную лямбда-функцию. я не использую буст; только стл. Я использую С++ 17 атм. нет доступа к c++20. Я также использую Visual Studio 2017 CE

Francis Cugler 01.06.2019 16:55

@ИгорьР. Что-то вроде дубликата, но мой вопрос конкретно о том, как исправить второй цикл for в моей функции.

Francis Cugler 01.06.2019 17:01

Этот вопрос также не имеет решения range-3v.

L. F. 02.06.2019 03:51

@ИгорьР. Хорошо, вы, кажется, правы, только один из ответов (непринятый использовал range-3v для своего ответа; и мне не особенно понравились полученные ответы. Однако мой вопрос все еще был специфичен для условий цикла for , Пользователь JeJo дал отличный ответ, на мой взгляд.

Francis Cugler 02.06.2019 08:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
307
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

I know what is causing the error; on the last iteration after it increments by 2 and goes to check if it2 != values.cend() it is going past the end of the vector. How do I fix this?

Вам не нужны два разных цикла для перебора вектора values.

std::vector<int> temp1, temp2;
temp1.reserve(values.size() / 2); // reserve the memory
temp2.reserve(values.size() / 2);

for (std::size_t index = 0; index < values.size(); ++index)
{
    if (index & 1) temp2.emplace_back(values[index]); // odd index
    else temp1.emplace_back(values[index]);           // even index
}

Во-вторых, results в то время не выделял никакой памяти.

result[i] = temp1[i] + temp2[i];

следовательно, за пределами неопределенного поведения. Вам следует

for (std::size_t i = 0; i < std::min(temp1.size(), temp2.size()); i++)
    result.emplace_back(temp1[i] + temp2[i]);

С другой стороны, если цель состоит в том, чтобы получить результирующий вектор из сумма последовательной пары элементов, temp1 и temp2 избыточны. result можно заполнить просто:

void sumElementPairsFromVector(const std::vector<int>& values, std::vector<int>& result)
{
    result.reserve(values.size() / 2);

    for (std::size_t index = 0; index < values.size() - 1; index += 2)
        result.emplace_back(values[index] + values[index+1]);
}

Я могу зарезервировать размер в main, прежде чем передать его функции; Не ошибка.

Francis Cugler 01.06.2019 17:03

Тебе нужно сделать больше, чем reserve, @Francis. На самом деле вам нужно создать элементы, прежде чем назначать их.

Lightness Races in Orbit 01.06.2019 17:07

Я пробовал это; но вывод не правильный. Я получаю 3 3 3 7 3 7 3 7 11 в качестве результата.

Francis Cugler 01.06.2019 17:07

Неважно, что это была моя ошибка, у меня был второй цикл for, работающий внутри первого. Я вытащил его из цикла for и теперь получаю правильные результаты.

Francis Cugler 01.06.2019 17:13

Поскольку вы не работаете с функциями шаблона, ваша функция просто использует вектор, итераторы, на мой взгляд, вам не нужны.

Вы могли бы просто иметь что-то вроде

...
for (int i = 0; i < values.size(); i += 2) {
    result.push_back(values[i] + values[i + 1]);
}
...

Хорошо, если вы уверены, что values.size() всегда четно. Если это не так, вы можете сделать что-то вроде

void sumElementPairsFromVector(const std::vector<int>& values, std::vector<int>& result)
{
    for (int i = 1; i < values.size(); i += 2) {
        result.push_back(values[i] + values[i - 1]);
    }
    if (values.size() % 2) {
        // whatever you want to do with the last element of an uneven vector
        result.push_back(values[values.size() - 1]);
    }
}

потому что, если вы не уверены, что размер значений всегда четный, первый метод попытается получить доступ к n-му элементу, где n больше, чем количество элементов, поэтому вы можете получить значение мусора.

Я заявил, предполагая, что векторы всегда имеют четную длину. Они не должны использоваться вне этого контекста. Я ценю обратную связь!

Francis Cugler 01.06.2019 19:13

Другие вопросы по теме