Циклический сдвиг массива влево с помощью указателей

Интересной и полезной может быть задача на арифметику указателей: циклический сдвиг одномерного массива влево.
Показываемое решение взято из алгоритма стандартной библиотеки. Ради любителей самостоятельно пытать свои умы, это решение спрятано вовнутрь спойлера. Немного модифицировано, но суть — что используется алгоритм, применяемый в std::rotate.

Наиболее простой алгоритм сдвига — это использование функции копирования блоков памяти. Этот способ можно не считать за решение поставленной задачи по сдвигу, потому что прямой работы программиста с указателями нет и весь кайф от задачи с таким решением не поймаешь. Но поскольку имя массива С++ умеет приводить к указателю на свой первый элемент, а функция, копирующая блоки памяти, работает с указательной переменной, то можно с натяжкой считать, что то, что будет показано ниже, всё-таки тоже решение.

Конечно чисто на указателях, как показано в первом листинге, выполнять круче и правильнее с точки зрения поставленной задачи. Но и с копированием областей памяти кому-то может быть окажется пример полезным. При копировании областей память вовнутрь круглых скобок по очереди отдавались: массив, в который копируем, массив, из которого копируем, и количество копируемых байт.
Чтобы копировались все значения ячеек массива, нужно домножить количество ячеек на размер типа массива. Т. е. если у массива был бы тип double и он состоял из N ячеек, то нужно бы было в количестве байтов использовать умножение: N*sizeof(double).

11 комментариев на «“Циклический сдвиг массива влево с помощью указателей”»

  1. Gen:

    В CODE::BLOCK для работы функции memcpy необходимо подключить

    и соответственно using namespace std; и главная функция int main().и все работает на ура.Спасибо. 😛

  2. В CodeBlock

  3. Gen:

    Эти коды идентичны? И как лучше писать с прототипами или как у вас?

    • Да, идентичны. В маленьких программах Принципиальной разницы нет, но в больших проектах использование прототипов может сильно улучшить читаемость кода и ускорить компиляцию проекта.
      Я такие вещи не описывал, но это можно найти в любом популярном поисковике, задав вопрос: «Зачем нужны прототипы». Многие авторы книг используют прототипы, при этом не особо углубляясь в механизм их работы. Так, например, в одном из изданий Дейтелов есть интересная ошибка, связанная с прототипами (интересна с той точки зрения, что новичкам её очень сложно исправить). Там описывается пример моделирования колоды карт и этот пример описан на сайте.
      Я это к тому, что всё от ситуации зависит. Если что-то есть в языке, то не обязательно это это что-то использовать везде и повсюду, лучше это что-то уметь применять и применять только тогда когда это действительно нужно.
      Вот как-то так, наверное.

      • Пример описан не в виде ошибки и ее исправления, а просто в виде правильного примера. Издание я не помню.

  4. Gen:

    Угловые скобки не принимает ни при каком раскладе.инклуды iostream,mem.h,stdlib.h

  5. Gen:

    Спасибо!Растолковали стало понятнее.Речь об ошибках не идет, ошибок нет оба кода работают одинаково верно.

  6. Максим:

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

    грубейшие ошибки в 28 строке
    1- это использование мемкопи для пересекающихся областей памяти, если области накладываются то нужно использовать memmove
    2- вы выходите за границу массива, копировать нужно только N-step элементов.

    «В коде видно, что в функции сдвига сначала идет смещение указателя на несколько позиций, потом идет возвращение его на исходную. Делается это для корректного удаления выделенной беглецу памяти, так как уже было описано, память за массивом не бегает.»

    тут дело не только в «утечке памяти» вы поломали внешнюю переменную, указывавшую на начало массива, и вам необходимо её починить, это одна из причин почему передавать данные по ссылке без острой на то необходимости считается плохим тоном..

    • Я достаточно часто передавал данные по ссылке, хотя иногда зазря. Не могу этого отрицать.
      Вы скорее всего тут не совсем точно выразились. Может и дурной тон с ссылками, но большинство компиляторов умеют игнорировать передачу по ссылке в тех случаях когда передача по ссылке не имеет смысла.
      То, что я говорю: «Неточно выразились» — просто выражение: «острая на то необходимость» достаточно расплывчато. А может в меня стрельнули бы и убили, если бы я не передавал данные по ссылке. Или может обещали заплатить миллион, если я передам по ссылке. А это всё — острая необходимость.
      =================
      И я с вами кое в чем не согласен.
      Здесь дурной тон не передача по ссылке, а то, что я ломаю внешнюю переменную, которую ломать не должен.
      ==================
      я это достаточно давно писал и честно говоря не врубаюсь пока, как выхожу за границу массива, пока не врублюсь, исправлять этот момент не стану.
      ==================
      по поводу того, что можно убрать 30 строчку. Эта строчка важна с той точки зрения, что должна показывать, что то, что мы вытворяем, иногда нужно откатывать. Здесь это маловажно, но зато актуально становится при работе с памятью. И вы должны хорошо понимать к чему я клоню.

      • По поводу выходов за границы. Посмотрел, подумал, но так и не увидел в чем проблема.
        В 28 строке я копирую step элементов. Просто применяю арифметику указателей, чтобы копировать не с первого элемента по индексу, а начиная с элемента по индексу (N-step). Т.е. последние step элементов.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/denis-kolisnichenko/programmirovanie-dlya-android-samouchitel/?lfrom=15589587
Яндекс.Метрика