2016-12-06 86 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