Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
Ваю
20 / 20 / 9
Регистрация: 21.04.2015
Сообщений: 567
1

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

06.07.2015, 20:36. Просмотров 504. Ответов 8
Метки нет (Все метки)

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

C++
1
2
3
4
5
6
7
double **d = (double **)calloc(n, sizeof(double *));// создаём матрицу
for(int i=0;i<n;i++)
    d[i] =  (double *)calloc(n, sizeof(double));
printf("Write elements of array:\n");// вводим элементы матрицы
for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
        scanf("%lf", &d[i][j]);

У меня имется вот это:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
__int16 i, j, l = 0, Min = numeric_limits<__int16>::max(), Max = numeric_limits<__int16>::min();
int SizeW = 0, SizeH = 0, SizeX = 0; __int16 * Arr = NULL, * ArrX = NULL;
 
 
srand((unsigned int)time(0)); SizeW = 10 + rand() % 255; SizeH = 10 + rand() % 255;
 
Arr = (__int16*)realloc(Arr, SizeW * SizeH * sizeof(__int16));
if (Arr == NULL) { free(Arr); Arr = NULL; puts("Error memory"); system("pause"); exit(1); }
else { i = 0;
    
while (j++ < SizeH) { 
    while (i++ < SizeW) {
        Arr[j][i] = 128 - rand() % 255; //ошибка
    } i = 0;
}
 
    puts(""); free(Arr); Arr = NULL; system("pause");
}
Добавлено через 16 минут
Про сквозную адресацию в массиве я знаю, просто она неудобна, для того, чтобы понять какой это адрс в многомерном представлеии нужно применять операции div/mod к одномерному представлению адресации и/или использовать перемножение и сложение для вычисления одномерного адреса, что тоже неудобно

Кликните здесь для просмотра всего текста
Добавлено через 1 час 29 минут
И почините форум, достало уже, что кнопки в форме быстрго ответа в IE не работают, а в FF не работает разворот спойлера, недохром не предлагать, хотя я не знаю работает оно там или нет, то, что жрёт 5 гигов места на винте и 2 гига оперативы браузером не является, я пользуюсь, пользовался и буду пользоваться только IE, а FF стоит для аниме
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.07.2015, 20:36
Ответы с готовыми решениями:

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

Динамическое выделение памяти для двумерного массива
Здравствуйте! В следующей программе я пытаюсь выделить динамически память для двумерного...

Реализовать фунцию для выделения блока свободной динамической памяти (кучи) заданного размера
4) Управления кучей. Реализовать фунцию для выделения блока свободной динамической памяти (кучи)...

Выделение динамической памяти
Чтобы выделить динамическую память под символьный массив надо так: int n; char *str; ...

Выделение динамической памяти
В одномерном массиве,*состоящем из п вещественных элементов, вычислить: - минимальный элемент...

8
Bazil
8 / 8 / 6
Регистрация: 02.09.2014
Сообщений: 19
06.07.2015, 23:03 2
Ваши примеры кода - это код на C++, а не на Си. Чтобы не мучаться с выделением памяти на C++, посмотрите в сторону vector в STL.
0
Ваю
20 / 20 / 9
Регистрация: 21.04.2015
Сообщений: 567
08.07.2015, 21:37  [ТС] 3
Bazil, я разбираюсь с азами, когда курил маны я натыкался на вектора, но туда мне лезть рано, а написал я в этом разделе поскольку выделение памяти использует realloc, которая является сишной функцией

2All: пытаюсь сделать из этог функцию, но не получается передать адрес массива по указателю наружу, чяднт?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <cstdlib>
#include <iostream>
#include <time.h>
using namespace std;
 
int GenRndArr(__int16 * Array, int & SizeWidth, int & SizeHeight);
 
void main() {
    __int16 l = 0, Min = numeric_limits<__int16>::max(), Max = numeric_limits<__int16>::min();
    int SizeW = 0, SizeH = 0, SizeX = 0; __int16 * Arr = NULL, * ArrX = NULL;
 
    if (!GenRndArr(Arr, SizeW, SizeH)) {
 
    puts(""); free(Arr); Arr = NULL; system("pause");
    }
}
 
int GenRndArr(__int16 * Arr, int & SizeW, int & SizeH)
{
    __int16 i, j, * ArrNew = NULL; srand((unsigned int)time(0));
 
    SizeW = 10 + rand() % 6; SizeH = 10 + rand() % 10;
 
    ArrNew = (__int16*)realloc(Arr, SizeW * SizeH * sizeof(__int16));
    if (ArrNew == NULL) { free(Arr); Arr = NULL; puts("Error memory"); system("pause"); /*return 1;*/ }
    else { Arr = ArrNew; j = 0;
 
        while (j < SizeH) { i = 0;
            while (i < SizeW)   { Arr[j * SizeW + i] = 128 - rand() % 255; i++; } j++;
        } j = 0;
 
        printf("SizeW = %d ; SizeH = %d\n", SizeW, SizeH);
        while (j < SizeH) { i = 0;
            while (i < SizeW) { printf("%4d ", Arr[j * SizeW + i]); i++; }
            puts(""); j++;
        }
    }
 
    if (Arr) { return 0; } else { return 1; }
}
0
Bazil
8 / 8 / 6
Регистрация: 02.09.2014
Сообщений: 19
08.07.2015, 22:52 4
Цитата Сообщение от Ваю Посмотреть сообщение
пытаюсь сделать из этог функцию, но не получается передать адрес массива по указателю наружу, чяднт?
Дело в том, что когда Вы передаете указатель __int16 * Arr в виде параметра функции, он копируется в стек. Далее работа происходит уже со скопированным указателем. Когда вызывается функция realloc, она присваивает новый указатель тому Arr, который скопирован в стек. Исходный же Arr так и остается нулевым. Выход из этой ситуации - возвращать указатель на Arr через return.
C
1
2
3
4
5
__int16 *GenRndArr(__int16 * Arr, int & SizeW, int & SizeH)
{
      ...
      return Arr;
}
0
Ваю
20 / 20 / 9
Регистрация: 21.04.2015
Сообщений: 567
08.07.2015, 22:56  [ТС] 5
Если я всё правильно понимаю, то я не могу использовать return, функция должна возвращать код отработки и массив одновременно, но если я испоьзую return, то мне придётся использовать присвоение и в результате этого я не получу кода отработки
0
Bazil
8 / 8 / 6
Регистрация: 02.09.2014
Сообщений: 19
08.07.2015, 23:10 6
В данной ситуации я не вижу другого выхода, кроме того, что я предложил. Код отработки можно записать, как параметр функции, то есть __int16 *GenRndArr(__int16 * Arr, int *KOD_OTRABOTKI, int & SizeW, int & SizeH). Но так как в коде написана такая конструкция: if (Arr) { return 0; } else { return 1; }, можно просто написать return Arr, а в main() проверять равен Arr нулю или нет
0
Ваю
20 / 20 / 9
Регистрация: 21.04.2015
Сообщений: 567
08.07.2015, 23:17  [ТС] 7
плохо, что иаче никак... не хотелось бы так делать, тогда подругому, как это переделать на указатели второго уравня? С ними передача по return не нужна. Возможно ли будет в этом случае получить желаемое?

Про указатели я понял вот это:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*объявление и инициализация указателя*/
/*тип данных*/ /*имя переменной*/ = /*значение*/;
/*тип данных*/ * /*имя указателя 1*/ = & /*имя переменной*/;
 
/*тип данных*/ ** /*имя указателя 2*/ = & /*имя указателя 1*/;
/*тип данных*/ *** /*имя указателя 3*/ = & /*имя указателя 2*/;
 
/*имя переменной*/ /*- это операция взятия значения переменной*/
& /*имя переменной*/ /*- это операция взятия адреса переменной*/
/*имя указателя*/ /*- это операция взятия адреса переменной*/
* /*имя указателя*/ /*- это операция взятия значения указателя*/
++ /*имя указателя*/ /*- это операция вычисления адреса следующей ячейки данных*/
 
 
int Var = 123, *pPnt, *pVar = &Var, **ppVar = &pVar, ***p3Var = &ppVar;
 
pPnt = &Var; /*получение адреса переменной*/
printf("%d, %d, %d, %d, %d, %x \n\n", Var, *pVar, **ppVar, ***p3Var, *pPnt, pPnt);
system("pause");
 
 
int num, q, *p;
 
num = 100; /* num присваивается 100 */
p = &num; /* p получает адрес num */
q = *p; /* q посредством p присваивается значение num */
printf("%d", q); /* выводит 100 */
system("pause");
 
/*объявление указателя на функцию*/
/*тип данных*/ (* /*имя указателя*/)(/*список аргументов функции*/);
 
#include <iostream>
using namespace std;
int NOD(int, int ); // прототип указываемой функции
int main(int argc, char* argv[])
{
  int (*pNOD)(int, int); // объявление указателя на функцию
  pNOD = NOD; // присваиваем адрес функции указателю ptrnod 
  int a, b;
  cout << "Enter first number: "; cin >> a;
  cout << "Enter second number: "; cin >> b;
  cout << "NOD = " << pNOD(a, b) << endl; // обращаемся к функции через указатель
  system("pause");
}
 
int NOD(int number1, int number2) // рекурсивная функция нахождения наибольшего общего делителя НОД
{
  if ( !number2 ) //базовое решение
    return number1;
  return NOD(number2, number1 % number2); // рекурсивное решение НОД
}
 
 
/*объявление и инициализация ссылок*/
/*тип данных*/ /*имя переменной*/ = /*значение*/;
/*тип данных*/ & /*имя ссылки*/ = /*имя переменной*/;
 
/*имя ссылки*/ /*- это операция взятия значения переменной*/
& /*имя ссылки*/ /*- это операция взятия адреса переменной*/
 
int Var = 123, &rVar = Var;
 
printf("%d, %x \n\n", rVar, &rVar);
system("pause");
Ссылки – особый тип данных, являющийся скрытой формой указателя, который при использовании автоматически разименовывается. Ссылка – это объект, который синтаксически выглядит как переменная, а по семантике является адресом. Ссылка может быть объявлена как другим именем, так псевдонимом переменной, на которую она ссылается. Любое изменение значения содержащегося в ссылке повлечёт за собой изменение этого значения в переменной, на которую ссылается ссылка. Через ссылку меняется значение ссылочной переменной, таким образом, сама ссылка не имеет копии значения переменной, она всего лишь ссылается на её адрес. Основное назначение указателя – это организация динамических объектов, то есть размер, которых может меняться (увеличиваться или уменьшаться). Тогда как ссылки предназначены для организации прямого доступа к тому, или иному объекту. Главное отличие состоит во внутреннем механизме работы. Указатели ссылаются на участок в памяти, используя его адрес. А ссылки ссылаются на объект, по его имени (тоже своего рода адрес). Ссылка является альтернативным именем объекта. Так или иначе ссылка должна быть инициализирована. Все операции производятся не над самой ссылкой, а над тем объектом, на который она указывает. После объявления ссылки её невозможно привязать к другой переменной. Важно отличать ссылки от оператора взятия адреса & (address of). Оператор взятия адреса используется для уже созданного объекта с целью получить его адрес (то есть адрес области памяти, где хранятся значения), а ссылка это только задание альтернативного имени объекта (с точки зрения программиста, а не реализации). Ссылки не могут быть неинициализированными, так как невозможно переинициализировать ссылку, она должна быть инициализирована сразу после создания, поэтому ссылка не может быть NULL. Ссылку нельзя использовать после того как объект, на который она указывала был уничтжен, иначе это вызовет ошибку доступа к памяти.
0
Bazil
8 / 8 / 6
Регистрация: 02.09.2014
Сообщений: 19
08.07.2015, 23:29 8
Цитата Сообщение от Ваю Посмотреть сообщение
как это переделать на указатели второго уравня?
Не очень понимаю, что Вы имеете ввиду под указателями второго уровня?

Добавлено через 8 минут
Если под указателями второго уровня Вы понимаете ссылки, то не смогу ответить на этот вопрос, не знаю, как работает компилятор со ссылками. Это нужно пробовать. Думаю, так как ссылка является тем же указателем, только "поумнее", скорее всего результат будет таким же, как и в случае с указателями
0
Ваю
20 / 20 / 9
Регистрация: 21.04.2015
Сообщений: 567
09.07.2015, 04:48  [ТС] 9
Под указателями 2го уравня я понимаю указатели 2го уравня (указатель на указатель, число вложений может быть любым), а ссылка - это ссылка, к тому же не "поумнее", а "потупее" и в добавок ссылки работают иначе, ссылки удобно использовать разве что для передачи адресов между функциями

Добавлено через 7 минут
Ничего лучше вот этого Не работает функция realloc() на форуме пока не нашёл, по крайней мере на данный момент, но меня напрягает копипаста (memmove) памяти внутри не зависимо от того, было перемещение в новое место при выделении или нет

Добавлено через 1 час 24 минуты
Уточню ещё, по заданию мне запрещено явным образом использовать глобальные перменные, кто знает как можо передать значение наружу без их использования - помогите пожалуйста, я не знаю как ещё можно сделать.

С использованием глобальных переменных можно так:

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <cstdlib>
#include <iostream>
#include <time.h>
using namespace std;
 
int GenRndArr(__int16 * Array, int & SizeWidth, int & SizeHeight);
 
__int16 * Arr = NULL, * ArrX = NULL;
 
void main() {
    __int16 Min = numeric_limits<__int16>::max(), Max = numeric_limits<__int16>::min();
    int SizeW = 0, SizeH = 0, SizeX = 0;
 
    if (!GenRndArr(Arr, SizeW, SizeH)) {
 
    puts(""); free(Arr); Arr = NULL; system("pause");
    }
}
 
int GenRndArr(__int16 * Arr, int & SizeW, int & SizeH)
{
    __int16 i, j, * ArrNew = NULL; srand((unsigned int)time(0)); 
 
    SizeW = 10 + rand() % 6; SizeH = 10 + rand() % 10;
 
    ArrNew = (__int16*)realloc(Arr, SizeW * SizeH * sizeof(*Arr));
    if (ArrNew == NULL)
    { free(Arr); Arr = NULL; puts("Error memory"); system("pause"); /*return 1;*/ }
    else { Arr = ArrNew; j = 0;
 
        while (j < SizeH) { i = 0;
            while (i < SizeW)   { Arr[j * SizeW + i] = 128 - rand() % 255; i++; } j++;
        } j = 0;
 
        printf("SizeW = %d ; SizeH = %d\n", SizeW, SizeH);
        while (j < SizeH) { i = 0;
            while (i < SizeW) { printf("%4d ", Arr[j * SizeW + i]); i++; }
            puts(""); j++;
        }
    }
 
    ::Arr = Arr;
    if (Arr) { return 0; } else { return 1; }
}


Добавлено через 3 часа 39 минут
При использовании глобальных переменных функция будет выглядеть так:
C++
1
int GenRndArr(int & SizeWidth, int & SizeHeight);
Т.е __int16 * & Arr в ней бесмыслено и не нужно.

Вроде разобрался...

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

Нужно всего-навсего ввести ещё один дополнительный указатель, который инициализировать в параметрах через ссылку, в конечном итоге выделение динамической памяти внутри функции БЕЗ использования return, циклов и многоуравневых указателей выглядет как:

Коменты:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int /*Имя функции*/(/*Тип данных массива*/* & /*Имя массива подробно*/, /*Тип данных для адресации массива*/ & /*Длинна строки подробно*/, /*Тип данных для адресации массива*/ & /*Чисто строк подробно*/);
 
void main() {
    /*Тип данных для адресации массива*/ /*Длинна строки*/ = 0, /*Чисто строк*/ = 0; /*Тип данных массива*/ * /*Имя массива*/ = NULL;
    /*Имя функции*/(/*Имя массива*/, /*Длинна строки*/, /*Чисто строк*/);
}
 
int /*Имя функции*/(/*Тип данных массива*/* & /*Имя массива*/, /*Тип данных для адресации массива*/ & /*Длинна строки*/, /*Тип данных для адресации массива*/ & /*Чисто строк*/)
{
    /*Тип данных для адресации массива*/ /*Счётчик столбцов*/, /*Счётчик строк*/;
    /*Тип данных массива*/ */*Имя временного указателя массива*/ = NULL, */*Имя указателя перемещённого в памяти массива при выделении памяти*/ = NULL;
 
    /*Ввод рвзмеров массива*/; //srand((unsigned int)time(0)); SizeW = 10 + rand() % 6; SizeH = 10 + rand() % 10;
 
    /*Имя указателя перемещённого в памяти массива при выделении памяти*/ = (/*Тип данных массива*/*)realloc(/*Имя временного указателя массива*/, /*Длинна строки*/ * /*Чисто строк*/ * sizeof(*/*Имя временного указателя массива*/));
    if (/*Имя указателя перемещённого в памяти массива при выделении памяти*/ == NULL)
    { free(/*Имя временного указателя массива*/); /*Имя временного указателя массива*/ = NULL; puts("Error memory"); system("pause"); /*return 1;*/ }
    else { /*Счётчик: чисто строк*/ = 0; /*Имя массива*/ = /*Имя указателя перемещённого в памяти массива при выделении памяти*/;
 
        while (/*Счётчик: чисто строк*/ < /*Чисто строк*/) { /*Счётчик: чисто столбцов*/ = 0;
            while (/*Счётчик: чисто столбцов*/ < /*Чисто столбцов*/) { Arr[/*Счётчик: чисто строк*/ * /*Чисто столбцов*/ + /*Счётчик: чисто столбцов*/] = 128 - rand() % 255; /*Счётчик: чисто столбцов*/++; } /*Счётчик: чисто строк*/++;
        } /*Счётчик: чисто строк*/ = 0;
 
//code
 
    }
 
    if (/*Имя массива*/) { return 0; } else { return 1; }
}

Код:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int GenRndArr(__int16* & Array, int & SizeWidth, int & SizeHeight);
 
void main() {
    int SizeW = 0, SizeH = 0; __int16 * Arr = NULL;
    GenRndArr(Arr, SizeW, SizeH);
}
 
int GenRndArr(__int16 * & Arr, int & SizeW, int & SizeH)
{
    __int16 i, j, *ArrTmp = NULL, *ArrNew = NULL; srand((unsigned int)time(0));
 
    SizeW = 10 + rand() % 6; SizeH = 10 + rand() % 10;
 
    ArrNew = (__int16*)realloc(ArrTmp, SizeW * SizeH * sizeof(*ArrTmp));
    if (ArrNew == NULL)
    { free(ArrTmp); ArrTmp = NULL; puts("Error memory"); system("pause"); /*exit(1);*/ }
    else { j = 0; Arr = ArrNew;
 
        while (j < SizeH) { i = 0;
            while (i < SizeW) { Arr[j * SizeW + i] = 128 - rand() % 255; i++; } j++;
        } j = 0;
 
//code
 
    }
 
    if (Arr) { return 0; } else { return 1; }
}
0
09.07.2015, 04:48
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.07.2015, 04:48

Выделение динамической памяти для двумерного массива.
#include &lt;iostream&gt; int main() { setlocale( LC_ALL,&quot;Russian&quot; ); int N, M; std::cout &lt;&lt;...

Выделение динамической памяти для массива
можно ли так выделять? int array = new int;оно работает,но правильно ли это?

Выделение динамической памяти для массива точек
Доброго времени суток. Вот у нас есть структура точка struct point { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru