使用指针在 C 中扩展数组

Extending arrays in C using pointers

我正在学习 C 中的指针。要了解详细信息,我正在研究数组程序。我想要实现的是,如果数组的大小为 0(最初),则使用大小为 2 的 malloc 创建一个动态数组,然后将元素添加到初始位置。

此外,当添加更多元素时,如果元素总数 == 数组大小,我会使用 malloc 创建一个新数组,其大小是之前的两倍。我创建了一个临时数组,从以前的数组中复制元素,然后在最后添加新元素。问题是当我尝试打印元素时,我得到的是最后一个元素的地址,而不是元素的地址。

这是完整的代码。

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

void display(int *arr, int *total_elements)
{
    if(*total_elements==0){
        printf("No elements present in array\n");
        return;
    }
    else
    {
        for(int i=0;i< *total_elements;i++){
            printf("%d\t",*(arr+i));
        }
    }
}

void push(int *arr, int *size, int ele, int *total_elements)
{
    if(*size==0)
    {
        *arr = (int*)malloc(2*sizeof(int));
        arr[*size] = ele;
        *total_elements = *total_elements + 1;
        *size = *size + 2;
        return;
    }
    else if(*size>*total_elements)
    {
        arr[*total_elements] = ele;
        *total_elements = *total_elements + 1;
        return;
    }
    else if(*size==*total_elements)
    {
        int *temp,i;
        temp = (int*)malloc((*(size)*2)*sizeof(int));
        for(i=0;i < *size;i++)
        {
            temp[i] = *(arr+i);
        }
        temp[i]=ele;
        arr = temp;
        *size = (*size)*2;
        *total_elements = *total_elements + 1;
        for(int i=0;i< *total_elements;i++){
            printf("%d\t",*(arr+i));
        }
    }
}

void pop()
{
}

void main()
{
    int select=0;
    int *arr, size=0, total_elements = 0;
    while(select!=4)
    {
        printf("\nSelect a number\n1. push\n2. pop\n3. display\n4. exit\n");
        scanf("%d",&select);
        switch (select)
        {
            case 1: 
                printf("Enter element to push: ");
                int ele;
                scanf("%d",&ele);
                push(arr,&size,ele,&total_elements);
                break;
            
            case 3: 
                display(arr, &total_elements);
                break;

            case 4: break;
            
            default:
                break;
        }

    }
}

输入3个元素(11,22,33)后。 推送功能的打印输出。

11      22      33

显示函数的打印输出。

11      22      -1943936495

我确定在使用指针时推送函数有错误。为什么会这样?

由于 arr = temp;push 函数可以正常工作。观察 arr 实际上是 push 函数内部的局部变量。当 push 函数 returns 时,main 而不是 知道 arr 变量在 [=10] 中被更改过=].

当您将 arr 传递给 display 时,将发送 main 具有的副本。如果您需要在另一个函数中更新 arr(在本例中为 push),您需要传递 arr - push(&arr,&size,ele,&total_elements); 的地址,同样, push函数现在应该接受 int **arr 而不是 int *arr。另外,确保在 push.

中取消引用 arr 的正确次数

push 中,您可以通过 *arr = temp; 更新 arr。此后,arr 将指向在 pushmalloc 编辑的新数组,您可以将 arr 传递给 display 函数。

在您的代码中:

  1. arr是数组指针。
  2. size 是当前 filled/used 个元素的数量。
  3. total_elements 分配的 元素的数量。

您正在过度分配 arr(使用 total_elements),这很好。

但是,您混淆了 sizetotal_elements 的使用。在 display 中,您应该使用 size.

请注意,在 main 中,您 不是 初始化 arr [到 NULL]。对于您的代码,这没问题,因为 push 的实现方式。但是,通常最好将其设置为 NULL-- 见下文。

push中,您不是来电者更新arr

此外,push 比它需要的更复杂(即)太多的特殊情况。

如果 main 初始化 arr,那么 push 可以只使用 realloc(因为 realloc 处理空指针就像 malloc [内部]).

我们可以为包含单独标量值的数组创建一个控件 struct,而不是将 3 个东西传递给 push。这大大简化了代码。我们只是将 [single] struct 指针传递给所有函数。


这是一些重构代码。出于测试目的,我添加了一个 case 5:

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

typedef struct {
    int *arr;                           // pointer to array data
    int size;                           // number of filled/inuse elements
    int total_elements;                 // number of allocated elements
} dynarr_t;

void
display(dynarr_t *dyn)
{

    if (dyn->size == 0) {
        printf("No elements present in array\n");
        return;
    }

    int totlen = 0;

    for (int i = 0;  i < dyn->size;  i++) {
        if (totlen >= 68) {
            printf("\n");
            totlen = 0;
        }
        int curlen = printf(" %d",dyn->arr[i]);
        totlen += curlen;
    }

    if (totlen > 0)
        printf("\n");
}

void
push(dynarr_t *dyn,int ele)
{

    // grow the array
    if (dyn->size >= dyn->total_elements) {
        // the amount here is arbitrary
        dyn->total_elements += 10;

        dyn->arr = realloc(dyn->arr,sizeof(*dyn->arr) * dyn->total_elements);

        // out of memory
        if (dyn->arr == NULL) {
            perror("push");
            exit(1);
        }
    }

    // append new element
    dyn->arr[dyn->size++] = ele;
}

// RETURNS: 1=valid, 0=empty
int
pop(dynarr_t *dyn,int *ele)
{

    // no elements in array
    if (dyn->size <= 0)
        return 0;

    // pop the last element
    *ele = dyn->arr[--dyn->size];

    return 1;
}

int
main(void)
{
    int select = 0;
    int ele;

    // allocate a pointer to the array control struct
    dynarr_t *dyn = calloc(1,sizeof(*dyn));

    while (select != 4) {
        printf("\nSelect a number\n1. push\n2. pop\n3. display\n4. exit\n");
        scanf("%d", &select);
        switch (select) {
        case 1:
            printf("Enter element to push: ");

            scanf("%d", &ele);
            push(dyn, ele);
            break;

        case 2:
            if (pop(dyn,&ele))
                printf("main: pop %d\n",ele);
            else
                printf("main: pop empty\n");
            break;

        case 3:
            display(dyn);
            break;

        case 4:
            break;

        case 5:  // internal test
            for (int ele = 1;  ele <= 100;  ++ele)
                push(dyn,ele);
            display(dyn);
            break;

        default:
            break;
        }
    }

    // free up the memory
    free(dyn->arr);
    free(dyn);

    return 0;
}

这里是测试输出 [for 5 4]:


Select a number
1. push
2. pop
3. display
4. exit
 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 66 67 68 69 70 71 72
 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
 96 97 98 99 100

Select a number
1. push
2. pop
3. display
4. exit