使用C读取.mat文件:如何正确读取单元格结构

我基本上试图在C代码中翻译Matlab代码。 这是我上一个问题的延伸。

在Matlab中,我使用了包含matrices (double) of variable sizes cell-structures 。 这是我的* .mat文件supposed to store的玩具示例:

Matlab代码:

 A = [[1 2 3]; [5 7 1]; [3 5 9]]; B = [[2 4];[5 7]]; Creator = 'DKumar'; nFilters = 2; Filters{1} = [[-1.0 -1.0 -1.0]; [-1.0 8 -1.0]; [-1.0 -1.0 -1.0]]; Filters{2} = 2.0*[[-1.0 -1.0]; [-1.0 8]; [-1.0 -1.0]]; cd('/home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File'); save('Test_FILE.mat', 'A', 'B', 'Creator', 'nFilters', 'Filters'); 

C代码:函数"matread_Matrix" reads matrices stored in *.mat properly 。 这是函数"matread_Cell" ,它应该读取单元结构, not working

 #include  #include  #include "/usr/local/MATLAB/R2011b/extern/include/mat.h" mxArray *arr; mxArray *C_CELL; /* declare a 2 x 1 array of pointers to access the cell array in C */ mxArray *cellArray[2]; struct stDoubleMat{ double* pValueInField; int nRows, nCols; }; void matread_Matrix(const char *file, const char *FieldName2Read, struct stDoubleMat* poDoubleMat_LOC) { printf("Reading file %s...\n\n", file); //Open file to get directory MATFile* pmat = matOpen(file, "r"); if (pmat == NULL) { printf("Error opening file %s\n", file); return; } // extract the specified variable arr = matGetVariable(pmat, FieldName2Read); double *pr; if (arr != NULL && !mxIsEmpty(arr)) { // copy data mwSize num = mxGetNumberOfElements(arr); pr = mxGetPr(arr); if (pr != NULL) { poDoubleMat_LOC->pValueInField = pr; poDoubleMat_LOC->nRows = mxGetM(arr); poDoubleMat_LOC->nCols = mxGetN(arr); } printf("matread_Matrix \n") ; printf( "oDoubleMat_LOC.nRows %i ; oDoubleMat_LOC.nCols %i \n", poDoubleMat_LOC->nRows , poDoubleMat_LOC->nCols); }else{ printf("nothing to read \n") ; } // close the file matClose(pmat); return; } void matread_Cell(const char *file, const char *FieldName2Read, int CellIndex) { printf("Reading file %s...\n\n", file); //Open file to get directory MATFile* pmat = matOpen(file, "r"); if (pmat == NULL) { printf("Error opening file %s\n", file); return; } // extract the specified variable C_CELL = matGetVariable(pmat, FieldName2Read); cellArray[CellIndex] = mxGetCell(C_CELL, CellIndex); double* p2 = (double*)cellArray[CellIndex]; int nRows = mxGetM(cellArray[CellIndex]); int nCols = mxGetN(cellArray[CellIndex]); printf(" From inside matread_Cell : nRows %i and nCols %i \n", nRows, nCols); int i2; for (i2 = 0; i2 < nRows*nCols; i2++) { printf(" copied value : %f \n", *p2); p2 = p2 +1; } // close the file matClose(pmat); } int main(int argc, char **argv) { const char *FileName = "/home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat"; const char *FieldName2Read = "A"; struct stDoubleMat oDoubleMat; matread_Matrix(FileName, FieldName2Read, &oDoubleMat); double* v = oDoubleMat.pValueInField; printf("From main \n"); printf( "oDoubleMat.nRows %i ; oDoubleMat.nCols %i \n", oDoubleMat.nRows , oDoubleMat.nCols); int i; for (i = 0; i < oDoubleMat.nCols*oDoubleMat.nRows; i++) { printf(" copied value : %f \n", *v); v = v +1; } // Reading the structure const char *FieldName2Read2 = "Filters"; matread_Cell(FileName, FieldName2Read2, 0); matread_Cell(FileName, FieldName2Read2, 1); // cleanup the mex-array mxDestroyArray(arr); mxDestroyArray(C_CELL); /* How to delete mxArray of pointer : should this be a array of pointers */ //mxDestroyArray(cellArray[0]); //mxDestroyArray(cellArray[1]); return 0; } 

输出:

 $ gcc -g -o Test Read_MatFile_DKU_2.c -I/usr/local/MATLAB/R2011b/extern/include -L/usr/local/MATLAB/R2011b/bin/glnxa64 -lmat -lmx $ ./Test Reading file /home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat... matread_Matrix oDoubleMat_LOC.nRows 3 ; oDoubleMat_LOC.nCols 3 From main oDoubleMat.nRows 3 ; oDoubleMat.nCols 3 copied value : 1.000000 copied value : 5.000000 copied value : 3.000000 copied value : 2.000000 copied value : 7.000000 copied value : 5.000000 copied value : 3.000000 copied value : 1.000000 copied value : 9.000000 Reading file /home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat... From inside matread_Cell : nRows 3 and nCols 3 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 Reading file /home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat... From inside matread_Cell : nRows 3 and nCols 2 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 

另外,我也无法正确阅读这个字段:Creator =’DKumar’;

更新:

根据@Sherwin的建议

我的C代码:

 #include  #include  #include "/usr/local/MATLAB/R2011b/extern/include/mat.h" mxArray *arr; mxArray *C_CELL; /* declare a 2 x 1 array of pointers to access the cell array in C */ mxArray *cellArray[2]; struct stDoubleMat{ double* pValueInField; int nRows, nCols; }; void matread_Matrix(MATFile* pmat , const char *FieldName2Read, struct stDoubleMat* poDoubleMat_LOC) { // extract the specified variable arr = matGetVariable(pmat, FieldName2Read); double *pr; if (arr != NULL && !mxIsEmpty(arr)) { // copy data mwSize num = mxGetNumberOfElements(arr); pr = mxGetPr(arr); if (pr != NULL) { poDoubleMat_LOC->pValueInField = pr; poDoubleMat_LOC->nRows = mxGetM(arr); poDoubleMat_LOC->nCols = mxGetN(arr); } printf("matread_Matrix \n") ; printf( "oDoubleMat_LOC.nRows %i ; oDoubleMat_LOC.nCols %i \n", poDoubleMat_LOC->nRows , poDoubleMat_LOC->nCols); }else{ printf("nothing to read \n") ; } return; } void matread_String(MATFile* pmat , const char *FieldName2Read) { // extract the specified variable arr = matGetVariable(pmat, FieldName2Read); double *pr; if (arr != NULL && !mxIsEmpty(arr)) { // copy data mwSize num = mxGetNumberOfElements(arr); pr = mxGetPr(arr); if (pr != NULL) { char *p2 = (char*) pr; // Printing and checking int i2; for (i2 = 0; i2 < num; i2++) { printf(" copied value : %s \n", p2); p2 = p2 +1; } } }else{ printf("nothing to read \n") ; } return; } void matread_Cell(MATFile* pmat , const char *FieldName2Read, int CellIndex) { // extract the specified variable C_CELL = matGetVariable(pmat, FieldName2Read); cellArray[CellIndex] = mxGetCell(C_CELL, CellIndex); double *p2 = (double*) mxGetPr(cellArray[CellIndex]); int nRows = mxGetM(cellArray[CellIndex]); int nCols = mxGetN(cellArray[CellIndex]); printf(" From inside matread_Cell : nRows %i and nCols %i \n", nRows, nCols); int i2; for (i2 = 0; i2 < nRows*nCols; i2++) { printf(" copied value : %f \n", *p2); p2 = p2 +1; } } int main(int argc, char **argv) { const char *FileName = "/home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat"; const char *FieldName2Read = "A"; //Open file to get directory printf("Reading file %s...\n\n", FileName); MATFile* pmat = matOpen(FileName, "r"); if (pmat == NULL) { printf("Error opening file %s\n", FileName); return; } struct stDoubleMat oDoubleMat; matread_Matrix(pmat, FieldName2Read, &oDoubleMat); double* v = oDoubleMat.pValueInField; int i; for (i = 0; i < oDoubleMat.nCols*oDoubleMat.nRows; i++) { printf(" copied value : %f \n", *v); v = v +1; } // Reading the structure const char *FieldName2Read2 = "Filters"; matread_Cell(pmat, FieldName2Read2, 0); matread_Cell(pmat, FieldName2Read2, 1); // Reading the string const char *FieldName2Read3 = "Creator"; matread_String(pmat, FieldName2Read3); // cleanup the mex-array mxDestroyArray(arr); mxDestroyArray(C_CELL); /* How to delete mxArray of pointer : should this be a array of pointers */ //mxDestroyArray(cellArray[0]); //mxDestroyArray(cellArray[1]); // close the file matClose(pmat); return 0; } 

输出:

 oDoubleMat.nRows 3 ; oDoubleMat.nCols 3 copied value : 1.000000 copied value : 5.000000 copied value : 3.000000 copied value : 2.000000 copied value : 7.000000 copied value : 5.000000 copied value : 3.000000 copied value : 1.000000 copied value : 9.000000 From inside matread_Cell : nRows 3 and nCols 3 copied value : -1.000000 copied value : -1.000000 copied value : -1.000000 copied value : -1.000000 copied value : 8.000000 copied value : -1.000000 copied value : -1.000000 copied value : -1.000000 copied value : -1.000000 From inside matread_Cell : nRows 3 and nCols 2 copied value : -2.000000 copied value : -2.000000 copied value : -2.000000 copied value : -2.000000 copied value : 16.000000 copied value : -2.000000 copied value : D copied value : copied value : K copied value : copied value : u copied value : copied value : 

问题:1)存储在创建者中的字符串值未正确显示。

2)如何删除cellArray [2])?

结果稍有变化,您的代码可以正常工作:

在函数“ void matread_Cell ”中替换行double* p2 = (double*)cellArray[CellIndex]; 有:

 p2 = (double*) mxGetPr(cellArray[CellIndex]); 

我检查了一下。 它做的工作。

另外要阅读创建者字段,类似于mtread_matrix代码应该可以工作,只是类型是char*而不是double* (虽然我没有检查这个。请告诉我它是否不起作用)。

更新:您可以使用以下代码来读取字符串。 (参考: 这里 )

 void matread_string(const char *file, const char *FieldName2Read, char *pr, mwSize *len) { printf("Reading file %s...\n\n", file); //Open file to get directory MATFile* pmat = matOpen(file, "r"); if (pmat == NULL) { printf("Error opening file %s\n", file); return; } // extract the specified variable arr = matGetVariable(pmat, FieldName2Read); if (arr != NULL && !mxIsEmpty(arr)) { // copy data mwSize num = mxGetNumberOfElements(arr); //int mxGetString(const mxArray *pm, char *str, mwSize strlen); int res= mxGetString(arr, pr, num+1); //strlen should be len+1. cf reference. if(res==0) printf("success!\n"); else printf("failed.\n"); if ( pr == NULL){ printf("null pointer.\n"); } printf("matread_string \n") ; printf( "len: %i \n", (int)num); *len=num; }else{ printf("nothing to read \n") ; } // close the file matClose(pmat); return; } 

main你可以使用它像:

  const char *FieldName2Read3 = "Creator"; char pr[20]; mwSize len; matread_string(FileName, FieldName2Read3, pr, &len); //int i; printf(" copied value: %s \n",pr); for (i = 0; (mwSize) i < len; i++) { printf(" copied value : %c \n", pr[i]); } 

关于解除分配cellArray,我得到错误:“指针被释放没有被分配”,所以我认为你不需要释放它。 释放动态内存的另一个有用命令是: void mxFree(void *ptr);

关于mexPrintf函数,我实际上可以使用它。 我只是得到一个警告implicit declaration of function 'mexPrintf' is invalid in C99 [-Wimplicit-function-declaration] ,因为我是通过gcc而不是mex编译的。 如果您使用的是gcc,则可能需要包含适当的库来识别该function。 您可能会觉得这很有用,因为它对我有用。