反向波兰表示法 - C 中的数组、向量、标量

Reverse Polish Notation - arrays, vectors, scalars in C

我有一个大问题。我的老师告诉我,我必须写一个程序。我必须对向量、矩阵、标量等的运算使用反向波兰符号。例如,当你计算时,你写 4+5-6。在 RPN 中,你将以这种方式编写 45+6-。 https://www.prodevelopertutorial.com/given-an-expression-in-reverse-polish-notation-evaluate-it-and-get-the-output-in-c/ 我必须将输出写入文件并显示在屏幕上

但是我的程序会难很多

  1. 我不会在我的计算中使用数字,而是向量、标量、矩阵。
  2. 我必须从文件中读取值
  3. 我必须使用快捷方式; V 是向量,S 是标量,M 是矩阵
  4. 此外,我必须使用更多的操作,而不仅仅是简单的操作 还有
+ adding
- subtraction
* multiplication
/ division
T transpose of an array
. scalar product
x vector product
D determinant
R inverse matrix

这是我的数据文件

S scalar1 3
S scalar2 5
V vector1 3
2 4 7
V vector2 3
3 6 1
M matrix_A 3 3
1 2 3
4 5 6
7 8 9
M matrix_B 3 3
9 8 7
6 5 4
3 2 1

您看到我必须创建具有快捷方式 M/V/S、元素名称、维度(矩阵的 dimX 和 Y)和值的结构。 稍后我将在这个数据文件中添加像

这样的操作
matrix_A
matric_B
*

这是我的带有 io 函数的文件 operation_io.c

#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME 20
#define MAX_ARRAY_DIM 50

typedef struct Vector {
    char keyWordV;
    char name[MAX_NAME];
    int dim;
    double data[MAX_ARRAY_DIM];
} Vector;

typedef struct Scalar {
    char keyWordS;
    char name[MAX_NAME];
    double data;
} Scalar;

typedef struct Matrix {
    char keyWordM;
    char name[MAX_NAME];
    int dimX;
    int dimY;
    double data[MAX_ARRAY_DIM][MAX_ARRAY_DIM];
} Matrix;

typedef struct Element {
    char type;
    union {
        Scalar s;
        Vector v;
        Matrix m;
    } elem;
} Element;

void readScalar(FILE *file, Scalar* s) {
    fscanf(file, " %s ", &s->name[0]);
    fscanf(file, "%10lf", &s->data);
    }
    
void writeScalar(FILE *file, Scalar* s) {
    fprintf(file, "S");
    fprintf(file, " %s \n", s->name);
    fprintf(file, "%10.2lf \n", s->data);
    }

void showScalar(Scalar* s) {
    printf("S");
    printf(" %s \n", s->name);
    printf("%10.2lf \n", s->data);
    }
    
void readVector(FILE *file, Vector* v) {
    fscanf(file, " %s %d ", &v->name[0], &v->dim);
    for (int j = 0; j < v->dim; ++j) {
        fscanf(file, "%10lf", &v->data[j]);
    }
}

void writeVector(FILE *file, Vector* v) {
    fprintf(file, "V");
    fprintf(file, " %s %d \n", v->name, v->dim);
    for (int j = 0; j < v->dim; ++j) {
        fprintf(file, "%10.2lf ", v->data[j]);
    }
    fprintf(file, "\n");
}

void showVector(Vector* v) {
    printf("V");
    printf(" %s %d \n", v->name, v->dim);
    for (int j = 0; j < v->dim; ++j) {
        printf("%10.2lf ", v->data[j]);
    }
    printf("\n");
}

void readMatrix(FILE *file, Matrix* m) {
    fscanf(file, " %s %d %d", &m->name[0], &m->dimX, &m->dimY);
    for (int i = 0; i < m->dimX; ++i)
        for (int j = 0; j < m->dimY; ++j)
            fscanf(file, "%10lf", &m->data[i][j]);
}

void writeMatrix(FILE *file, Matrix* m) {
    fprintf(file, "M");
    fprintf(file, " %s %d %d \n", m->name, m->dimX, m->dimY);
    for (int i = 0; i < m->dimX; ++i) 
    {
        for (int j = 0; j < m->dimY; ++j)
        {
            fprintf(file, "%10.2lf", m->data[i][j]);
        }
        fprintf(file, "\n");
    }
}

void showMatrix(Matrix* m) {
    printf("M");
    printf(" %s %d %d \n", m->name, m->dimX, m->dimY);
    for (int i = 0; i < m->dimX; ++i)
    {
        for (int j = 0; j < m->dimY; ++j)
        {
            printf("%10.2lf", m->data[i][j]);
        }
        printf("\n");
    }
}
void readElement(FILE *file, Element* e) {
    char type;
    fscanf(file, " %c ", &type);
    switch (type) {
    case 'S':
        e->type = 'S';
        readScalar(file, &e->elem.s);
        writeScalar(file, &e->elem.s);
        showScalar(&e->elem.s);
        break;
    case 'V':
        e->type = 'V';
        readVector(file, &e->elem.v);
        writeVector(file, &e->elem.v);
        showVector(&e->elem.v);
        break;
    case 'M':
        e->type = 'M';
        readMatrix(file, &e->elem.m);
        writeMatrix(file, &e->elem.m);
        showMatrix(&e->elem.m);
        break;
    default:
        fputs("Error: unknown token!\n", stderr);
        exit(1);
    }
}

void policz(FILE *file, Element* e1, Element* e2, Element* e3)
{
    char type1, type2, type3;
    fscanf(file, " %c ", &type1);
    fscanf(file, " %c ", &type2);
    fscanf(file, " %c ", &type3);
    
}
int isOperator(char ch){
   if(ch == '+'|| ch == '-'|| ch == '*'|| ch == '/' || ch == '^')
      return 1;//character is an operator
   return -1;//not an operator
}
int isOperand(char ch){
   if(ch == 'S' || ch == 'V' || ch == 'M')
      return 1;//character is an operand
   return -1;//not an operand
}
#define MAX_D 256
double stack[MAX_D];
int depth;



void die(const char *msg)
{
    fprintf(stderr, "%s", msg);
    abort();
}
void push(double v)
{
    if (depth >= MAX_D) die("stack overflow\n");
    stack[depth++] = v;
}
 
double pop()
{
    if (!depth) die("stack underflow\n");
    return stack[--depth];
}
float operation(int a, int b, char op){ //bede dopiero pisal funkcje
   //Perform operation
   if(op == '+')
      return 1;
   else if(op == '-')
      return 1;
   else if(op == '*')
      return 1;
   else if(op == '/')
      return 1;
   else
      return 1; //return negative infinity
}

operation_io.h

#ifndef WEKTORY
#define WEKTORY

typedef struct Scalar Scalar;
typedef struct Vector Vector;
typedef struct Matrix Matrix;
typedef struct Element Element;

void readScalar(FILE *file, Scalar* s);
void writeScalar(FILE *file, Scalar* s);
void showScalar(Scalar* s);
void readVector(FILE *file, Vector* v);
void writeVector(FILE *file, Vector* v);
void showVector(Vector* v);
void readMatrix(FILE *file, Matrix* m);
void writeMatrix(FILE *file, Matrix* m);
void showMatrix(Matrix* m);
void readElement(FILE *file, Element* e);
void die(const char *msg);
void push(double v);
double pop();
float operation(int a, int b, char op);

#endif

这是我的主程序。 main.c

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "operation_io.h"
#define MAX_NAME 20
#define MAX_ARRAY_DIM 50


typedef struct Vector {
    char keyWordV;
    char name[MAX_NAME];
    int dim;
    double data[MAX_ARRAY_DIM];
} Vector;

typedef struct Scalar {
    char keyWordS;
    char name[MAX_NAME];
    double data;
} Scalar;

typedef struct Matrix {
    char keyWordM;
    char name[MAX_NAME];
    int dimX;
    int dimY;
    double data[MAX_ARRAY_DIM][MAX_ARRAY_DIM];
} Matrix;

typedef struct Element {
    char type;
    union {
        Scalar s;
        Vector v;
        Matrix m;
    } elem;
} Element;

int main (int argc, char *argv[])
{    
    FILE *wz, *wc;  

    if (argc != 3) {                                
    printf("Wrong arguments number\n");
    printf("I should run this way:\n");
    printf("%s source\n",argv[0]);
    exit(1);
    }
    
    if( (wz= fopen(argv[1],"r")) == NULL) {
        printf("Open error %s\n", argv[1]);
        exit(1);
    }
    if( (wc= fopen(argv[2], "w")) == NULL) {
    printf("Open error %s\n", argv[2]);
    exit(2);
    }


    Element elements[10];
    for (int i = 0; i < 6; i++) {
        readElement(wz, &elements[i]);
    }
    fclose(wz);
    fclose(wz);
    
    return 0;

}

我的文件用算术运算。 operation_m.c 是空的,因为我没有开始编写这些函数,因为我遇到了问题。 我想使用那样的算法 https://rosettacode.org/wiki/Parsing/RPN_calculator_algorithm#C 但是我的情况比较复杂,因为我没有使用数字,而且我有更多的操作(不仅是+,-,*,=)

我现在有 3 个问题

  1. 我的书写功能不工作,但我的显示在屏幕上的功能完美无缺。
  2. 我不知道,我的程序如何知道我使用的是矩阵、向量还是标量? 例如我有
matrix_A
matrix_B
*

我的程序如何知道名称 matrix_A 和 matrix_B 表示 2 个矩阵的乘法并使用函数 multMatrices() (我还没有编写此函数,但我会的)。我有个主意。我想用快捷方式连接名称。所以我的程序会发现我想乘以矩阵而不是例如标量和矩阵。我这里有我的对象 - 元素数组

    Element elements[10];
    for (int i = 0; i < 6; i++) {
        readElement(wz, &elements[i]);
    }

所以我必须知道如何使用这个数组中的适当元素,那么该怎么做呢?

  1. 在这个算法中我没有一元运算https://rosettacode.org/wiki/Parsing/RPN_calculator_algorithm#C但是在我的程序中我会有矩阵的转置等。所以我可能必须添加一些if in switch case???
  1. I dont know, how my program will know that I use matrix, vector or scalar? For example I have

    matrix_A matrix_B * how my program will know that name matrix_A and matrix_B means the multiplication of 2 matrices and use function multMatrices()

您需要一个字典将名称 (char*) 关联到 Element,因为您的定义很可能很少,没有性能问题,而且使用起来毫无用处复杂的结构并使用散列或平衡树等 map 实现

然后进行例如二进制操作,有效情况是至少有 2 个 Element 压入堆栈,您只需要检查它们的 type 来决定调用什么函数。请注意,您还可以使用 0、1、2 作为允许使用函数指针数组的类型。

操作数的类型必须相同吗?例如,标量可能允许 multiply/add/divide/substract a vector/matrix,将操作应用于每个单元格 ?

Vector中属性keyWordV,在Scalar中属性 keyWordS 没用,在 Matrix 中属性 keyWordM 没用。

name属性在Vector/Scalar/Matrix里面也是没用的,只需要在元素类型同级(出union

Vector/Scalar/Matrix中使用固定大小的数组是可行的,但使用的内存比必要的多,如果元素数量大于MAX_ARRAY_DIM 或者名称是否大于 MAX_NAMEElement elements[10];.

相同
  1. My writing functions aren't working, but my functions with showing on the screen works perfect

怎么可能,writeXshowX函数完全一样,其实showX(x)可以定义作为 writeX(stdout, x)

  1. In this algorithm I dont have unary operations ...

坦率地说,逆波兰表示法实现起来非常简单,您可以自己从头开始做,这样做您会学到更多 ;-)

无论 n 一个 nnary 运算符从入栈(当然要检查至少有n个元素否则报错),计算结果,然后push结果,trivial