C vector сумма элементов

Обновлено: 02.07.2024

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

Решение

когда вы останавливаетесь на data.size() -1 вы возвращаете 0 для vectorSum(data, data.size()-1) без подсчета значения последней записи

Решение

(Использование вашего стиля для функции, а не современного C ++.)

Другие решения

Ты можешь использовать std::accumulate() ,

accumulate() функция действительно просто левый сгиб , и по умолчанию он использует + функция для объединения элементов.

Другие решения

Когда вы смотрите на последний элемент, у вас есть это условие:

С этой точки зрения, position является 4 , а также data.size() является 5 , Таким образом, условие соответствует и рекурсия заканчивается.

Вам нужно изменить == в > или бросьте -1

В рекурсивной функции всегда есть две части: условие остановки и рекурсия. Простое условие остановки здесь: когда в векторе нет элементов, сумма равна 0. Рекурсия: сумма элементов непустого вектора равна значению его первого элемента плюс сумма оставшихся элементов. , В коде условие остановки выглядит так:

В коде рекурсия выглядит так:

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

По сравнению с первым этот уровень рекурсии меньше. Но это не работает для пустых векторов. Так что выбирай свой яд.

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

Я новичок в языке C++. Я начал использовать векторы и заметил, что во всем коде я вижу итерацию, хотя вектор через индексы, первый параметр for цикл всегда основан на векторе. В Java я мог бы сделать что-то подобное с ArrayList:

почему я не вижу этого в C++? Это плохая практика?

есть ли причина, по которой я не вижу этого в C++? Это плохая практика?

нет. Это не плохая практика, но она делает ваш код определенным гибкость.

обычно, pre-c++11 код для итерации по элементам контейнера использует итераторы, что-то вроде:

Это потому что это делает код более гибким.

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

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

iterator код стиля.

следующие могут быть причинами людей, не рассматривающих vector.size() способ зацикливания:

  1. быть параноиком о вызове size() каждый раз в цикле состояние. Однако либо это не проблема, либо это может быть тривиально исправлено
  2. предпочитая std::for_each() на for цикл
  3. позже изменение контейнера из std::vector к другому (например map , list ) также потребует изменения механизма зацикливания, потому что не каждый контейнер поддерживает size() стиль перекручивание

C++11 обеспечивает хорошее средство для перемещения через контейнеры. Это называется "range based for loop" (или "enhanced for loop" в Java).

С небольшим кодом вы можете пройти через полный (в обязательном порядке!) std::vector :

или (эквивалент выше)

до C++0x вы должны заменить auto типом итератора и использовать функции-члены вместо глобальных функций begin и end.

это, вероятно, то, что вы видели. По сравнению с подходом, который вы упомянули, преимущество заключается в том, что вы не сильно зависите от типа vector . Если вы измените vector в другой класс "collection-type", ваш код, вероятно, все еще будет работать. Однако вы можете сделать что-то подобное и на Java. Концептуально разница невелика; C++, однако, использует шаблоны для реализации этого (по сравнению с дженериками в Java); следовательно, подход будет работать для всех типов, для которых begin и end функции определены, даже для неклассовых типов, таких как статические массивы. Смотрите здесь: как работает диапазон для простых массивов?

правильный способ сделать это:

где T-тип класса внутри вектора. Например, если класс был CActivity, просто напишите CActivity вместо T.

этот тип метода будет работать на каждом STL (а не только векторах, что немного лучше).

Если вы все еще хотите использовать указатели, как это:

есть несколько веских причин использовать итераторы, некоторые из которых упоминаются здесь:

т. е., если вы переходите от std:: vector к std::list или std:: set, вы не можете использовать числовые индексы, чтобы получить содержащееся значение. Использование итератора по-прежнему допустимо.

Если вы измените свой контейнер в середине цикла, в следующий раз вы используйте свой итератор, он выдаст недопустимое исключение итератора.

С STL программисты используют iterators для обхода контейнеров, так как итератор является абстрактной концепцией, реализованной во всех стандартных контейнерах. Например, std::list нет operator [] на всех.

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

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

пробовал l.assign(4, -1); Это не так, как ожидалось. Ни один из других векторных методов не подходит.

я использовал вектор, поскольку мне нужна функциональность произвольного доступа в моем коде (используя l.at(i) ).

at и operator[] оба возвращают ссылку на индексированный элемент, поэтому вы можете просто использовать:

хотя ответ @JamesMcNellis является действительным, я хотел бы объяснить что-то об обработке ошибок, а также тот факт, что есть другой способ сделать то, что вы хотите.

у вас есть четыре способа доступа к определенному элементу в векторе:

  • С помощью [] оператор
  • использование функции-члена at(. )
  • использование итератора в сочетании с заданным смещением
  • используя std::for_each С algorithm заголовок стандартной библиотеки C++. Это еще один способ, который я могу рекомендовать (он использует внутри итератора). Вы можете прочитать больше об этом, например здесь.

в следующих примерах я буду использовать следующий вектор в качестве лабораторной крысы и объяснять первые три метода:

это создает вектор, как показано ниже:

сначала давайте посмотрим на [] способ делать вещи. Он работает в довольно много так же, как и при работе с обычным массивом. Вы даете индекс и возможно вы получаете доступ к элементу, который вы хотите. Я говорю возможно потому что [] оператор не проверяет, действительно ли вектор имеет столько элементов. Это приводит к молчаливому недопустимому доступу к памяти. Пример:

это может привести или не привести к мгновенному сбою. В худшем случае, конечно, если это не так, и вы действительно получаете то, что кажется действительным значением. Подобный массивы это может привести к потере времени, пытаясь найти причину, почему например 1000 строк кода Вы получите значение 100 вместо 234 , который несколько связан с тем самым местом, где вы получаете элемент от вас вектора.

гораздо лучший способ-использовать at(. ) . Это автоматически проверит для out of bounds поведение и перерыв бросив std::out_of_range . Так и в том случае, когда у нас

terminate вызывается после вызова экземпляра 'std:: out_of_range'
что (): вектор:: _M_range_check: _ _ n (что равно 10) >= this - > size() (который 4)

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

как вы можете видеть, мы также можем сделать

который снова является недопустимым доступом к памяти. Это в основном то же самое, что и использование at(0 + offset) но без проверки ошибок за пределами границ.

я бы посоветовал использовать at(. ) когда это возможно не только потому, что он более читаемый по сравнению с доступом к итератору, но и из-за проверки ошибок недопустимый индекс, который я упомянул выше для итератора с комбинацией смещения и [] оператора.

Как бы найти сумму элементов в векторе, который был введен пользователем? Я пытался найти способ сделать это везде в Интернете, но не смог найти такого онлайн, который бы объяснил это очень хорошо, и, к сожалению, он не был слишком объяснен в классе.

Таким образом, я в основном имею векторы, введенные пользователем здесь, но я понятия не имею, как использовать его, чтобы взять его сумму? (printvector присутствует только там, потому что я должен представить то, что пользователь положил пользователю, прежде чем сообщать пользователю сумму)

Читайте также: