从文件中读取矩阵并获取其维度 [英] reading matrices from a file and retriving their dimension

查看:50
本文介绍了从文件中读取矩阵并获取其维度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文本文件,其中包含以下两种形式的矩阵:

I have a text file containing two matrices in this form:


1 2 3
4 5 6
1 2 3
*
4 5 6
1 2 3]

我希望能够读取两个矩阵的维数和操作类型* +/-.我想同时检索维度并读取数据.

I want to be able to read the dimension of the two matrices and the type of operation * + / -. I'd like to retrieve the dimension and read data at the same time.

在我的代码中,get_dim()函数遍历文件中的数据以获取两个矩阵的维数.我不知道此时是否有一种方法可以通过动态内存分配来存储矩阵的值.使用函数read_matrix(),我知道矩阵的维数,因此我可以再次读取相同的数据.

In my code the get_dim() function goes through the data in the file to get the dimension of the two matrices. I don't know if there is a way to store the values of the matrices already at this point with dynamic memory allocation. With the function read_matrix() one that I know the dimension of the matrices I'm reading again the same data.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>

#define IN 1
#define OUT 0

struct matrix{
    int rows;
    int cols;
    double *data;
};

void f(double x); /*truncate a double */
int get_dim(char *file, int *r, int *col);
void read_matrix(char *file, struct matrix *A, struct matrix *B);
void print_matrix(struct matrix *A);
void multiply(struct matrix *A, struct matrix *B, struct matrix *C);

int main (int argc, char *argv[])
{
    int rows[2]= {0,0};
    int cols[2]= {0,0};
    int operation; /*type of operation 1 for * and 2 for + */

    operation = get_dim(argv[1], rows, cols);   

    struct matrix A;
    struct matrix B;
    struct matrix C;

    A.rows = rows[0];
    A.cols = cols[0];

    B.rows = rows[1];
    B.cols = cols[1];

    C.rows = rows[0];
    C.cols = cols[1];

    A.data = malloc(sizeof(double) * A.rows * A.cols);
    B.data = malloc(sizeof(double) * B.rows * B.cols); 
    C.data = malloc(sizeof(double) * A.rows * B.cols);

    read_matrix(argv[1],&A,&B);

    print_matrix(&A);

    printf("\n*\n");

    print_matrix(&B);
    printf("\n=\n");

    multiply(&A,&B,&C);
    print_matrix(&C);

    free(A.data);
    free(B.data);
    free(C.data);

    return 0;
}

void read_matrix(char *file, struct matrix *A, struct matrix *B){

    int i,j;
    FILE *fp;
    int c=1;

    if((fp = fopen(file, "r")) != NULL ){

        for(i=0; i < A->rows; i++)
            for(j=0; j < A->cols; j++)
                fscanf(fp, "%lf", (A->data + (i * A->cols + j)));

        /*skip the character operator line */

        while(!isdigit(c))
            c=fgetc(fp);

        ungetc(c,fp);

        for(i=0; i < B->rows; i++)
           for(j=0; j < B->cols; j++)
                fscanf(fp, "%lf", (B->data + (i * B->cols + j)));
    }
    fclose(fp);
}

int get_dim(char *file, int *rows, int *cols){

    FILE *fp;
    double a;
    int c =1;
    int n = OUT;
    int op=0;

    if((fp = fopen(file, "r")) == NULL ){
        fprintf(stderr, "matrix: I cannot open %s\n",file);
        exit(1);
    }

    while(fscanf(fp,"%lf",&a)){

            if(n==OUT)
                cols[0]++;

            c=fgetc(fp);

            if(isdigit(c))
                ungetc(c,fp);

            else if(c =='\n'){
                rows[0]++;
                n=IN;                
            }

            else if(c=='*'){
                op=1;
                break;
            }
    }  

    n=OUT;
    printf("\n");

    while(!isdigit(c))
        c=fgetc(fp);

    ungetc(c,fp);   

    while(fscanf(fp,"%lf",&a)){

        if(n==OUT)
            cols[1]++;

        c=fgetc(fp);

        if(isdigit(c))
            ungetc(c,fp);

        else if(c =='\n'){
            rows[1]++;
            n=IN;                
        }

        else if(c == ']'){
                rows[1]++;
                break;    
        }
    }
    fclose(fp);
    return op;
} 

void print_matrix(struct matrix *A){

    int i,j;

/*printing the matrices*/

     double *tmp = A->data;

     for(i=0; i < A->rows; i++){
        for(j=0; j < A->cols; j++){
                f(*(tmp++));
        }
        printf("\n");
    }    
}

void multiply(struct matrix *A, struct matrix *B, struct matrix *C) 
{ 
    int i, j, k;

    /*initialize C to 0*/

   for (i=0; i< C->rows; i++){
    for (j=0; j < C->cols; j++)
        C->data[i * C->cols + j]=0;
   }
// Multiplying matrix A and B and storing in C.
   for(i = 0; i < A->rows; ++i)
        for(j = 0; j < B->cols; ++j)
            for(k=0; k < A->cols; ++k)
                C->data[i * C->cols + j] += A->data[i * A->cols + k] * B->data[k * B->cols + j];
}

void f(double x)
{
    double i,f= modf(x,&i);

    if(f<.00001)
        printf("%.f ",i);
    else printf("%f ",x);    
}

推荐答案

关于您问题的第一个版本的一些评论

Some remarks on the first version of your question

您的循环

 while (chr != EOF)
 {
   //Count whenever new line is encountered
   if (chr == '\n')
       rows++;
   //take next character from file.
   chr = getc(fp);
 }

读取文件的末尾,因此两个矩阵都需要检测到"*",因此您要分开第一个和第二个矩阵

read up to the end of the file so both matrices, you need to detect the "*" so you do separate the first and the second matrices

您不检测列数,需要读取每行的行数,然后计算每行的值数(至少是第一行)

you do not detect the number of columns, you need to read line per line, then to count the number of values per line (at least the first)

str = (char *) malloc(6 * sizeof(char));

if( fgets (str, 24, fp)!=NULL ) {

您可能会遇到未定义的行为,因为您只分配了6个字符而最多读取了24个执行 fgets(str,24,fp)的字符

you can have an undefined behavior because you read up to 24 characters doing fgets (str, 24, fp) while you allocated only 6

c!= EOF 要求 c int ,而不是 char

这是一个建议,我不知道您希望使用哪种数字,所以我不尝试读取数字,我只看空格分隔的元素,可以添加 sscanf 或等同于检查每个元素是否为数字.我还假定运算符在其行上是一个单独的字符(紧随其后的是换行符)

Here is a proposal, I do not know what are the kind of number you expect so I do not try to read number, I just look at elements separated by space, you can add a sscanf or equivalent to check each element is a number. I also suppose the operator is a character alone on its line (there is a newline just after)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int readMat(FILE * fp, int * cols, int * rows, char * oper)
{
  *cols = *rows = 0;
  *oper = 0;

  char * lineptr = NULL;
  size_t n = 0;

  while (getline(&lineptr, &n, fp) > 0) {
    if (((*lineptr == '*') || (*lineptr == '/') || (*lineptr == '-') || (*lineptr == '+'))
        && (lineptr[1] == '\n')) {
      *oper = *lineptr;
      break;
    }

    if (strtok(lineptr, " ") == NULL) {
      /* invalid input */
      *cols = 0;
      break;
    }

    *rows += 1;

    int c = 1;

    while (strtok(NULL, " ") != NULL)
      c += 1;

    if (*cols == 0)
      *cols = c;
    else if (*cols != c) {
      /* invalid input */
      *cols = 0;
      break;
    }
  }

  free(lineptr);

  return *cols != 0;
}

int main(int argc, char ** argv)
{
  if (argc != 2)
    printf("Usage: %s <file>\n", *argv);
  else {
    FILE * fp = fopen(argv[1], "r");

    if (fp == NULL)
      fprintf(stderr, "cannot open '%s'\n", argv[1]);
    else {
      int cols, rows;
      char oper;

      if (!readMat(fp, &cols, &rows, &oper))
        fputs("invalid first matrice", stderr);
      else if (oper == 0)
        fputs("operator is missing", stderr);
      else {
        printf("first matrice has %d columns and %d rows\noper is %c\n", cols, rows, oper);

        if (!readMat(fp, &cols, &rows, &oper))
          fputs("invalid second matrice", stderr);
        else if (oper != 0)
          fputs("unexpected operator", stderr);
        else
          printf("second matrice has %d columns and %d rows\n", cols, rows);
      }
      fclose(fp);
    }
  }

  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wall -Wextra m.c
pi@raspberrypi:/tmp $ cat m
1 2 3
4 5 6
1 2 3
*
  44  5.2   6e12
-1     2   333
pi@raspberrypi:/tmp $ ./a.out m
first matrice has 3 columns and 3 rows
oper is *
second matrice has 3 columns and 2 rows
pi@raspberrypi:/tmp $ 


如果您没有 getline 替换

  char * lineptr = NULL;
  size_t n = 0;

  while (getline(&lineptr, &n, fp) > 0) {

例如,

  char * lineptr = malloc(1024);

  while (fgets(lineptr, 1024, fp) != NULL) {

这篇关于从文件中读取矩阵并获取其维度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆