C записывает случайную матрицу в файл, а затем считывает и копирует указанную матрицу из файла, используя форматированный ввод / вывод - PullRequest
3 голосов
/ 28 декабря 2011

Спасибо за всю помощь, которую я получил здесь раньше.

В приведенной ниже программе я хочу создать случайную матрицу, распечатать ее на экране, записать в файл, а затем отсканировать копию этогоматрица из файла и распечатать копию на экран, все работает, за исключением случаев, когда я пытаюсь прочитать из файла, алгоритм в моем коде является неправильным, я думаю,

функция scanf не работает, я не знаю, почему....

double *matrix_read(FILE *fptr, double *mat, int m, int n ) ;

double *matrix_read(FILE *fptr,double *mat, int m, int n ) {
     int i,j;
     double *ptr,x ;
     ptr=mat;

    if((fptr=fopen("matrixA.txt","r"))==NULL)
    {
        puts("Cannot Open File");
    }
    rewind(fptr);
    fscanf( fptr,"\n\nrows %d, columns %d\n\n", &m, &n) ;
    mat = (double *) malloc( sizeof( double ) * m * n ) ;

    for ( i=0; i < m; i++ )
    {
        for ( j=0; j < n; j++ )
        {
            fscanf(fptr, "  %5.2lf", &x );
            *ptr++=x;
        }
    }
    fclose(fptr);

    return mat ;   
}

В моем main функции вызываются следующим образом:

rand_matrix(MATRIX.matrix, MATRIX.rows, MATRIX.cols );  /* populates matrix with random                     data */

print_matrix(MATRIX.matrix, MATRIX.rows, MATRIX.cols ) ;  /* prints the matrix */

matrix_write( fptr, MATRIX.matrix, MATRIX.rows, MATRIX.cols ) ; /* writes matrix to     file*/

_flushall();
getchar();

MATRIX1.matrix=matrix_read( fptr, MATRIX.matrix, MATRIX.rows, MATRIX.cols ) ; /* reads     above matrix from file as a copy */

print_matrix(MATRIX1.matrix, MATRIX.rows, MATRIX.cols ) ; /* prints this copyed matrix*/

при печати скопированной матрицы я получаю кучу искаженных, массивных чисел (т.е. 1259000000000000000000) Я думаю, что это имена ячеек памяти или что-то, может кто-нибудь помочь мне исправить мою read_matrix() функцию?

Большое спасибо.

Ниже приведен мой полный код (он компилируется).

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>
#include <conio.h>

double random() ;
double *rand_matrix( double *mat, int m, int n ) ;
void print_matrix( double *mat, int m, int n ) ;    
void matrix_write(FILE *fptr, double *mat, int m, int n ) ;    
double *matrix_read(FILE *fptr, double *mat, int m, int n ) ;    

int main()
{

    struct matrep {
      unsigned rows,cols;
      double *matrix;
    } MATRIX,MATRIX1,MATRIX2;

    int check = 0 ;
    FILE *fptr;

    printf( "\n\nMatrix Manipulations Program" );

    do {
        printf( "\n\nEnter matrix dimensions : rows x columns : " );
        check = scanf( "%d x %d", &MATRIX.rows, &MATRIX.cols );
        _flushall();
    } while ( check != 2 || MATRIX.rows < 1 || MATRIX.cols < 1 ) ;

    MATRIX.matrix = (double *) malloc( sizeof( double ) * MATRIX.rows * MATRIX.cols ) ;

    if ( !MATRIX.matrix ){
        printf( "\n\nSTOP : unable to allocate memory - exiting program") ;
        exit( 1 ) ;
    }

    rand_matrix(MATRIX.matrix, MATRIX.rows, MATRIX.cols );  /* populates matrix with random data */

    print_matrix(MATRIX.matrix, MATRIX.rows, MATRIX.cols ) ;  /* prints the matrix */

    matrix_write( fptr, MATRIX.matrix, MATRIX.rows, MATRIX.cols ) ; /* writes matrix to     file*/

    _flushall();
    getchar();

    MATRIX1.matrix=matrix_read( fptr, MATRIX.matrix, MATRIX.rows, MATRIX.cols ) ; /* reads     above matrix from file as a copy */

    print_matrix(MATRIX1.matrix, MATRIX.rows, MATRIX.cols ) ; /* prints this copyed matrix*/

    _flushall();
    getchar();
}

/***********************************************************/

double random()
{
    static int seeded = 0;
    double val ;

    if ( !seeded )
    {
       srand( time(NULL) ) ;
       seeded = 1;
    }

    val = ((double)rand())/ (double)RAND_MAX * 100.0 ;

    return val ;
}

/***********************************************************/

double *rand_matrix( double *mat, int m, int n ) 
{
    double *ptr ;
    int i, j ;

    ptr = mat ;

    for ( i=0; i < m; i++ ){
        for ( j=0; j < n; j++ ){
            *ptr++ = random() ;
        }
    }
    return mat ; 
}

/***********************************************************/

void print_matrix( double *mat, int m, int n ) 
{
    double *ptr ;
    int i, j ;

    if ( mat==0 || m==0 || n==0 )
    {
       printf("\n\nEmpty matrix" );
       return ;       
    }

    ptr = mat ;

    printf( "\n\nrows %d, columns %d\n\n", m, n) ;

    for ( i=0; i < m; i++ )
    {
        for ( j=0; j < n; j++ )
        {
            printf( "\t%5.2lf", *ptr++ );
        }
        printf( "\n" ) ;
    }

}

/***********************************************************/
void matrix_write(FILE *fptr,double *mat, int m, int n ) {
     int i,j;
    if((fptr=fopen("matrixA.txt","w"))==NULL)
    {
        puts("Cannot Open File");
    }
    fprintf( fptr,"\n\nrows %d, columns %d\n\n", m, n) ;

    for ( i=0; i < m; i++ )
    {
        for ( j=0; j < n; j++ )
        {
            fprintf(fptr, "  %5.2lf", *mat++ );
        }
        fprintf(fptr, "\n" ) ;
    }
    fclose(fptr);    
}

/***********************************************************/
double *matrix_read(FILE *fptr,double *mat, int m, int n ) {
     int i,j;
     double *ptr,x ;
     ptr=mat;

    if((fptr=fopen("matrixA.txt","r"))==NULL)
    {
        puts("Cannot Open File");
    }
    rewind(fptr);
    fscanf( fptr,"\n\nrows %d, columns %d\n\n", &m, &n) ;
    mat = (double *) malloc( sizeof( double ) * m * n ) ;

    for ( i=0; i < m; i++ )
    {
        for ( j=0; j < n; j++ )
        {
            fscanf(fptr, "  %5.2lf", &x );
            *pt++r=x;
        }
    }
    fclose(fptr);

    return mat ;   
}

Ответы [ 2 ]

3 голосов
/ 28 декабря 2011
for ( i=0; i < m; i++ )
{
    for ( j=0; j < n; j++ )
    {
        fscanf(fptr, "  %5.2lf", &x );
        *ptr=x;
    }
}

Хотя весь ваш код был слишком длинным для чтения, этот раздел определенно не верен.Вы должны увеличить указатель на некоторое время, иначе будет инициализирован только первый элемент.Попробуйте:

*ptr++ = x;

valgrind - отличный инструмент для обнаружения таких ошибок, он выдаст ошибку при доступе (или печати, в вашем случае) к неинициализированной памяти.

2 голосов
/ 29 декабря 2011

Проблема, как это часто бывает, в управлении памятью. Однако в коде много других странностей:

double *matrix_read(FILE *fptr, double *mat, int m, int n)
{
    int i, j;
    double *ptr, x;
    ptr = mat;  // This points to the matrix passed into the function

    // Why pass fptr as an argument if the first thing you do is open a file?
    // Especially since you close it at the end
    if ((fptr = fopen("matrixA.txt", "r")) == NULL)
    {
        puts("Cannot Open File");
        return 0;  // Get out; do not use the file stream!
    }
    rewind(fptr);  // This is unnecessary; a file is opened for reading at the start
    if (fscanf(fptr, "\n\nrows %d, columns %d\n\n", &m, &n) != 2)
    {
        puts("Failed to read dimensions of array");
        return 0;
    }
    mat = (double *)malloc(sizeof(double) * m * n);
    // Now you've got a new matrix, but you did not reinitialize ptr to use it!

Есть также несколько случайных интервалов между операторами. Последовательность имеет первостепенное значение; учитывая это, пробелы после запятых, а не до; пробелы после точек с запятой, а не до; пробелы вокруг бинарных операторов.

Кроме того, у вас есть структура для матрицы, но вы не передаете эту структуру своим функциям. Ваш код, вероятно, был бы лучше, если бы вы его использовали. OTOH, вам нужно переместить определение struct matrep за пределы main(), чтобы его могли видеть функции.

int matrix_read(struct matrep *mat)
{
    FILE *fptr;
    unsigned m, n;

    if ((fptr = fopen("matrixA.txt", "r")) == NULL)
    {
        fprintf(stderr, "Cannot Open File %s\n", "matrixA.txt");
        return -1;
    }
    if (fscanf(fptr, "\n\nnrows %u, columns %u\n\n", &m, &n) != 2)
    {
        fprintf(stderr, "Failed to read dimensions\n");
        return -1;
    }
    // ?? free(mat.matrix); ?? /* to release previously allocated memory */
    mat.matrix = (double *)malloc(sizeof(double) * m * n);
    if (mat.matrix == 0)
    {
        fprintf(stderr, "Failed to allocate %d*%d matrix\n", m, n);
        return -1;
    }
    double *ptr = mat.matrix;

    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            double x;
            if (fscanf(fptr, "  %5.2lf", &x) != 1)
            {
                fprintf(stderr, "Failed to read element matrix[%d,%d]\n", i, j);
                free(mat.matrix);
                mat.matrix = 0;
                mat.columns = 0;
                mat.rows = 0;
                return -1;
            }
            *ptr++ = x;
        }
    }
    fclose(fptr);
    mat.columns = m;
    mat.rows = n;

    return 0;  // Success   
}

Есть много изменений, но наиболее значительным является то, что, передав struct matrep в функцию, код может указать размер матрицы, которую он читает в вызывающий код.

...