Борьба с итерацией по списку - PullRequest
0 голосов
/ 04 ноября 2019
...
// ConsoleApplication2.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>
#include <vector>
#include <list>



void squareVector(std::vector<int>&array1) 
{
    std::list<int> listint;
    for (int j = 0; j < array1.size();++j) 
    {
        listint.push_back(array1[j]);
    }
    std::list<int>::iterator it;
    it = listint.begin();
    int val;

    for (std::list<int>::iterator i = listint.begin(); i != listint.end(); ++i) 
    {
    val = *i * *i;
    listint.insert(it, val);
    ++it;
    }
    for (std::list<int>::iterator i = listint.begin(); i != listint.end(); ++i) 
    {
        std::cout << *i << ", ";    
    }
}

int main()
{
     std::vector<int>intlist ({ 1,3,2,5 });
    squareVector(intlist);
}

...

Моя цель состоит в том, чтобы взять числа 1,3,2 и 5, поместить их в список, а затем поставить квадрат в квадрат после каждого числа, после чего мне удалосьвозьмите их в квадрате и поместите в список, но по какой-то причине туда возвращайтесь. то есть результат должен быть 1,1,3,9,2,4,5,25, но я получаю 1,1,9,3,4,2,25,5.

Я попытался добавить еще один инкремент к итератору, но во время выполнения выдает ошибку «невозможно инкрементировать итератор конечного списка».

Редактировать, спасибо всем за ваши комментарии, очень признателен, очевидно, мне еще многое предстоит узнать.

Ответы [ 5 ]

0 голосов
/ 04 ноября 2019

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

Я бы порекомендовал простой подход:

for (int j = 0; j < array1.size(); ++j)
{
    listint.push_back(array1[j]);
    listint.push_back(array1[j] * array1[j]);
}
0 голосов
/ 04 ноября 2019

Вместо того, чтобы использовать отдельный итератор и увеличивать его отдельно, вы можете использовать i внутри цикла.

for (std::list<int>::iterator i = listint.begin(); i != listint.end(); ++i) 
{
    val = *i * *i;
    i=listint.insert(std::next(i), val); // i points to the inserted element

}

std::next возвращает итератор элемента-преемника. i необходимо обновить после вставки, чтобы он не стал недействительным.

0 голосов
/ 04 ноября 2019

просто используйте вектор / список std :: pair для хранения результатов. pair.first содержит ваше базовое значение, pair.second результат. Поэтому вам не нужно изменять количество элементов во время итерации.

0 голосов
/ 04 ноября 2019

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

Вставить функцию вставки перед заданной позицией. Например, если вы зададите 4-ую позицию, она будет вставлена ​​перед 4-й позицией.

Прочитайте этот фрагмент из ссылки cpp
1. pos - итератор, перед которым будет вставлен контент. pos может быть итератором end ().

Поэтому, когда вы выполняете, вы вставляете до того, как указатель указывает на позицию вашего итератора. Таким образом, 1,3,2,5 становится 1², 1,3², 3,2², 2,5², 5 (до 1, затем до 3 и т. Д.)

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

void squareVector(std::vector<int>&array1)
{
    std::list<int> listint;
    for (int j = 0; j < array1.size();++j)
    {
        listint.push_back(array1[j]);
    }
    std::list<int>::iterator it;
    it = listint.begin();
    int val;

    for(auto &i : listint) // declare i as reference not as plain i.
        i = i*i;
    for (std::list<int>::iterator i = listint.begin(); i != listint.end(); ++i)
    {
        std::cout << *i << ", ";
    }
}
0 голосов
/ 04 ноября 2019

Из cpp справочной документации, функция вставки

вставляет значение перед pos

Так что, когда вы делаете это listint.insert(it, val);, вы вставляете val перед позицией вашего итератора it. Таким образом, 1,3,2,5 становится 1², 1,3², 3,2², 2,5², 5 = 1,1,9,3,4,2,25,5.

Если вы увеличиваете оператор, вам нужно убедиться, что вы не пытаетесь получить доступ к listint.end(), поскольку, согласно документации ,

std ::list :: end

Возвращает итератор для элемента, следующего за последним элементом контейнера.

Этот элемент действует как заполнитель; попытка получить к нему доступ приводит к неопределенному поведению.

Как уже отмечали другие, если вы хотите просто получить квадрат исходных чисел, вам не нужно вставлять новыезначения, вы можете просто изменить значение в вашем итераторе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...