在C语言中使用指针扩展数组



我正在学习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 arrayn");
return;
}
else
{
for(int i=0;i< *total_elements;i++){
printf("%dt",*(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("%dt",*(arr+i));
}
}
}
void pop()
{
}
void main()
{
int select=0;
int *arr, size=0, total_elements = 0;
while(select!=4)
{
printf("nSelect a numbern1. pushn2. popn3. displayn4. exitn");
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)后。push函数的打印输出

11      22      33

显示功能的打印输出。

11      22      -1943936495

我敢肯定,有一个错误的推函数,而使用指针。这是为什么呢?

由于arr = temp;的存在,push功能正常。注意,arr实际上是push函数内部的一个局部变量。当push函数返回时,main知道pusharr变量被更改过。

当你将arr传递给display时,将发送main的副本。如果您需要在另一个函数(本例中为push)中更新arr,则需要传递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是当前已填充/已使用元素的数量。
  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。这极大地简化了代码。我们只是把[单个]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 arrayn");
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 numbern1. pushn2. popn3. displayn4. exitn");
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 %dn",ele);
else
printf("main: pop emptyn");
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;
}

以下是[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

最新更新