C 编程创建动态数组

标签 c arrays memory dynamic

到目前为止,您已经创建了固定大小的静态数组。 动态数组可以使用结构体和 malloc() 来更改其大小。 当数组已满时: 分配一个新的内存块。 将数据从一个指针复制到另一个指针。 释放旧指针。 将新指针分配给动态数组结构

您只需实现初始化动态数组和扩展动态数组的函数。 按照注释查看您需要编码的内容。 需要代码的注释里面写有 TODO: memcpy(void *dest, void *src, int 字节) 在指针之间复制内存的有用函数。 参数 1:要复制到的目标指针。 参数 2:您要从中复制的源指针。 参数3:要复制的字节数

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

//The dynamic array struct.  This maintains my pointer to memory, effective size and maximum size
typedef struct
{
    double *arrayPointer;
    int effectiveSize;
    int maximumSize;
} DynamicArray;

//Initialize the dynamic array
void CreateArray(DynamicArray *mArray, int initialSize)
{
    //TODO: Use malloc to create an array of the initial size.  Assign to the arrayPointer variable

    //TODO: Set effective size to 0 and maximum size to the initial size
}

//Expand the array to a new size
void ExpandArray(DynamicArray *mArray, int newSize)
{
    //TODO: Create a new pointer (double *newArray) and set it with a malloc call of the new size

    //TODO: Using either memcpy or a for loop, copy all of the data from the old array to the new one.
    //You are only copying to mArray->maximumSize, not the new size.

    //TODO: Using the free function, release the previous mArray->arrayPointer

    //TODO: Update mArray with the new pointer and the new maximum size.  Effective size does not change.
}

//Add a new value from the user to the array
void AddValue(DynamicArray *mArray)
{
    //Get the input
    double input;
    printf("Enter a new value: ");
    scanf_s("%lf", &input);

    //Assign the input to the array.  Increase effective size
    mArray->arrayPointer[mArray->effectiveSize] = input;
    mArray->effectiveSize++;

    //If effective size is now the same as maximum size we need to expand.
    if (mArray->effectiveSize == mArray->maximumSize)
    {
        //Output that we are expanding
        printf("Expanding array from %d to %d\n", mArray->maximumSize, mArray->maximumSize * 2);

        //Double the size of the array
        ExpandArray(mArray, mArray->maximumSize * 2);
    }
}

//Print the array
void PrintArray(const DynamicArray *mArray)
{
    int i;

    //Walk through the array up to effective size and print the values
    for (i = 0; i < mArray->effectiveSize; i++)
    {
        printf("%.2lf ", mArray->arrayPointer[i]);
    }
    printf("\n");
}

int main(void)
{
    int i;

    //Create my dynamic array of size 5
    DynamicArray mArray;
    CreateArray(&mArray, 5);

    //Add five values to it
    for (i = 0; i < 5; i++)
    {
        AddValue(&mArray);
    }

    //Print the array
    PrintArray(&mArray);

    //Add five more values
    for (i = 0; i < 5; i++)
    {
        AddValue(&mArray);
    }

    //Print the array
    PrintArray(&mArray);
    system("pause");
}

图片就是它应该的样子。

请帮助我,因为我被困住了,不知道该怎么办

最佳答案

如果要为任何内容动态分配存储空间,首先需要一个指向类型的指针。您使用 DynamicArray mArray; 声明了 1 个 DynamicArray 类型的静态变量。相反,您需要 DynamicArray *mArray; 并且您也可以将其初始化为 NULL:

int main (void) {

    /* Create my dynamic array of size 5 */
    DynamicArray *mArray = NULL;
    CreateArray (&mArray, 5);

    return 0;
}

由于您有一个指针,因此当您将地址发送到CreateArray时,funciton参数必须是一个双指针。然后,在 CreateArray 中,要分配 mArray,您必须取消引用作为参数传递的值并分配 *mArray = malloc...。您还可以使用 calloc 代替 malloc,这样只需微不足道的额外开销即可分配新内存块并将其初始化为零:

/* Initialize the dynamic array */
void CreateArray (DynamicArray **mArray, int initialSize)
{
    /*  TODO: Use malloc to create an array of the initial size.
        Assign to the arrayPointer variable */

    /* using calloc will allocate & initialize to zero */
    *mArray = calloc (initialSize, sizeof **mArray);

    if (!(*mArray)) {
        fprintf (stderr, "CreateArray() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }

}

除非您需要为函数使用 void 类型,否则为什么不返回指针呢?

DynamicArray *CreateArray (DynamicArray **mArray, int initialSize)
{
    /*  TODO: Use malloc to create an array of the initial size.
        Assign to the arrayPointer variable */

    /* using calloc will allocate & initialize to zero */
    *mArray = calloc (initialSize, sizeof **mArray);

    if (!(*mArray)) {
        fprintf (stderr, "CreateArray() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
        /* or you can now: 'return NULL;' instead of exiting. */
    }

    return *mArray;
}

最后,在您编写的动态分配内存的任何代码中,对于分配的任何内存块,您都有 2 个责任:(1) 始终保留指向内存块起始地址的指针,因此,(2)当不再需要时可以将其释放。您还必须使用内存错误检查程序来确保您没有在分配的内存块之外进行写入,并确认您已释放已分配的所有内存。对于 Linux,valgrind 是正常选择。有很多微妙的方法可以滥用内存块,从而导致真正的问题,没有理由不这样做。

其他示例

所以,您需要更多帮助将它们缝合在一起。下面是一个简短的示例,它分配一个由 5 个 struct DynamicArray 组成的动态数组,并初始化元素 04。然后,它打印 arrayPointer 指向的 double 组中第 4 个元素的值,然后释放分配的内存。我还包含了编译字符串和 valgrind 内存错误检查:

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

#define DASIZE 5

typedef struct {
    double *arrayPointer;
    int effectiveSize;
    int maximumSize;
} DynamicArray;

void CreateArray (DynamicArray **mArray, int initialSize);

int main (void) {

    double tmp[] = {0.0, 0.1, 0.2, 0.3};
    int i;

    /* Create my dynamic array of size 5 */
    DynamicArray *mArray = NULL;
    CreateArray (&mArray, DASIZE);

    /* assign pointer and values for element 0 */
    mArray[0].arrayPointer = tmp;
    mArray[0].effectiveSize = sizeof tmp/sizeof *tmp;
    mArray[0].maximumSize = mArray[0].effectiveSize;

    /* assign pointer and values for element 4 */
    mArray[4].arrayPointer = tmp;
    mArray[4].effectiveSize = sizeof tmp/sizeof *tmp;
    mArray[4].maximumSize = mArray[4].effectiveSize;

    /* print values for element 4 */
    printf ("\n information for mArray[4]:\n\n");
    printf ("   mArray[4].effectiveSize : %d\n", mArray[4].effectiveSize);
    printf ("   mArray[4].maximumSize   : %d\n\n", mArray[4].maximumSize);
    for (i = 0; i < mArray[4].effectiveSize; i++)
        printf ("   mArray[4].arrayPointer[%d] : %.1lf\n",
                i, mArray[4].arrayPointer[i]);

    free (mArray);  /* free all memory allocated */

    putchar ('\n'); /* add an additional newline to make it look nice */

    return 0;
}

/* Allocate memory for dynamic array of struct */
void CreateArray (DynamicArray **mArray, int initialSize)
{
    /* using calloc will allocate & initialize to zero */
    *mArray = calloc (initialSize, sizeof **mArray);

    if (!(*mArray)) {
        fprintf (stderr, "CreateArray() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }
}

编译

gcc -Wall -Wextra -O2 -o bin/array_dyn_min array_dyn_min.c

使用/输出

$ ./bin/array_dyn_min

 information for mArray[4]:

   mArray[4].effectiveSize : 4
   mArray[4].maximumSize   : 4

   mArray[4].arrayPointer[0] : 0.0
   mArray[4].arrayPointer[1] : 0.1
   mArray[4].arrayPointer[2] : 0.2
   mArray[4].arrayPointer[3] : 0.3

内存/错误检查

$ valgrind ./bin/array_dyn_min
==2232== Memcheck, a memory error detector
==2232== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==2232== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==2232== Command: ./bin/array_dyn_min
==2232==

 information for mArray[4]:

   mArray[4].effectiveSize : 4
   mArray[4].maximumSize   : 4

   mArray[4].arrayPointer[0] : 0.0
   mArray[4].arrayPointer[1] : 0.1
   mArray[4].arrayPointer[2] : 0.2
   mArray[4].arrayPointer[3] : 0.3

==2232==
==2232== HEAP SUMMARY:
==2232==     in use at exit: 0 bytes in 0 blocks
==2232==   total heap usage: 1 allocs, 1 frees, 80 bytes allocated
==2232==
==2232== All heap blocks were freed -- no leaks are possible
==2232==
==2232== For counts of detected and suppressed errors, rerun with: -v
==2232== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

内存错误检查的重要行是:

  total heap usage: 1 allocs, 1 frees, 80 bytes allocated
...
All heap blocks were freed -- no leaks are possible
...
ERROR SUMMARY: 0 errors from 0 contexts...

这告诉您有'1'动态内存分配和'1'空闲,并且所有分配的内存都已释放,并且没有内存错误程序运行期间内存的使用。您可以忽略 (suppressed: 2 from 2),它是 valgrind 告诉您它缺少 2 个库的符号表(调试版本)。 (在我的系统上,因为它们没有安装...)

关于C 编程创建动态数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33818919/

相关文章:

c - 尝试从排序列表创建新链表时出现段错误 11

安卓图像大小限制

memory - 如何检查已编译类型的表示?

python - Python2 字典中的非单调内存消耗

c - 发送到 : Operation not permitted: netsnmp

javascript - Angular 交互 2 种不同类型的数组 - 单个 ng-repeat 中的线性数组和 json 数组

C - 顶级进程和底层(叶)进程之间的命名管道

java - 有没有办法将字母形式的数字字符串数组转换为数字形式?

c - 为什么当我什么都不输入时程序会打印出 "@"?

c - 读取C中具有特定结构的文件