使用指针在 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
将指向在 push
中 malloc
编辑的新数组,您可以将 arr
传递给 display
函数。
在您的代码中:
arr
是数组指针。
size
是当前 filled/used 个元素的数量。
total_elements
是 分配的 元素的数量。
您正在过度分配 arr
(使用 total_elements
),这很好。
但是,您混淆了 size
和 total_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
我正在学习 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
将指向在 push
中 malloc
编辑的新数组,您可以将 arr
传递给 display
函数。
在您的代码中:
arr
是数组指针。size
是当前 filled/used 个元素的数量。total_elements
是 分配的 元素的数量。
您正在过度分配 arr
(使用 total_elements
),这很好。
但是,您混淆了 size
和 total_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