2015-04-12 14 views
13

Tôi về cơ bản đang cố gắng dịch mã Matlab trong mã C. Đây là phần mở rộng của số question trước đó của tôi.Đọc tệp .mat sử dụng C: cách đọc cấu trúc ô đúng cách

Trong Matlab, tôi đã sử dụng cell-structures nắm giữ matrices (double) of variable sizes. Dưới đây là một ví dụ đồ chơi về những gì file * .mat của tôi là supposed to store:

Matlab Mã số:

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-code: Chức năng "matread_Matrix" reads matrices stored in *.mat properly. Đó là hàm "matread_Cell", được cho là đọc cấu trúc ô, là 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; 
} 

Output:

$ 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 

Ngoài ra, tôi không thể đọc lĩnh vực này đúng cách cũng như: Đấng Tạo Hóa = 'DKumar';

UPDATE:

Dựa trên đề nghị của @Sherwin

C-Mã của tôi:

#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; 
} 

Output:

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 : 

Vấn đề: 1) Chuỗi giá trị được lưu trữ trong người sáng tạo không được hiển thị đúng cách.

2) Cách xóa cellArray [2])?

+0

tại sao bạn lưu dữ liệu ở định dạng 'MAT' nếu bạn đọc nó bên ngoài Matlab? tại sao không xuất dữ liệu (trong Matlab) sang, nói, hdf5 và sử dụng các công cụ hiện có để đọc dữ liệu nhị phân hdf5? – Shai

+0

Tôi chưa bao giờ sử dụng định dạng hdf5 trước đây và tôi không biết liệu nó có thể lưu trữ và truy cập vào cấu trúc ô. –

+2

Matlab lưu các tệp MAT ở định dạng hdf5 (cho phiên bản 7.3 trở lên, AFAIK). Vì vậy, về nguyên tắc nó có thể làm bất cứ điều gì bạn cần. Bạn sẽ phải làm cho bàn tay của bạn bẩn và học cách giao tiếp với hdf5, nhưng xem xét thực tế rằng bạn đang trải qua quá trình (đau đớn) với định dạng MAT, tôi nghĩ bạn nên học một công cụ linh hoạt hơn (HDF5) thay vì tập trung vào MAT rất hạn chế ... Nhưng đây chỉ là ý kiến ​​của tôi. – Shai

Trả lời

5

Hóa ra với một thay đổi nhỏ, mã của bạn hoạt động:

Trong chức năng "void matread_Cell" thay thế dòng double* p2 = (double*)cellArray[CellIndex]; với:

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

Tôi đã kiểm tra nó ra. Nó làm việc.

Ngoài ra để đọc trường người sáng tạo, mã tương tự với mtread_matrix sẽ hoạt động, chỉ loại là char* thay vì double* (Tôi chưa đánh dấu trang này. Hãy cho tôi biết nếu nó không hoạt động).

cập nhật: bạn có thể sử dụng mã sau để đọc chuỗi.(Tham khảo: 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; 
} 

Trong main bạn có thể sử dụng nó như:

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]); 
    } 

Về deallocating cellArray, tôi nhận được lỗi: "con trỏ được trả tự do đã không được phân bổ", vì vậy tôi don' Tôi nghĩ rằng bạn cần phải giải phóng điều đó. Một lệnh hữu ích khác để giải phóng bộ nhớ động là: void mxFree(void *ptr);

Về chức năng mexPrintf Tôi thực sự có thể sử dụng nó. Tôi chỉ nhận được một cảnh báo implicit declaration of function 'mexPrintf' is invalid in C99 [-Wimplicit-function-declaration], vì tôi đang biên dịch qua gcc chứ không phải là mex. Nếu bạn đang sử dụng gcc, bạn có thể cần phải bao gồm các thư viện thích hợp để nhận ra hàm đó. Bạn có thể tìm thấy this hữu ích vì nó hoạt động đối với tôi.

+0

Tôi đã cập nhật mã của mình dựa trên đề xuất của bạn và tôi có thể đọc CellArray, vẫn không thể đọc chuỗi. Ngoài ra, tôi không biết làm thế nào để xóa cellArray [2]). Ngoài ra, tôi sẽ thích sử dụng mexPrintf hơn. Nhưng, tôi nhận được một lỗi: undefined tham chiếu đến 'mexPrintf '. Bất kỳ đoán về điều đó ?? –

+0

Tôi đã thêm cập nhật vào câu trả lời của mình. – Shervin

Các vấn đề liên quan