2015-04-12 14 views
13

In pratica sto tentando di tradurre il codice Matlab nel codice C. Questa è l'estensione del mio precedente question.Lettura del file .mat utilizzando C: come leggere correttamente la struttura della cella

In Matlab, ho usato cell-structures che detiene matrices (double) of variable sizes. Ecco un esempio di giocattoli di ciò che il mio file .mat * è supposed to store:

Matlab Codice:

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: La funzione "matread_Matrix" reads matrices stored in *.mat properly. È la funzione "matread_Cell", che dovrebbe leggere la struttura della cella, è 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; 
} 

uscita:

$ 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 

Inoltre, non ho potuto leggere questo campo correttamente pure: Creatore = 'DKumar';

UPDATE:

Basato su suggerimento di @Sherwin

mio codice 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; 
} 

uscita:

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 : 

Problema: 1) Valore stringa memorizzata in creatore non è visualizzato correttamente.

2) Come eliminare cellArray [2])?

+0

Perché sei il salvataggio dei dati in formato 'MAT' se lo si legge al di fuori di Matlab? perché non esportare i dati (in Matlab), per esempio, in hdf5 e utilizzare gli strumenti esistenti per leggere i dati binari di hdf5? – Shai

+0

Non ho mai usato il formato hdf5 prima e non so se può archiviare e accedere alle strutture di celle. –

+2

Matlab salva i suoi file MAT in formato hdf5 (per versione 7.3 e on, AFAIK). Quindi, in linea di principio, può fare tutto ciò di cui hai bisogno. Dovrai sporcarti le mani e imparare come interfacciare a hdf5, ma considerando il fatto che stai attraversando lo stesso (doloroso) processo con il formato MAT, penso che starai meglio imparando uno strumento più versatile (HDF5) invece di concentrarsi sul MAT molto ristretto ... Ma questa è solo la mia opinione. – Shai

risposta

5

si scopre con un leggero cambiamento, il tuo codice funziona:

Nella funzione "void matread_Cell" sostituire la linea double* p2 = (double*)cellArray[CellIndex]; con:

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

ho controllato fuori. Funziona.

anche leggere il campo creatore, un codice simile a mtread_matrix dovrebbe funzionare, proprio il tipo è char* invece di double* (Non ho controllato questo però. Fatemi sapere se non funziona).

aggiornamento: è possibile utilizzare il seguente codice per leggere le stringhe.(Riferimento: 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; 
} 

Nel main è possibile utilizzarlo come:

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

Per quanto riguarda deallocando cellArray, ottengo l'errore: "puntatore di essere liberata non è stato assegnato", così ho don' Penso che sia necessario liberarlo. Un altro comando utile per liberare la memoria dinamica è: void mxFree(void *ptr);

Per quanto riguarda la funzione mexPrintf, sono effettivamente in grado di usarlo. Ho appena ricevuto un avviso implicit declaration of function 'mexPrintf' is invalid in C99 [-Wimplicit-function-declaration], dal momento che sto compilando tramite gcc anziché mess. Se si utilizza gcc, è probabilmente necessario includere le librerie appropriate per riconoscere tale funzione. È utile trovare this utile, come ha funzionato per me.

+0

Ho aggiornato il mio codice in base al tuo suggerimento e posso leggere CellArray, ancora non riesco a leggere la stringa. Inoltre, non so come eliminare cellArray [2]). Inoltre, avrei preferito usare mexPrintf. Ma sto ricevendo un errore: riferimento non definito a 'mexPrintf '. Qualche ipotesi su questo ?? –

+0

Ho aggiunto l'aggiornamento alla mia risposta. – Shervin

Problemi correlati