Как увеличить динамический массив c
Перейти к содержимому

Как увеличить динамический массив c

  • автор:

Увеличение динамического массива в С++

Возникла проблемка которая не дает мне спокойствия. Суть такова, есть указатель на целое int *a;Затем выделяем память, а=new int[10]; потом, заполнили его в цикле числами. И тут мне надо еще добавить ячеек в массив а, что бы туда записать числа, можно конечно через временный массив но мне не хотеться. Когда так делаю а=new int[20]; то вся информация что была раньше исчезает. Как увеличить массив без потери данных? Заранее спасибо!
Пример

int *a;
a =new int [10];

a=new int [20];//тут вся информация исчезает

11 ответов

#include <iostream>
#include <vector>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
<
vector<int> coll;
for(int i = 0;i < 10;++i)
coll.push_back(i);
coll.push_back(10);
coll.push_back(22);
for(int i = 0;i < coll.size();++i)
cout<<coll<<‘ ‘;
cout<<endl;
return 0;
>

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

Ну или можно исспользовать указатель на тип (который сам по себе тип но у него есть оператор присваивания). ))

Информация не исчезает, а просто становится недоступной, потому что выделяется новый блок, но в программе отсутствует указатель на старый блок — утечка памяти.
Для простых типов данных можно использовать функцию realloc

Я постоянно работаю с динамическими массивами в Object Pascal и PHP. Вот внезапно возникла необходимость использования языка C++ и пришлось немного почесать голову )). :confused:

Библиотека <vector> это конечно хорошо, но почему изменение длины массива не реализовано в стандартной библиотеке. А ведь C++ самый успешный и развивающийся язык программирования.

Учитывая тот факт что в С++ можно объявить массив где угодно в теле алгоритма, то преимущества динамического массива сужаются к двум:
1. можно создавать (суб)подмассивы произвольной длинны (в принципе существенный фактор);
2. тут же удалить массив из памяти после выполнения необходимых операций (не дожидаясь конца функции и т.п.).

А для Object Pascal преимущества динамического массива увеличиваются как минимум на два:
3. не занимает памяти, пока массив не востребован, т.е. не задана длинна (большой бонус, поскольку переменные объявляются только в разделе var и занимают память от начала алгоритма);
4. можно сколь угодно удлинять и укорачивать массив без потери данных в пределах усечения ( пример SetLength(Massiv, 1) ).

Резонные вопросы:
1. может Object Pascal хитрит, т.е. метод SetLength создает второй массив новой длины и копирует данные с первого и переписывает указатель?
2. или забросили и недоделали данную операцию в С++ поскольку была библиотека <vector> (бред какой-то)? 😮

Ответы на свои вопросы искал заранее, но нигде ничего не нашел. Может Вы, где что видели или знаете? Заранее благодарен. :rolleyes:

Как увеличить размер массива в C++?

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

Она возвращает адрес нового массива,далее пытаюсь принять этот результат:

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

Resizing dynamic array in c++

I have some code that is producing unexpected results. Here is the code:

The function A(int** arr) works fine as far as I can tell and actually resizes the array. However, in the last for loop in main(), when the array is printing, the first two elements of the array are not 0 and 1 like it is supposed to be. Here is the result I am getting:

Those first two ints after the space are different each time the program is executed. After some debugging I found out that the first two elements print correctly until the iterator i=13 in the second to last for loop in main(). Then the first two elements in the array take on some large numbers. I am not sure why this is happening and I have been working on this for a couple of hours now 🙁 Any help is appreciated.

2 Answers 2

A() is not modifying nums to point at the new array. Even if it were, it is deleting the new array, so nums would end up pointing at invalid memory. You need to declare the arr parameter as a reference, and delete the old array instead of the new array:

For what you are attempting, I think you have too much indirection. Try removing a level:

Since you are using C++, you should be using a std::vector instead of a raw array, then you can eliminate A() altogether:

First of all, your function, A , does not resize anything. It prints a newline character to standard output, it multiplies the global size variable by 2, and then it leaks some memory. That’s it.

Now, because it multiplies size by 2 (going from 10, to 20), you run into a problem, here:

Here, you are trying to access elements 10 through 19 of the array which nums points to. But the array which nums points to only has 10 elements (numbered 0 through 9), so your code has undefined behavior.

    The Overflow Blog
Related
Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.3.3.43278

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Динамическое выделение памяти в Си

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

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

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

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

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

Стандартные функции динамического выделения памяти

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

Функции динамического распределения памяти:

Для использования функций динамического распределения памяти необходимо подключение библиотеки <malloc.h> :

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

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

Память, динамически выделенная с использованием функций calloc(), malloc() , может быть освобождена с использованием функции

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

Динамическое выделение памяти для одномерных массивов

Форма обращения к элементам массива с помощью указателей имеет следующий вид:

Пример на Си : Организация динамического одномерного массива и ввод его элементов.

Результат выполнения программы:
Динамическое выделение памяти

Динамическое выделение памяти для двумерных массивов

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

index = i*m+j;

где i — номер текущей строки; j — номер текущего столбца.

Рассмотрим матрицу 3×4 (см. рис.)
Матрица 3х4
Индекс выделенного элемента определится как

index = 1*4+2=6

Объем памяти, требуемый для размещения двумерного массива, определится как

n·m·(размер элемента)

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

Правильное обращение к элементу с использованием указателя будет выглядеть как

  • p — указатель на массив,
  • m — количество столбцов,
  • i — индекс строки,
  • j — индекс столбца.

Пример на Си Ввод и вывод значений динамического двумерного массива

Результат выполнения
Ввод и вывод значений динамического двумерного массива

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

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

Динамическое выделение памяти под двумерный массив

Графически такой способ выделения памяти можно представить следующим образом.
Выделение памяти под двумерный массив - графическое представление
При таком способе выделения памяти компилятору явно указано количество строк и количество столбцов в массиве.
Пример на Си

Результат выполнения программы аналогичен предыдущему случаю.

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

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

Пример на Си : Свободный массив

Результат выполнения
Свободный массив

Перераспределение памяти

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

  • Выделить блок памяти размерности n+1 (на 1 больше текущего размера массива)
  • Скопировать все значения, хранящиеся в массиве во вновь выделенную область памяти
  • Освободить память, выделенную ранее для хранения массива
  • Переместить указатель начала массива на начало вновь выделенной области памяти
  • Дополнить массив последним введенным значением

Все перечисленные выше действия (кроме последнего) выполняет функция

  • ptr — указатель на блок ранее выделенной памяти функциями malloc() , calloc() или realloc() для перемещения в новое место. Если этот параметр равен NULL , то выделяется новый блок, и функция возвращает на него указатель.
  • size — новый размер, в байтах, выделяемого блока памяти. Если size = 0 , ранее выделенная память освобождается и функция возвращает нулевой указатель, ptr устанавливается в NULL .

Размер блока памяти, на который ссылается параметр ptr изменяется на size байтов. Блок памяти может уменьшаться или увеличиваться в размере. Содержимое блока памяти сохраняется даже если новый блок имеет меньший размер, чем старый. Но отбрасываются те данные, которые выходят за рамки нового блока. Если новый блок памяти больше старого, то содержимое вновь выделенной памяти будет неопределенным.

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

Результат выполнения
realloc()

Комментариев к записи: 99

for ( int i = 0; i < 4; i++) <
for ( int j = 0; j < 4; j++)
<
printf( "%d " , mas[i][j]);
>
printf( "\n" );
>
printf( "\n" );
for ( int i = 0; i < 4; i++) <
for ( int j = i + 1; j < 4; j++)
<
N = (abs(mas[1][3]) + abs(mas[1][3]) + abs(mas[1][3]) + abs(mas[1][1]) + abs(mas[1][1]));
printf( "%d " , mas[i][j]);
>
printf( "\n" );
>
printf( "\n" );
for ( int i = 1; i < 4; i++) <
for ( int j = 0; j < i; j++) <
printf( "%d " , mas[i][j]);
M = (abs(mas[1][2]) + abs(mas[1][2]) + abs(mas[1][3]) + abs(mas[1][3]) + abs(mas[1][3]) + abs(mas[3][1]) + abs(mas[3][1]));
>
printf( "\n" );
>
printf( "%d " , N);
printf( "%d " , M);
G = N — M;
printf( "\n" );
printf( "%d " , G);
printf( "\n" );
>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

void allocate( /* нужные параметры указать тут */ );
void fill( /* нужные параметры указать тут */ );
void print( /* нужные параметры указать тут */ );
void release( /* нужные параметры указать тут */ );
void find_min( /* нужные параметры указать тут */ );

int main( int argc, char const *argv[])
<
int NO_OF_COLS = 0;
int NO_OF_ROWS = 0;

int ** matrix = NULL ;

allocate( /* нужные аргументы передавать сюда */ );

fill( /* нужные аргументы передавать сюда */ );

print( /* нужные аргументы передавать сюда */ );

find_min( /* нужные аргументы передавать сюда */ );

release( /* нужные аргументы передавать сюда */ );

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

void allocate( /* нужные параметры указать тут */ );
void fill( /* нужные параметры указать тут */ );
void print( /* нужные параметры указать тут */ );
void release( /* нужные параметры указать тут */ );
void find_min( /* нужные параметры указать тут */ );

int main( int argc, char const *argv[])
<
int NO_OF_COLS = 0;
int NO_OF_ROWS = 0;

int ** matrix = NULL ;

allocate( /* нужные аргументы передавать сюда */ );

fill( /* нужные аргументы передавать сюда */ );

print( /* нужные аргументы передавать сюда */ );

find_min( /* нужные аргументы передавать сюда */ );

release( /* нужные аргументы передавать сюда */ );

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
int main()
<
int **a; // указатель на указатель на строку элементов
int i, j, n, m;
system( "chcp 1251" );
system( "cls" );
printf( "Введите количество строк: " );
scanf( "%d" , &n);
printf( "Введите количество столбцов: " );
scanf( "%d" , &m);

// Выделение памяти под указатели на строки
a = ( int **)malloc(n * sizeof ( int *));
if (a== NULL )

// Ввод элементов массива
for (i = 0; i<n; i++) // цикл по строкам
<
// Выделение памяти под хранение строк
a[i] = ( int *)malloc(m * sizeof ( int ));
if (a[i]== NULL ) < printf( "Память не выделена\n" ); n= i; goto ALARM; >
for (j = 0; j<m; j++) // цикл по столбцам
<
printf( "a[%d][%d] = " , i, j);
scanf( "%d" , &a[i][j]);
>
>
// Вывод элементов массива
for (i = 0; i < n; i++) // цикл по строкам
<
for (j = 0; j < m; j++) // цикл по столбцам
<
printf( "%5d " , a[i][j]); // 5 знакомест под элемент массива
>
printf( "\n" );
>

// Очистка
ALARM:
for ( int ii = 0; ii < n; ii++) // цикл по строкам
free(a[ii]); // освобождение памяти под строку
free(a);
getchar(); getchar();
return 0;
>

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <clocale>
#include <iostream>
#include <malloc.h>
#define S 5

using namespace std;

void two_dim_input( int ** a)
<
srand(time(0));
for ( int i = 0; i < S; i++)
<
for ( int u = 0; u < S; u++)
<
*(( int *)a + i * S + u) = rand() % 99;
>
>

int ** mas = ( int **)calloc(S, sizeof (*mas));
for ( int i = 0; i < S; i++)
*(mas + i) = ( int *)calloc(S, sizeof (mas));
two_dim_input(mas);
two_dim_output(mas);

two_dim_sum(mas);
printf( "\n\n" );
two_dim_output(mas);
for ( int i = 0; i < S; i++) // цикл по строкам
free(mas[i]); // освобождение памяти под строку
free(mas);
>

cout << "_asm code started working" << endl;

_asm <
pushf // помещаем регистр флагов в стек
pop var // извлекаем операнд из стека (шта?)
>

cout << "_asm code finished working" << endl;

short *var;
var = new short[1];
cout << "_asm code started working" << endl;

_asm <
pushf // помещаем регистр флагов в стек
pop *var[0] // извлекаем операнд из стека (шта?)
>

cout << "_asm code finished working" << endl;

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>

int main()
<
system( "chcp 1251"); system("cls" );
srand(time( NULL ));
int * b, n, m;
printf( "кол-во строк: "); scanf_s("%d" , &n);
printf( "кол-во столбцов: "); scanf_s("%d" , &m);
b = ( int *)malloc(n * m * sizeof ( int ));
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++)
*(b + i * m + j) = rand() % 100;
>
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++) <
printf( "%4d" , *(b + i * m + j));
>
printf( "\n" );
>
int max, maxi = 0, maxj = 0;
max = *b;
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++)
if (*(b + i * m + j) == max) <
continue;
>
else if (*(b + i * m + j) > max) <
max = *(b + i * m + j);
maxi = i;
maxj = j;
>
>
printf( "\nMax = %d" , max);
printf( "\nmaxi = %d" , maxi);
printf( "\nmaxj = %d" , maxj);

for ( int i = maxi; i < n; i++) <
for ( int j = 0; j < m; j++) <
*(b + (i — 1) * m + j) = *(b + i * m + j);
>
>
n—;
printf( "\nматрица после удаления строки\n\n" );
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++) <
printf( "%4d" , *(b + i * m + j));
>
printf( "\n" );
>
m++;
for ( int i = 0; i < n; i++) <
for ( int j = m — 1; j > maxj — 1; j—) <
*(b + i * m + j) = *(b + i * m + (j — 1)); //зміщуємо стовбчики вправо
>
>
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++) <
*(b + i * m + maxj) = rand() % 100;
>
>
printf( "\nматрица после добавления столбца\n\n" );
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++) <
printf( "%4d" , *(b + i * m + j));
>
printf( "\n" );
>
return 0;
>
else return 0;
>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>

int main()
<
system( "chcp 1251"); system("cls" );
srand(time( NULL ));
int * b, n, m;
printf( "кол-во строк "); scanf_s("%d" , &n);
printf( "кол-во столбцов: "); scanf_s("%d" , &m);
b = ( int *)malloc(n * m * sizeof ( int ));
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++)
*(b + i * m + j) = rand() % 100;
>
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++)
printf( "%4d" , *(b + i * m + j));
>
int max, maxi = 0, maxj = 0;
max = *b;
for ( int i = 0; i < n; i++) <
for ( int j = 0; j < m; j++)
if (*(b + i * m + j) == max) <
continue;
>
else if (*(b + i * m + j) > max) <
max = *(b + i * m + j);
maxi = i;
maxj = j;
>
>
printf( "\nMax = %d" , max);
printf( "\nmaxi = %d" , maxi);
printf( "\nmaxj = %d" , maxj);
>

#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "stdio.h"
#include "conio.h"
#include "math.h"
#include <malloc.h>
#include "locale.h"
#include "string.h"
#include "windows.h"
#include "time.h"

int main()
<
int ** a; // указатель на указатель на строку элементов
int ** b; // указатель на указатель на строку элементов
int i, j, n, m;
int counter = 0;
system( "chcp 1251" );
system( "cls" );
printf( "Введите количество строк: " );
scanf( "%d" , &n);
printf( "Введите количество столбцов: " );
scanf( "%d" , &m);
// Выделение памяти под указатели на строки
a = ( int **)malloc(n * sizeof ( int *));
// Ввод элементов массива
for (i = 0; i < n; i++) // цикл по строкам
<
// Выделение памяти под хранение строк
a[i] = ( int *)malloc(m * sizeof ( int ));
for (j = 0; j < m; j++) // цикл по столбцам
<
printf( "a[%d][%d] = " , i, j);
scanf( "%d" , &a[i][j]);
>
>

// Вывод элементов массива
for (i = 0; i < n; i++) // цикл по строкам
<
for (j = 0; j < m; j++) // цикл по столбцам
<
printf( "%5d " , a[i][j]); // 5 знакомест под элемент массива
>
printf( "\n" );
>

b = ( int **)malloc(n * sizeof ( int *));
// Ввод элементов массива
for (i = 0; i < n; i++) // цикл по строкам
<
// Выделение памяти под хранение строк
b[i] = ( int *)malloc(m * sizeof ( int ));
for (j = 0; j < m; j++) // цикл по столбцам
<
printf( "a[%d][%d] = " , i, j);
scanf( "%d" , &b[i][j]);
>
>

for (i = 0; i < n; i++) // цикл по строкам
<
for (j = 0; j < m; j++) // цикл по столбцам
<
printf( "%5d " , b[i][j]); // 5 знакомест под элемент массива
>
printf( "\n" );
>

a = ( int **)realloc(a, (2*n*m) * sizeof ( int ));

for (i = n; i < 2*n; i++) // цикл по строкам
<
for (j = 0; j < m; j++) // цикл по столбцам
<
a[i][j] = b[counter][j];
counter++;
>
printf( "\n" );
>

for (i = 0; i < 2*n; i++) // цикл по строкам
<
for (j = 0; j < m; j++) // цикл по столбцам
<
printf( "%5d " , a[i][j]); // 5 знакомест под элемент массива
>
printf( "\n" );
>

// Очистка памяти
for (i = 0; i < n; i++) // цикл по строкам
free(a[i]); // освобождение памяти под строку
free(a);

for (i = 0; i < n; i++) // цикл по строкам
free(b[i]); // освобождение памяти под строку
free(b);

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

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