我是C的初学者,目前正努力在函数中使用结构体。即使我给我的函数指向我的struct并使用它来改变它们的值,看起来我的函数无法自己改变指针的值
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
typedef struct Vector
{
int n;
double *entry;
}Vector;
//defining the struct vector with n for its length and entry as a pointer which will become an array for its values
Vector *newVector(int n)
{
int i = 0;
Vector *X = NULL;
assert(n > 0);
X = malloc(sizeof(Vector));
assert(X != NULL);
X->n = n;
X->entry = malloc(n+1*sizeof(double));
assert(X->entry != NULL);
X->entry[0] = 0;
for (i=1; i<n+1; ++i) {
scanf("%lf",&X->entry[i]);
}
return X;
}
//making a new vector struct from the size given and returning its pointer (the array is made so it goes from 1-n instead of 0-(n-1)
void delVector(Vector *X)
{
assert(X != NULL);
assert(X->entry != NULL);
free(X->entry);
free(X);
X = NULL;
}
int getVectorLength (Vector *X)
{
assert(X != NULL);
return X->n;
}
void setVectorLength(Vector *X, int k)
{
assert(X != NULL);
assert(k>0);
delVector(X);
printf("so far.\n");
X = newVector(k);
} //deleting the vector and then replacing it with the new sized vector
double getVectorEntry (Vector *X, int h)
{
return X->entry[h];
}
void setVectorEntry (Vector *X, int h)
{
printf("Value %d.\n",h);
scanf("%lf",&X->entry[h]);
}
main()
{
Vector *h = NULL;
h = newVector(3);
printf("%f\n",h->entry[1]);
printf("%f\n",getVectorEntry(h,1));
setVectorEntry(h,1);
printf("%f\n",getVectorEntry(h,1));
printf("%d\n",getVectorLength(h));
setVectorLength(h,6);
printf("%f\n",getVectorEntry(h,6));
setVectorEntry(h,6);
printf("so far.\n");
printf("%f\n",getVectorEntry(h,6));
}
运行代码一旦到达delVector就会崩溃。如果我要评论delVector它会在X = newVector(k);
崩溃,原因我也找不到(它启动函数newVector,但在我输入之前崩溃)。那导致错误的原因是什么?
非常感谢提前!
答案 0 :(得分:6)
让我们只关注setVectorLength函数
void setVectorLength(Vector *X, int k)
{
assert(X != NULL);
assert(k>0);
delVector(X);
printf("so far.\n");
X = newVector(k);
}
这里,Vector * X是一个仅存在于此函数中的局部变量。它指向内存中的某个位置,但使用它您无法修改原始指针。所以有两种方法可以解决它。 1.您不删除并重新创建矢量。而是做这样的事情
void setVectorLength(Vector *X, int k)
{
X->entry = realloc(X->entry, k*sizeof(double)); // frees X->entry and allocates it to a new heap array
X->k = k;
}
2。使用指针指针。请注意,这将更慢并且是不必要的。转到1解决方案。
void setVectorLength(Vector **X, int k)
{
assert(*X != NULL);
assert(k>0);
delVector(*X);
printf("so far.\n");
*X = newVector(k);
}
变量Vector ** X指向原始变量,因此您可以对其进行修改。
答案 1 :(得分:3)
问题似乎在于功能
Vector *newVector(int n)
{
int i = 0;
Vector *X = NULL;
assert(n > 0);
X = malloc(sizeof(Vector));
assert(X != NULL);
X->n = n;
X->entry = malloc(n+1*sizeof(double));
assert(X->entry != NULL);
X->entry[0] = 0;
for (i=1; i<n+1; ++i) {
scanf("%lf",&X->entry[i]);
}
return X;
}
在上述声明中,您使用X->entry
分配n + sizeof(double)
,但根据您的要求,您应该分配(n + 1) * sizeof(double)
您应该将X->entry
的内存分配为
X->entry = malloc((n + 1) * sizeof(double));
答案 2 :(得分:0)
您的分配错误,您必须将n
和1
分组,就像您在纸上一样。并非您n + 1 * sizeof(double)
表达的含义与n + sizeof(double)
相同。
X->entry = malloc((n + 1) * sizeof(*X->entry));
将是正确的方式!
实际上,您的代码会调用未定义的行为,一旦可能导致程序崩溃。很可能是因为试图从其内存空间中访问内存,因此发生了分段错误。
答案 3 :(得分:0)
void setVectorLength(Vector *X, int k)
{
assert(X != NULL);
assert(k>0);
delVector(X);
printf("so far.\n");
X = newVector(k);
}
在此函数中,X
是调用者传入的指针变量的副本。它包含地址的副本。修改函数参数不会更改调用者的值。正如执行k = 0
对调用者没有任何影响一样,重新分配X
是调用者看不到的本地更改。
如果您希望来电者查看newVector(k)
的结果,您可以选择几种方式。您可以将setVectorLength()
更改为newVector()
,返回新指针。
Vector *setVectorLength(Vector *X, int k) {
...
printf("so far.\n");
return newVector(k);
}
int main() {
...
h = setVectorLength(h, 6);
}
或者您可以添加另一层间接 - 使X
指向指针的指针。这将要求调用者传递他们想要更改的变量的地址。不是通过h
,而是通过&h
。
void setVectorLength(Vector *X, int k) {
...
printf("so far.\n");
*X = newVector(k);
}
int main() {
...
setVectorLength(&h, 6);
}
顺便说一下,你写setVectorLength()
的方式,它会破坏向量中的任何现有数据。您可能希望将旧向量中的数据复制到新向量。 (或者,as @pi_pi3 suggests,修改矢量而不是销毁它并创建一个新的。)