2016-12-06 84 views
3

我正在製作一個程序,我必須不斷地在函數中使用矩陣工作,這是許多函數中的一個,這個函數應該打開一個外部文件,它是一個數據設置,其中的數據用表格分開,它打開文件並將數據保存在矩陣M中,我知道這個矩陣由6列組成,但行號是未知的,我知道錯誤是我聲明矩陣的地方,它必須用指針聲明,因爲該函數返回矩陣。從函數中返回一個矩陣C

//type float** since it will return a matrix 
float **carga_archivo(char *nombre_archivo)  
{ 
    float **M=(float **)malloc(6*sizeof(float*)); //error should be here 
    int i=0; 
    FILE *archivo;      //FILE type pointer to open the external file 
    archivo=fopen(nombre__archivo,"r"); //Opens the file in the address indicated 
             //"nombre_de_archivo" is a variable 
    while(!feof(archivo))    //Browses the file row per row till the end of it 
    { 
     //saves the data in its corresponding place in the matrix 
     fscanf(archivo,"%f\t%f\t%f\t%f\t%f\t%f\n", 
      &M[0][i],&M[1][i],&M[2][i],&M[3][i],&M[4][i],&M[5][i]); 
     i++; 
    } 
    tam=i; 
    fclose (archivo);     //closes the file 
    return M; 
} 

我需要的是正確的方法來聲明矩陣。

P.S.我記錄了代碼中的主要內容,以便可以幫助需要類似內容的人。

歡迎任何更正。

更新: 進行一些改動的意見建議,並更好地工作,這裏是新的代碼我名手該功能

float **carga_archivo(char *nombre_archivo) 
{ 
int i=0; 
float P[300][6]; 
FILE *archivo; 
archivo=fopen(nombre_archivo,"r"); 
while(!feof(archivo)) 
{ 
i++; 
     //this was just so the feof function could browse row per row 
     //instead of character per character 
    scanf("%f\t%f\t%f\t%f\t%f\t%f\n", 
       &P[0][i],&P[1][i],&P[2][i],&P[3][i],&P[4][i],&P[5][i]); 
    printf("%i\n",i); 
} 
tam=i; 
printf("%i",tam); 
int filas = 6; 
int columnas = tam; 
float **M; 

M = (float **)malloc(filas*sizeof(float*)); 

for (i=0;i<filas;i++) 
    M[i] = (float*)malloc(columnas*sizeof(float)); 

for (i = 0; i < columnas; ++i) 
    fscanf(archivo,"%f\t%f\t%f\t%f\t%f\t%f\n", 
      &M[0][i],&M[1][i],&M[2][i],&M[3][i],&M[4][i],&M[5][i]); 
fclose (archivo); 
return M; 
} 

新的問題是,當函數被調用,程序實際上編譯,但是當它的運行和函數被調用時,程序崩潰並停止。 這是調用該函數的代碼的一部分。

int main() 
{ 
int i,j; 
char *nombre_archivo="Agua_Vapor.txt"; 
float **agua_vapor=carga_archivo(nombre_archivo); 
for (i = 0; i < 6; i++) 
{ 
    for (j = 0; i < tam; i++) 
     printf("%f ", agua_vapor[i][j]); 
    printf("\n"); 
} 
return 0; 
} 
+2

'焦炭nombre_archivo'是錯誤。一個文件名有多個字符。另外,如果行數未知 - 您需要將該信息返回給調用者,也許作爲返回值(同時將函數的指針傳遞給將在函數返回後指向浮點數組的函數 –

+0

你,我只是編輯你提到的第一個問題,但我覺得我不跟你在第二部分,我不是很熟悉的指針,也許一個例子可以幫我一個小 –

+2

如果你不知道事先的行數,則需要通過文件掃描至少一次得到這個數字,*然後*分配*總*的內存量需要從文件中的數據存儲你的數據,然後讀入到您的矩陣。這需要通過文件讀取的兩倍。 – Evert

回答

2

您的程序有未定義的行爲,因爲您正在填充由未初始化的指針引用的內存。

由於您知道總是有6列,所以一個簡單的方法是將矩陣存儲爲行優先而不是列優先(您的示例是列專業)。這意味着您可以將矩陣數據存儲爲一大塊內存,並在需要時使用realloc。你也可以爲此做一個簡單的結構。

struct matrix { 
    int rows, cols; 
    float ** data; 
}; 

然後動態創建它。

struct matrix * matrix_alloc(int rows, int cols) 
{ 
    int i; 

    struct matrix * m = malloc(sizeof(struct matrix)); 
    m->rows = rows; 
    m->cols = cols; 
    m->data = malloc(rows * sizeof(float*)); 
    m->data[0] = malloc(rows * cols * sizeof(float)); 

    for(i = 1; i < rows; i++) { 
     m->data[i] = m->data[i-1] + cols; 
    } 
    return m; 
} 

void matrix_free(struct matrix * m) 
{ 
    free(m->data[0]); 
    free(m->data); 
    free(m); 
} 

現在,當你決定需要添加存儲更多的行:

void matrix_set_row_dimension(struct matrix * m, int rows) 
{ 
    float **new_index, *new_block; 
    new_index = realloc(m->data, rows * sizeof(float**)); 
    new_block = realloc(m->data[0], rows * m->cols * sizeof(float)); 
    if(new_index && new_block) 
    { 
     int i = m->rows; 
     m->rows = rows; 
     m->data = new_index; 

     /* if block address changed, prepare to reindex entire block */ 
     if(m->data[0] != new_block) 
     { 
      m->data[0] = new_block; 
      i = 1; 
     } 

     /* reindex */ 
     for(; i < rows; i++) { 
      m->data[i] = m->data[i-1] + cols; 
     } 
    } 
} 

所以,現在當你填入矩陣...

struct matrix * m = matrix_alloc(10, 6); /* Start with 10 rows */ 
int row = 0; 
while(1) { 
    /* Double matrix row count if not large enough */ 
    if(row == m->rows) 
    { 
     matrix_set_row_dimension(m, m->rows * 2); 

     /* Check for error here */ 
    } 

    /* Now the matrix has enough storage to continue adding */ 
    m->data[row][0] = 42; 
    m->data[row][1] = 42; 
    m->data[row][2] = 42; 
    m->data[row][3] = 42; 
    m->data[row][4] = 42; 
    m->data[row][5] = 42; 

    row++;  
} 
+1

注意:這不是強化代碼。需要適當處理所有重新分配故障情況,以及處理初始分配失敗。這裏的代碼純粹是一種合理方法的說明。 – paddy

+1

注意:'m-> data [0] = malloc(sizeof(float)* rows * cols);'與m-> data [0] = malloc(rows * cols * sizeof(float)) ;''sizeof(float)* rows * cols'通常不會在行* cols * sizeof(float)'後立即溢出。 – chux