如何解决C更改结构指针
我对C不太熟悉,并尝试使用功能将行添加到现有的矩阵结构中。此功能将在迭代循环中使用。
在我的代码中,我使用矩阵PreparedData_B4
作为参考矩阵。在第一步中,我从PreparedData_B4
中切出3行并创建矩阵ActData
。然后,我使用参数add_row
,mat In
和mat **Out
调用函数mat Out1
。也许还有另一个想法可以避免通过ActData (mat **Out)
和ActData (mat Out1)
本身的地址。这是我获得Tmp
正确尺寸的唯一机会。
编辑:在此函数中,我使用新尺寸创建了一个临时矩阵Temp
。在*Out = &Tmp
之后,我认为新地址已经设置并且可以正常工作。 (**Out)->n = 3
,(**Out)->m = 4
和(**Out)->v[][]
可以访问。
到目前为止,一切都很好。
该功能完成后,出现了问题。 ActData->n = 0
和ActData->v[][]
无法访问。
另一个问题是,如何释放“旧” ActData
的记忆?
#include <stdio.h>
#include <stdlib.h>
#define NELEMS(x) (int)(sizeof(x) / sizeof((x)[0]))
// Raw data
double raw_T7[][3] = {
{1800,261.753,1032.354},{1750,247.46,1028.439},{1700,250.385,1003.689},{1243,69.92,816.569},{670,67.485,614.319},{533,73.591,533.15},{509,73.404,517.456},{485,89.233,515.994},{460,110.535,501.412},{435,141.864,471.876},{411,195.009,480.623},{386,260.166,529.444},{361,375.958,462.411}
};
// Matrix structure
typedef struct {
int m,n;
double ** v;
} mat_t,*mat;
// Create new matrix
mat mat_new(int m,int n){
int i = 0;
mat out = malloc(sizeof(mat_t));
out->v = malloc(sizeof(double*) * m);
out->v[0] = calloc(sizeof(double),m * n);
for (i = 0; i < m; i++) out->v[i] = out->v[0] + n * i;
out->m = m;
out->n = n;
return out;
}
// Show matrix
void mat_show(mat A){
int i = 0,j = 0;
for(i = 0; i < A->m; i++) {
for (j = 0; j < A->n; j++) {
printf(" %8.3f",A->v[i][j]);
}
printf("\n");
}
printf("\n");
}
void add_row(mat In,mat **Out,mat Out1){
int i = 0,j = 0;
// Create new matrix
mat Tmp = mat_new(Out1->m + 1,Out1->n);
for (i = 0 ; i < Tmp->n ; i++) {
for(j = 0 ; j < Tmp->m ; j++){
Tmp->v[j][i] = In->v[j][i];
}
}
mat_show(Tmp);
// Delete old address
//free(Out1->v[0]);
//free(Out1->v);
//free(Out1);
*Out = &Tmp;
}
int main()
{
int i = 0,j = 0;
// Assign array address to first matrix structure
mat PreparedData_B4 = mat_new(NELEMS(raw_T7),NELEMS(raw_T7[0]));
double *ptr1[PreparedData_B4->m];
free(PreparedData_B4->v[0]);
free(PreparedData_B4->v);
PreparedData_B4->v = (double **)ptr1;
for (i = 0 ; i < PreparedData_B4->m ; i++) ptr1[i] = (double *)raw_T7 + i * NELEMS(raw_T7[0]);
// Create new matrix with the first 3 rows of PreparedData_B4
mat ActData = mat_new(3,PreparedData_B4->n);
for (i = 0 ; i < ActData->n ; i++) {
for(j = 0 ; j < ActData->m ; j++){
ActData->v[j][i] = PreparedData_B4->v[j][i];
}
}
puts("PreparedData_B4");
mat_show(PreparedData_B4);
puts("ActData");
mat_show(ActData);
puts("ActData with additional row");
add_row(PreparedData_B4,&ActData,ActData);
mat_show(ActData);
free(PreparedData_B4);
return 0;
}
解决方案: 由于戴维·C·兰金(David C. Rankin)的扎实基础,其他所有回应都是我的工作实例。非常感谢!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NELEMS(x) (int)(sizeof(x) / sizeof((x)[0]))
// Raw data
double raw_T7[][3] = {
{1800,n;
double *v;
} mat_t;
// Create new matrix
mat_t *mat_new (int m,int n)
{
mat_t *out = malloc (sizeof *out); /* allocate struct */
if (!out) {
perror ("malloc-out");
exit (EXIT_FAILURE);
}
out->v = malloc(sizeof *out->v * m * n); /* allocate for m * n doubles */
if (!out->v) {
perror ("malloc-out->v");
exit (EXIT_FAILURE);
}
out->m = m;
out->n = n;
return out;
}
// Show matrix
void mat_show(mat_t *A)
{
int i = 0,j = 0;
for(i = 0; i < A->m; i++) {
for (j = 0; j < A->n; j++)
printf(" %8.3f",(A->v)[i * A->n + j]);
putchar ('\n');
}
putchar ('\n');
}
void add_row(mat_t *In,mat_t **Out){
int i = 0,j = 0;
// Create new matrix
mat_t *Tmp = mat_new((*Out)->m + 1,(*Out)->n);
for (i = 0 ; i < Tmp->m ; i++) {
for(j = 0 ; j < Tmp->n ; j++){
(Tmp->v)[i * Tmp->n + j] = (In->v)[i * In->n + j];
}
}
// Delete old address
free((*Out)->v);
free(*Out);
// Assign new address
*Out = Tmp;
}
int main(void)
{
int rows = NELEMS(raw_T7),cols = NELEMS(raw_T7[0]);
int i = 0,j = 0;
// Assign array address to first matrix structure
mat_t *PreparedData_B4 = mat_new(rows,cols); /* allocate,set m & n */
/* copy raw_T7 to PreparedData_B4->v */
memcpy (PreparedData_B4->v,raw_T7,rows * cols * sizeof PreparedData_B4->v);
// Create new matrix with the first 3 rows of PreparedData_B4
mat_t *ActData = mat_new(3,PreparedData_B4->n);
for (i = 0 ; i < ActData->m ; i++) {
for(j = 0 ; j < ActData->n ; j++){
(ActData->v)[i * ActData->n + j] = (PreparedData_B4->v)[i * PreparedData_B4->n + j];
}
}
puts("PreparedData_B4");
mat_show(PreparedData_B4);
puts("ActData");
mat_show(ActData);
puts("ActData with additional row");
add_row(PreparedData_B4,&ActData);
mat_show(ActData);
free (PreparedData_B4->v);
free (PreparedData_B4);
return 0;
}
解决方法
在建造完美的房屋之前,必须建立牢固的基础-否则房屋将无法使用。
您会混淆使用指针和分配的内存块来存储数据。这在您的mat_new()
函数中非常明显。考虑一下...您为m
指针分配了
out->v = malloc(sizeof(double*) * m);
但是只能使用单指针:
out->v[0] = calloc(sizeof(double),m * n);
(您将其他m - 1
指针用于什么?)
您似乎想分配一个内存块来存储矩阵值,然后在索引中模拟一个2D数组(这是很好的方法,而且是一种非常有效的方法)。但是,您要做的是不为v
使用双指针,您只需使用单指针(例如double *v;
),这为您提供了单分配和单释放的优势存储的数据。 (您仍然必须释放结构本身)
让我们使用您的mat_new (int m,int n)
函数并使它正常工作,然后用您的mat_show(mat_t *A)
输出数据,最后释放我们分配给该点的内存,例如
// Create new matrix
mat_t *mat_new (int m,int n)
{
mat_t *out = malloc (sizeof *out); /* allocate struct */
if (!out) {
perror ("malloc-out");
exit (EXIT_FAILURE);
}
out->v = malloc(sizeof *out->v * m * n); /* allocate for m * n doubles */
if (!out->v) {
perror ("malloc-out->v");
exit (EXIT_FAILURE);
}
out->m = m;
out->n = n;
return out;
}
(注意:我已删除了 typedeffed 指针mat
)
对于您的mat_show()
函数,您将具有:
// Show matrix
void mat_show(mat_t *A)
{
int i = 0,j = 0;
for(i = 0; i < A->m; i++) {
for (j = 0; j < A->n; j++)
printf(" %8.3f",(A->v)[i * A->n + j]);
putchar ('\n');
}
putchar ('\n');
}
(注意:请勿使用printf
输出单个字符,这就是putchar()
的目的-尽管一个好的编译器会针对您)
如果将这些功能和简短的示例放在一起,您将拥有:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NELEMS(x) (int)(sizeof(x) / sizeof((x)[0]))
// Raw data
double raw_T7[][3] = { {1800,261.753,1032.354},{1750,247.46,1028.439},{1700,250.385,1003.689},{1243,69.92,816.569},{670,67.485,614.319},{533,73.591,533.15},{509,73.404,517.456},{485,89.233,515.994},{460,110.535,501.412},{435,141.864,471.876},{411,195.009,480.623},{386,260.166,529.444},{361,375.958,462.411} };
// Matrix structure
typedef struct {
int m,n;
double *v;
} mat_t;
// Create new matrix
mat_t *mat_new (int m,int n)
{
mat_t *out = malloc (sizeof *out); /* allocate struct */
if (!out) {
perror ("malloc-out");
exit (EXIT_FAILURE);
}
out->v = malloc(sizeof *out->v * m * n); /* allocate for m * n doubles */
if (!out->v) {
perror ("malloc-out->v");
exit (EXIT_FAILURE);
}
out->m = m;
out->n = n;
return out;
}
// Show matrix
void mat_show(mat_t *A)
{
int i = 0,(A->v)[i * A->n + j]);
putchar ('\n');
}
putchar ('\n');
}
int main (void)
{
int rows = NELEMS(raw_T7),cols = NELEMS(raw_T7[0]);
mat_t *PreparedData_B4 = mat_new(rows,cols); /* allocate,set m & n */
/* copy raw_T7 to PreparedData_B4->v */
memcpy (PreparedData_B4->v,raw_T7,rows * cols * sizeof PreparedData_B4->v);
mat_show (PreparedData_B4); /* output matrix */
free (PreparedData_B4->v);
free (PreparedData_B4);
}
(注意:包含string.h
,以便使memcpy()
函数可用于在单个调用中从out->v
初始化raw_T7
})>
使用/输出示例
$ ./bin/mat_prepare
1800.000 261.753 1032.354
1750.000 247.460 1028.439
1700.000 250.385 1003.689
1243.000 69.920 816.569
670.000 67.485 614.319
533.000 73.591 533.150
509.000 73.404 517.456
485.000 89.233 515.994
460.000 110.535 501.412
435.000 141.864 471.876
411.000 195.009 480.623
386.000 260.166 529.444
361.000 375.958 462.411
内存使用/错误检查
$ valgrind ./bin/mat_prepare
==10301== Memcheck,a memory error detector
==10301== Copyright (C) 2002-2017,and GNU GPL'd,by Julian Seward et al.
==10301== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10301== Command: ./bin/mat_prepare
==10301==
1800.000 261.753 1032.354
1750.000 247.460 1028.439
1700.000 250.385 1003.689
1243.000 69.920 816.569
670.000 67.485 614.319
533.000 73.591 533.150
509.000 73.404 517.456
485.000 89.233 515.994
460.000 110.535 501.412
435.000 141.864 471.876
411.000 195.009 480.623
386.000 260.166 529.444
361.000 375.958 462.411
==10301==
==10301== HEAP SUMMARY:
==10301== in use at exit: 0 bytes in 0 blocks
==10301== total heap usage: 3 allocs,3 frees,1,352 bytes allocated
==10301==
==10301== All heap blocks were freed -- no leaks are possible
==10301==
==10301== For counts of detected and suppressed errors,rerun with: -v
==10301== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
这就是您想要完成的事情。如果我误解了您的意图或还有其他疑问,请告诉我。首先正确使用内存,以提供坚实的基础并以此为基础。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。