Опубликован: 02.02.2011 | Уровень: для всех | Доступ: свободно
Лекция 26:

Одномерные динамические массивы

< Лекция 25 || Лекция 26: 123 || Лекция 27 >

Обращение к элементам одномерного динамического массива

Адресация элементов динамического массива осуществляется аналогично адресации элементов статического массива, то есть с помощью индексированного имени.

Синтаксис:

ИмяМассива[ВыражениеТипаКонстанты];

или

ИмяМассива[ЗначениеИндекса];

Например:

mas[5]индекс задается как константа,

sl[i]индекс задается как переменная,

array[4*p]индекс задается как выражение.

Пример 1. Сформировать динамический одномерный массив, заполнить его случайными числами. Преобразовать массив таким образом, чтобы в первой его половине располагались элементы, стоявшие в чётных позициях, а во второй половине – элементы, стоявшие в нечётных позициях.

#include "stdafx.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[]){
  int *a, n, i; 
  cout << "Введите n: "; 
  cin >> n;
  cout << ' ';
  a = new int [n];  //Выделение памяти под массив
  for (i=0; i<n; i++) {
    cout << "Введите a[" << i << "]: ";
    cin >> a[i];
    cout << ' ';
  }

  int *buf = new int [n]; 
  //Выделение памяти под вспомогательный массив
  int j = 0; //Индекс вспомогательного массива
  for (i=0; i<n; i+=2) {  
  //Переписываем элементы с чётным индексом в новый массив
    buf[j] = a[i];
    j++;
  }
  for (i=1; i<n; i+=2) { 
  //Переписываем элементы с нечётным индексом в новый массив
    buf[j] = a[i];
    j++;
  }
  cout << "Преобразованный: " << ' ';
  for (i=0; i<n; i++) 
    cout << buf[i] << ' ';
  delete [] a;  //Освобождаем память
  delete [] buf;
  system("pause");
  return 0;
}

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

Пример 2.

#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
  float *mas;
  int m;
  scanf("%d",&m);
  mas=(float *)calloc(m,sizeof(float));
  //сейчас указатель q показывает на начало массива
  mas[0]=22.3;
  mas-=5;
  /*теперь начальный элемент массива имеет индекс 5, 
    а конечный элемент индекс n-5*/
  mas[5]=1.5;
  /*сдвиг индекса не приводит к перераспределению массива 
    в памяти и изменится начальный элемент*/
  mas[6]=2.5; // это второй элемент 
  mas[7]=3.5; // это третий элемент 
  mas+=5;
  /*теперь начальный элемент вновь имеет индекс 0, 
    а значения элементов q[0], q[1], q[2] равны 
    соответственно 1.5, 2.5, 3.5*/
  mas+=2;
  /*теперь начальный элемент имеет индекс -2, следующий -1, 
    затем 0 и т.д. по порядку*/
  mas[-2]=8.2;
  mas[-1]=4.5;
  mas-=2;
  /*возвращаем начальную индексацию, три первых элемента 
    массива q[0],q[1],q[2], имеют значения 8.2, 4.5, 3.5*/
  mas--;
  /*вновь изменим индексацию. Для освобождения области 
    памяти, в которой размещен массив q используется 
    функция free(q), но поскольку значение указателя q   
    смещено, то выполнение функции free(q) приведет к 
    непредсказуемым последствиям. 
    Для правильного выполнения этой функции указатель q 
    должен быть возвращен в первоначальное положение */
  free(++mas);
  system("pause");
  return 0;
}

Пример 3. Задача Иосифа Флавия или считалка Джозефуса.

Задача в своей основе имеет легенду. Отряд из 41-го сикария, защищавший галилейскую крепость Массада, не пожелал сдаваться в плен блокировавшим его превосходящим силам римлян. Сикарии стали в круг и договорились, что каждые два воина будут убивать третьего, пока не погибнут все. Самоубийство – тяжкий грех, но тот, кто в конце концов останется последним, должен будет его совершить. Иосиф Флавий, командовавший этим отрядом, якобы быстро рассчитал, где нужно стать ему и его другу, чтобы остаться последними. Но не для того, чтобы убить друг друга, а чтобы сдать крепость римлянам. В современной формулировке задачи участвует n воинов и убивают каждого k -го. Требуется определить номера m и t начальных позиций двоих воинов, которые должны будут остаться последними.

#include "stdafx.h"
#include <iostream>
using namespace std;

void kill(int *mass,int n,int i);
void krug(int *mass,int n,int k, int i=0);

int _tmain(int argc, _TCHAR* argv[]){
  int n,k,*mass,i;
  FILE *f;
  f=fopen("input.txt","r");
  fscanf(f,"%d %d",&n,&k);
  fclose(f);
  mass=(int *)malloc(n*sizeof(int));
  for (i=0;i<n;i++) mass[i]=i+1;
  f=fopen("output.txt","w");
  fprintf(f,"Исходная нумерация: \n");
  for (i=0;i<n;i++) fprintf(f,"%d ",mass[i]);
  fclose(f);
  krug(mass,n,k);
  f=fopen("output.txt","a+");
  fprintf(f,"\nОставшиеся в живых: \n");
  for (i=0;i<k;i++) fprintf(f,"%d ",mass[i]);
  fclose(f);  
  free(mass);
  system("pause");
  return 0;
}

void kill(int *mass,int n,int i) {
  int j;
  for (j=i;j<n-1;j++) 
    mass[j]=mass[j+1];
}

void krug(int *mass,int n,int k,int i) {
  int ii;
  if (n>k) {
    ii=i+k-1;
    if (ii>=n) ii=ii%n;
    kill(mass,n,ii);
    krug(mass,n-1,k,ii);
  }
}

Ключевые термины

Динамический массив – это массив, размер которого заранее не фиксирован и может меняться во время исполнения программы.

Значение указателя на одномерный динамический массив – это адрес выделяемой области динамической памяти.

Одномерный динамический массив – это одномерный массив, расположенный в динамической памяти.

Тип одномерного динамического массива – это тип элементов массива.

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

Краткие итоги

  1. При работе с массивами, размер которых заранее не известен, используют динамические массивы.
  2. Под объявлением одномерного динамического массива понимают объявление указателя на переменную заданного типа для того, чтобы данную переменную можно было использовать как динамический массив.
  3. Работа с одномерными динамическими массивами начинается с выделения участка памяти, а завершается освобождением ранее выделенного участка.
  4. Выделение и освобождение памяти под одномерный динамический массив выполняется с помощью операций или функций для работы с динамической памятью.
  5. Адресация элементов динамического массива осуществляется с помощью индексированного имени.
  6. Указатель на одномерный динамический массив не обязательно должен показывать на начальный элемент некоторого массива.
< Лекция 25 || Лекция 26: 123 || Лекция 27 >
Денис Курбатов
Денис Курбатов
Владислав Нагорный
Владислав Нагорный

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

Спасибо!

Андрей Садовщиков
Андрей Садовщиков
Россия