C++ Builder: создание динамического массива

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

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

int A[5]; // определение массива из 5 элементов типа int
int A[5][5]; // определение массива размерностью 5х5 элементов типа int
int A[]={1,2,3}; // определение массива с инициализацией его элементов
int A[5]={1,2}; // определение массива с частичной инициализацией его элементов
static int A[5]; // определение массива. Все элементы этого массива примут значение 0

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

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

double* Mas1 = new double[kol1];

Здесь Mas1 – название массива, а kol1 – его размерность, которая будет определена по ходу выполнения программы.

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

double** Mas2 = new double*[kol2];
for(int i=0;i<kol2;i++) 
   Mas2[i]=new double[kol2];

Здесь Mas2 – название массива, а kol2 – его размерность, которая будет определена по ходу выполнения программы.

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

Надеюсь, разберетесь =)

Будут вопросы – задавайте!

26 comments on “C++ Builder: создание динамического массива

  1. double** Mas2 = new double*[kol2];
    for(int i=0;i<=kol2;i++)
    Mas2[i]=new double[kol2];

    В данном случае, если переменная kol2 будет содержать некое число, массив запонен. И потом если поиграться с kol2, то размерность массива будет меняться дальше ?

  2. В данном случае переменная kol2 служит не для заполнения массива, а для установки его размерности. И да, она может быть задана в процессе выполнения программы. Переопределить размерность массива можно будет несколько раз (в процессе выполнения приложения). Как-то так.

    1. Супер. Самый подробный ответ. И про malloc с realloc-ом
      написано. И более правильное использование типа String, не говоря уж о списке.

      Всем рекомендую этот ресурс —http://ru.stackoverflow.com/
      И хабр, конечно 🙂

  3. Извините, а в чем «динамичность» данного примера? Лишь в том, что он выделяется в динамической памяти, а размерность при этом все равно остается фиксированной?

    1. Размерность массива не фиксирована (имеются ввиду примеры 2 и 3).
      В них значение параметров kol1 и kol2 могут быть заданы во время выполнения программы. Потестируйте )

      1. 1. Сделайте через realloc. В чем проблема ?
        Только через realloc делать — это изврат.
        2. Можно список использовать или свой написать 🙂

    2. Не придирайтесь.
      Динамичность, потому, что new используется 🙂
      По определению.

      А так, конечно, надо было так написать.

      unsigned int n;

      cin >> n;

      int * arr = new int[n];

      for(unsigned int i = 0; i < n; i ++)
      cin << arr[i];

      delete arr;

      Устроит ?

  4. Проще на примере)
    Необходимо заполнить массив случайными числами так, чтобы сумма этих чисел была равна какому-то большому значению. Брать границы рандома и выделять сразу большой кусок памяти нельзя, т.е. нужно размер этого массива постоянно увеличивать и увеличивать, пока не выполнится условие. Данную задачу можно сделать через шаблон vector, но хочется и по-другому)

    1. Не пойму, в чем у вас проблема?
      Пример

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
      Randomize();
      int kol=2;
      double max=150;
      double Sum=0;
      double* Mas = new double[kol];
      for(int i=0;i<kol;i++)
      {
      Mas[kol]=random(kol); // генерируем элемент
      Sum+=Mas[kol]; // считаем сумму
      if(Sum<max)  // проверяем условие
      kol++; // увеличиваем количество элементов в массиве
      }

      Тестировать не тестировала, но, скорее всего, будет работать )
      Здесь Sum = сумма, max — ваше максимальное значение, начальное количество элементов массива задано как 2 (меньше одного ставить не стоит).
      Потестируете — отпишитесь.

      1. Я протестировал данный код, он не работает.Система не дает увеличить размер массива больше чем на корень выбранного типа, так при типе int максимум для такого массива будет 8 ячеек.

        1. Если вам нужно больше — используйте long int. Или объясните конкретней задачу. Если у вас переполнение, это одно, если не выходит создать динамический массив — это другое.

        2. Это бред. Нет такой зависимости. Интересно, как это система делает ? Какую ошибку Вы получаете ?

          У Вас просто может возникнуть range check error.
          Надо соблюдать верную индексацию. От 0 до kol -1 включительно.

      2. Работать не будет.
        Вы создали массив на 2 элемента,
        а обращаетесь к нему, будто в нем больше элементов.
        Будет ошибка выхода за границу массива. Только надо опцию компиляции соответствующую ставить range check error.
        И освободить память забыли — delete.
        В цикле лишняя переменная. Либо используйте i для индексации —либо kol. Kol ++ не увеличивает кол-во эл-тов в массиве. Эта переменная вообще здесь не нужна.

        Я уж не говорю о том, что надо бы из массива выйти по условию с помощью break. Надо поменять в цикле условие.
        Вместо i < kol поставить sum < max.

        Проблема решается использованием сишны= функций.
        Первый раз распределяем массив на 1 элемент ф-ей malloc
        Затем, если надо, переопределяем размер массива й-ей realloc.

        Не забываем освобождать память массива ф-ей free

        1. Да, возможно не будет: приведете пример рабочего кода?)
          На счет освобождения памяти — согласна.

          1. И Вы еще не согласны насчет остального ?
            Докажите на примере своего кода, пожалуйста, что я неправ 🙂

      3. Уважаемый Автор сайта. Настоятельно рекомендую, прежде, чем писать чушь, хотя бы эту чушь тестировать.

        И еще рекомендую — внимательно читать комментарии.
        Там, редко правда, но попадаются верные ответы.

        Настоятельно рекомендую изучить эту ссылку http://ru.stackoverflow.com/questions/55492/%D0%9A%D0%B0%D0%BA-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D1%82%D1%8C-%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2-%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8-%D0%B2-%D1%85%D0%BE%D0%B4%D0%B5-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D1%8B

        Это из ответа Кассандры. Там самый полный и обстоятельный ответ, как эту задачу решать. Заодно и свой уровень повысите.

        1. Прям уж чушь?)
          У меня не было цели сделать самый полный обзор всех способов задания динамического массива. Я привела пример как это будет работать.

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

          Ничего личного, но с чего вы взяли, что приведенная по линку информация «самый полный и обстоятельный ответ»?)

    2. void main (void)
      {

      int a;
      int * arr;
      int i, n;
      int s;

      srand( time(NULL) );

      a = rand();

      s = 0;
      i = 0;
      arr = (int*)malloc( sizeof(arr)*sizeof(arr[0]) );
      do
      {
      arr[i] = rand()/ 100;
      printf( «%d;», arr[i] );
      s += arr[i];
      i++;
      arr = (int*)realloc( arr, sizeof(arr)*( sizeof(arr[0]) + 1 ) );
      }
      while ( s <=a );

      printf("n%d", s);

      free(arr);

      getch();
      }

  5. Проверил, хоть и в более простой форме — действительно, работает) Без циклов, просто массив и присвоение 3х значений, с последующим выводом.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
        int *Mas = new int[kol];
        Mas[0] = 0;
        q.setNum(Mas[0]);
        msgBox-&gt;setText(q);
        msgBox-&gt;exec();
        Mas[1] = 1;
        q.setNum(Mas[1]);
        msgBox-&gt;setText(q);
        msgBox-&gt;exec();
        Mas[10] = 10;
        q.setNum(Mas[10]);
        msgBox-&gt;setText(q);
        msgBox-&gt;exec();

    Если выводит 10й элемент, значит, он создается.

    Проблема, значит, в понимании этого механизма %) В голове почему-то сидит устойчивое «массив на 2 элемента, больше — ни-ни».
    Спасибо Вам за потраченное время) Забираю свои слова про «динамичность» обратно.

    1. Интересно, как Вы проверяли ?
      У Вас ни переменная kol не описана нигде.
      Мало того. Она и не проинициализирована нигде.

      Предположим, что Вы забыли прописать строчку int kol.
      Тогда, в зависимости от компилятора, ей будет присвоено
      0 либо случайное значение.

      Соответственно, либо Вы сразу вылетите с range check error —
      выход за границу массива. При условии, что у Вас включена соответствующая опция компиляции.

      В противном случае, программа может и выполнится (если kol примет значение > 0) , но писать в нераспределенную память — верх идиотизма.

      А если kol примет значение > 0, то все будет работать.
      В вероятностном режиме 🙂

      Повторюсь, если Вы завели массив на kol элементов,
      так и адресуйтесь к нему, как к массиву на n элементов.
      Иное — неверно.

  6. Підкажіть ,будь-ласка, як реалізувати процес заміни кожного стовпця матриці елементами деякого вектора. Намагаюсь реалізувати метод Крамера.
    Посилання на алгоритм методу: https://www.mathros.net.ua/rozvjazok-systemy-linijnyh-algebraichnyh-rivnjan-metodom-kramera.html).

  7. Только обращаться по очереди. Т.е. получить количество столбцов и в цикле обращаться к каждому из них заменяя на свой вектор. Не забудьте это делать в отдельной переменной (не обновляя исходного массива)))

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

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