Я пытаюсь написать программу, которая сначала динамически инициализирует массив очереди для 100 элементов int. Всякий раз, когда очередь заполняется, а другой элемент должен быть поставлен в очередь, исходный массив должен удваивать размер, чтобы вставлять новые элементы. В случае, если элементы отложены, а количество элементов, из которых состоит очередь, падает ниже половины его фактического размера, размер очереди должен быть разрезан пополам. Однако его размер не должен опускаться ниже 10.Расширение и сокращение массива с использованием realloc
Я пытаюсь расширить и сжать массив с помощью realloc, однако у меня возникают проблемы с пониманием его механики, особенно при возврате нового указателя. Вот моя программа (с некоторыми резервными printf
по debugging
причинам):
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <iso646.h>
void enqueue(int arr[], int* lastElementIdx, int *length, int element);
int dequeue (int arr[], int* lastElementIdx, int *length);
void printQueue(const int arr[], int lastElementIdx);
int expandArray(int *arr, int length);
int shrinkArray(int *arr, int length, bool min);
void test1(int *arr, int* lastElementIdx, int *length)
{
int* temp = arr;
printf("\nprintQueue #1:\n"); //print queue, should be empty
printQueue(temp, *lastElementIdx);
for(int i = 1; i <= 100; i++) //insert elemnts to queue
enqueue(temp, lastElementIdx, length, i);
printf("\nprintQueue #2:\n"); //print queue
printQueue(temp,*lastElementIdx);
printf("\nAusgabe von dequeue:\n"); // dequeue array
while(*lastElementIdx > *length/4)
printf("\naddress: %p\tElement: %d\n", temp, dequeue(temp, lastElementIdx, length));
free(temp);
}
void test2(int *arr, int* lastElementIdx, int *length)
{
int *temp = arr;
printf("\n************\nEnqueue beyond queue[N-1]:\n");
puts("Queue aufbauen...");
for(int i = 1; i <= 150; i++)
enqueue(temp, lastElementIdx, length, i);
printf("\nprintQueue:\n");
printQueue(temp,*lastElementIdx);
printf("\nDequeue:\n");
while(*lastElementIdx > *length/4)
printf("\naddress: %p\tElement: %d\n", temp, dequeue(temp, lastElementIdx, length));
free(temp);
}
int main(int argc, char const *argv[])
{
int startingPoint = -1, *lastElementIdx = &startingPoint, N = 100, *length = &N;
int *queue = (int*) calloc(*length, sizeof(*queue));
test2(queue, lastElementIdx, length);
queue = (int*) calloc(*length, sizeof(*queue));
test1(queue, lastElementIdx, length);
return 0;
}
int expandArray(int *arr, int length)
{
/*function to double the array size*/
length *= 2;
int *temp;
temp = (int*) realloc(arr, sizeof(*arr)*length);
if (!temp) {
free(temp);
}
else{
if (arr != temp) {
free(arr);
arr = temp;
}
else{
arr = temp;
}
}
printf("EXPAND ARRAY: %p\n", arr);
return length;
}
int shrinkArray(int *arr, int length, bool min)
{
/*function that cuts array in half*/
int *temp;
if (min){
length = 10;
}
else{
length /= 2;
}
temp = (int*) realloc(arr,sizeof(*arr)*length);
if (!temp) {
free(temp);
}
else{
arr = temp;
}
printf("SHRINK ARRAY: %p\n",arr);
return length;
}
void enqueue(int arr[], int* lastElementIdx, int *length, int element)
{
if (*lastElementIdx < *length - 1){ //checks if there's space for another element
arr[*lastElementIdx + 1] = element; //if yes, insert element after lastElementIdx
(*lastElementIdx)++; //increment lastElementIdx
}
else{
*length = expandArray(arr, *length); //if not, expand array
}
}
int dequeue (int arr[], int* lastElementIdx, int *length)
{
printf("address before:\t%p\tLast Element: %d\tLength: %d\n", arr,*lastElementIdx, *length);
int *p = arr;
if(*lastElementIdx > -1){ //Checks if there is an element in the queue
if (*lastElementIdx + 2 < *length/2 and *lastElementIdx + 2 > 10) {
bool min = false;
*length = shrinkArray(arr, *length, min);
}
else if (*lastElementIdx + 2 < 10){
bool min = true;
*length = shrinkArray(arr, *length, min);
}
(*lastElementIdx)--; //shift position of last element
printf("address afterw:\t%p\tLast Element: %d\tLength: %d\n", arr, *lastElementIdx,*length);
return *(p + *lastElementIdx + 1);
}
return 0;
}
void printQueue(const int arr[], int lastElementIdx)
{
while(lastElementIdx > -1){
printf("%d\t", *(arr + lastElementIdx));
lastElementIdx--;
}
}
Однако я получаю 2 ошибки. Первый из них:
if (arr != temp) {
free(arr);
arr = temp;
}
error for object 0x1001013b0: pointer being freed was not allocated
. Я реализовал эту строку в первую очередь, потому что через некоторое время я выяснил адрес указателя перераспределенной памяти. Если удалить, что if statement
я все еще получаю сообщение об ошибке, на этот раз, находясь в этой строке:
temp = (int*) realloc(arr, sizeof(*arr)*length);
сообщение существо: malloc: *** error for object 0x100500000: pointer being realloc'd was not allocated
Я должен также добавить, что в обоих случаях, иногда программа выполняется без проблем. В последнем случае ошибка чередуется между строкой realloc в expandArray
и номером в shrinkArray
. Я действительно не понимаю, почему это происходит, и как справиться с ситуацией, когда realloc
возвращает новый адрес указателя. Вдохновленный подобными сообщениями, я пробовал разные подходы, например, прохождение int **arr
вместо int *arr
как на expandArray
, так и на shrinkArray
. Я также попробовал разные методы, чтобы освободить исходный массив после realloc, например
temp = (int*) realloc(arr,sizeof(*arr)*length);
if (!temp) {
free(temp);
}
else{
free(arr);
arr = temp;
}
всегда с тем же сообщением об ошибке. И я надеялся освободить память после каждой тестовой функции и выделить новую память в main function
для массива очереди до вызова вторых тестовых функций, чтобы решить проблему, когда на самом деле этого не произошло.
Я очень ценю любую помощь по этому вопросу.
Комментарий: довольно редко использовать заголовок ''. Наблюдая за кодом, я заметил один экземпляр 'и' вместо' &&'. Интересно, действительно ли это преимущество. Это не технически неправильно; это необычно. –
Хорошо спасибо. На самом деле я больше играл с ним, так как читал об этом несколько дней назад. Это был первый и единственный раз, когда я его использовал. –
Примечание: 1) 'realloc()' может возвращать 'NULL' в случаях, отличных от out-of-memory, как в' realloc (arr, sizeof (* arr) * length); ', if' length == 0'. Поэтому, вместо 'if (! Temp) {free (temp);' use 'if (! Temp && length! = 0) {free (temp);' Еще лучше, заранее определите 'if (length <= 0)' и просто наберите 'free (arr)'. 2) Лучше использовать 'size_t length'. – chux