【发布时间】:2018-04-10 12:33:41
【问题描述】:
我是C新手。我有一个具有这种结构的函数(此代码不可重现,这是“伪代码”,但我希望它足以解释我的问题):
unsigned** myfunction(double*** A, unsigned nx, unsigned ny, unsigned nz){
unsigned* cells[nz-1];
unsigned totallength = 0;
unsigned lengths[nz-1];
unsigned** bottomTypes = function1(A, nx, ny, 0);
for(unsigned k=0; k<nz-1; k++){
unsigned** topTypes = function1(A, nx, ny, k+1);
unsigned** cellTypes = function2(bottomTypes, topTypes);
unsigned length
unsigned** goodcells = function3(cellTypes, &length);
cells[k] = malloc(length * sizeof(unsigned));
for(unsigned l=0; l<length; l++){
cells[k][l] = goodcells[0][l] + k;
}
lengths[k] = length;
totallength += length;
bottomTypes = function1(A, nx, ny, k+1); // the same as topTypes
}
unsigned** out = malloc(4 * sizeof(unsigned*));
......
......
return out;
}
如您所见,在循环结束时,我执行bottomTypes = function1(A, nx, ny, k+1);,这与之前介绍的topTypes 相同。因此function1(A,nx,ny,k+1) 被调用了两次。那是因为我无法在bottomTypes 中复制topTypes。当我这样做时,代码产生了预期的输出。
为了避免双重通话,我尝试过,而不是这样做
**bottomTypes = **topTypes;
或
bottomTypes = malloc((nx-1) * sizeof(unsigned*));
for ( int i = 0; i < nx-1; ++i ){
bottomTypes[i] = malloc((ny-1)*sizeof(unsigned));
memcpy(bottomTypes[i], topTypes[i], ny-1);
}
代码可以编译,但是当我这样做时没有得到预期的结果。
将topTypes 复制到bottomTypes 的正确方法是什么?
我希望这很清楚。否则不要犹豫,说我不清楚,我会尝试做一个可重复的例子,但这并不容易。我在 SO 上发现了类似的问题,但没有一个可以让我解决我的问题。
编辑
下面是一个完整的可重现示例。我承认,不是非常少。
#include <stdlib.h> // for malloc
#include <stdio.h> // for printf
// function to create a "three-dimensional array" (I know this is not the correct wording)
// from a given function
double*** fun2array(double f(unsigned,unsigned,unsigned), unsigned nx, unsigned ny, unsigned nz){
double*** out = (double***) malloc(nx * sizeof(double**));
for(unsigned i=0; i<nx; i++){
out[i] = (double**) malloc(ny * sizeof(double*));
for(unsigned j=0; j<ny; j++){
out[i][j] = (double*) malloc(nz * sizeof(double));
for(unsigned k=0; k<nz; k++){
out[i][j][k] = f(i,j,k);
}
}
}
return out;
}
// a three-dimensional array
double fun(unsigned i, unsigned j, unsigned k){
return i+j+k;
}
double*** A = fun2array(fun, 2, 3, 4);
// function to "slice" a 3d-array to a 2D-array (a "matrix")
double** toMatrix(double*** A, unsigned nx, unsigned ny, unsigned k){
double** out = (double**) malloc(nx * sizeof(double*));
for(unsigned i=0; i<nx; i++){
out[i] = (double*) malloc(ny * sizeof(double));
for(unsigned j=0; j<ny; j++){
out[i][j] = A[i][j][k];
}
}
return out;
}
// function to convert double matrix to integer matrix
unsigned** floorMatrix(double** M , unsigned nx, unsigned ny){
unsigned** out = (unsigned**) malloc(nx * sizeof(unsigned*));
for(unsigned i=0; i<nx; i++){
out[i] = (unsigned*) malloc(ny * sizeof(unsigned));
for(unsigned j=0; j<ny; j++){
out[i][j] = (unsigned) M[i][j];
}
}
return out;
}
// function to sum 2 "matrices"
unsigned** matricialSum(unsigned** M1, unsigned** M2, unsigned nx, unsigned ny){
unsigned** out = (unsigned**) malloc(nx * sizeof(unsigned*));
for(unsigned i=0; i<nx; i++){
out[i] = (unsigned*) malloc(ny * sizeof(unsigned));
for(unsigned j=0; j<ny; j++){
out[i][j] = M1[i][j] + M2[i][j];
}
}
return out;
}
unsigned myfunction(double*** A, unsigned nx, unsigned ny, unsigned nz){
unsigned** bottomTypes = floorMatrix(toMatrix(A, nx, ny, 0), nx, ny);
unsigned** cellTypes;
for(unsigned k=0; k<nz-1; k++){
unsigned** topTypes = floorMatrix(toMatrix(A, nx, ny, k+1), nx, ny);
cellTypes = matricialSum(bottomTypes, topTypes, nx, ny);
bottomTypes = floorMatrix(toMatrix(A, nx, ny, k+1), nx, ny); // the same as topTypes
}
return cellTypes[0][0];
}
int main(){
unsigned result = myfunction(A, 2, 3, 4);
printf("result:%u\n", result);
return 0;
}
第二次编辑
我有一个解决方案,但肯定不是最优的:
unsigned** copyMatrix(unsigned** M, unsigned nx, unsigned ny){
unsigned** MM = malloc(nx * sizeof(unsigned*));
for(unsigned i=0; i<nx; i++){
MM[i] = malloc(ny * sizeof(unsigned));
for(unsigned j=0; j<ny; j++){
MM[i][j] = M[i][j];
}
}
return MM;
}
然后在示例代码中我释放bottomTypes 然后我做
unsigned** bottomTypes = copyMatrix(topTypes, nx-1, ny-1);
【问题讨论】:
-
根据经验:只要您在 C 程序中有超过 2 层间接,您的设计就会出错。这被称为“三星级编程”,是对不必要复杂代码的讽刺。也许您打算改用proper multi-dimensional arrays?
-
对不起@Stargateur,什么是“NANI”?
A***是一个三维数组。 -
感谢您的评论@Lundin,但这对我来说听起来太复杂了,抱歉。我真的是 C 的新手。我什至不明白你所说的“2 级间接”是什么意思。
-
wiki.c2.com/?ThreeStarProgrammer,这很简单,因为您的变量有
*的数量,基本上,您有一个双精度指针的指针......这显然在 C 中不应该发生。我们无法为您提供很多帮助,因为您没有提供 minimal reproducible example 或您的代码上下文。我清楚地看到您的数据结构可以改进很多,但没有细节我们无法帮助您。 -
*pointer = 1 级间接,**pointer = 2 级。等等。
A***不是一个三维数组。使用三维数组比晦涩难懂的三星编程要容易得多。一个 malloc,一个免费。