使用C读取.mat文件:如何正确读取单元格结构 [英] Reading .mat file using C: how to read cell-structure properly
问题描述
我基本上是在尝试将Matlab代码转换为C代码.这是我之前的问题的扩展.
I am basically attempting to translate Matlab code in C code. This is the extension of my previous question.
在Matlab中,我使用了 cell-structures
,其中包含 matrices (double) of variable sizes
.这是我的* .mat文件是 supposed to store
的玩具示例:
In Matlab, I have used cell-structures
which holds matrices (double) of variable sizes
. Here is a toy example of what my *.mat file is 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
.
C-code: The function "matread_Matrix" reads matrices stored in *.mat properly
. It's the function "matread_Cell"
, which is supposed to read cell-structure, is not working
.
#include <stdio.h>
#include <stdlib.h>
#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';
Also, I could not read this field properly as well: Creator = 'DKumar';
更新:
基于@Sherwin的建议
Based on suggestion of @Sherwin
我的C代码:
#include <stdio.h>
#include <stdlib.h>
#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)存储在创建者中的字符串值显示不正确.
Problem: 1) String value stored in creator is not properly displayed.
2)如何删除cellArray [2])?
2) How to delete cellArray[2])?
推荐答案
结果稍有变化,您的代码有效:
It turns out with a slight change, your code works:
在函数"void matread_Cell
"中,将行double* p2 = (double*)cellArray[CellIndex];
替换为:
In the function "void matread_Cell
" replace the line double* p2 = (double*)cellArray[CellIndex];
with:
p2 = (double*) mxGetPr(cellArray[CellIndex]);
我检查了一下.它可以完成工作.
I checked it out. It does the work.
也要读取创建者字段,应该使用与mtread_matrix
类似的代码,只是类型为char*
而不是double*
(尽管我没有对此进行检查.请让我知道它是否不是工作).
Also to read the creator field, a similar code to mtread_matrix
should work, just the type is char*
instead of double*
(I didn't check this one though. let me know if it doesn't work).
更新:您可以使用以下代码读取字符串. (参考:此处)
update: you can use the following code to read strings. (Reference: here)
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. c.f. 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
中,您可以像这样使用它:
In the main
you can use it like:
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);
Regarding deallocating cellArray, I get the error: "pointer being freed was not allocated", so I don't think you need to free that. Another useful command for freeing dynamic memory is : void mxFree(void *ptr);
关于mexPrintf
函数,我实际上可以使用它.我只是得到一个警告implicit declaration of function 'mexPrintf' is invalid in C99 [-Wimplicit-function-declaration]
,因为我是通过gcc而不是mex进行编译的.如果使用的是gcc,则可能需要包括适当的库才能识别该功能.您可能会发现这很有用,因为它对我有用.
Regarding the mexPrintf
function I am actually able to use it. I just get a warning implicit declaration of function 'mexPrintf' is invalid in C99 [-Wimplicit-function-declaration]
, since I am compiling via gcc rather than mex. If you are using gcc, you probably need to include the proper libraries to recognize that function. You might find this useful, as it worked for me.
这篇关于使用C读取.mat文件:如何正确读取单元格结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!