反向波兰表示法 - 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/
我必须将输出写入文件并显示在屏幕上
但是我的程序会难很多
- 我不会在我的计算中使用数字,而是向量、标量、矩阵。
- 我必须从文件中读取值
- 我必须使用快捷方式; V 是向量,S 是标量,M 是矩阵
- 此外,我必须使用更多的操作,而不仅仅是简单的操作
还有
+ 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 个问题
- 我的书写功能不工作,但我的显示在屏幕上的功能完美无缺。
- 我不知道,我的程序如何知道我使用的是矩阵、向量还是标量?
例如我有
matrix_A
matrix_B
*
我的程序如何知道名称 matrix_A 和 matrix_B 表示 2 个矩阵的乘法并使用函数 multMatrices() (我还没有编写此函数,但我会的)。我有个主意。我想用快捷方式连接名称。所以我的程序会发现我想乘以矩阵而不是例如标量和矩阵。我这里有我的对象 - 元素数组
Element elements[10];
for (int i = 0; i < 6; i++) {
readElement(wz, &elements[i]);
}
所以我必须知道如何使用这个数组中的适当元素,那么该怎么做呢?
- 在这个算法中我没有一元运算https://rosettacode.org/wiki/Parsing/RPN_calculator_algorithm#C但是在我的程序中我会有矩阵的转置等。所以我可能必须添加一些if in switch case???
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_NAME ?
Element elements[10];
.
相同
- My writing functions aren't working, but my functions with showing on the screen works perfect
怎么可能,writeX和showX函数完全一样,其实showX(x)
可以定义作为 writeX(stdout, x)
- In this algorithm I dont have unary operations ...
坦率地说,逆波兰表示法实现起来非常简单,您可以自己从头开始做,这样做您会学到更多 ;-)
无论 n 一个 nnary 运算符从入栈(当然要检查至少有n个元素否则报错),计算结果,然后push结果,trivial
我有一个大问题。我的老师告诉我,我必须写一个程序。我必须对向量、矩阵、标量等的运算使用反向波兰符号。例如,当你计算时,你写 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/ 我必须将输出写入文件并显示在屏幕上
但是我的程序会难很多
- 我不会在我的计算中使用数字,而是向量、标量、矩阵。
- 我必须从文件中读取值
- 我必须使用快捷方式; V 是向量,S 是标量,M 是矩阵
- 此外,我必须使用更多的操作,而不仅仅是简单的操作 还有
+ 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 个问题
- 我的书写功能不工作,但我的显示在屏幕上的功能完美无缺。
- 我不知道,我的程序如何知道我使用的是矩阵、向量还是标量? 例如我有
matrix_A
matrix_B
*
我的程序如何知道名称 matrix_A 和 matrix_B 表示 2 个矩阵的乘法并使用函数 multMatrices() (我还没有编写此函数,但我会的)。我有个主意。我想用快捷方式连接名称。所以我的程序会发现我想乘以矩阵而不是例如标量和矩阵。我这里有我的对象 - 元素数组
Element elements[10];
for (int i = 0; i < 6; i++) {
readElement(wz, &elements[i]);
}
所以我必须知道如何使用这个数组中的适当元素,那么该怎么做呢?
- 在这个算法中我没有一元运算https://rosettacode.org/wiki/Parsing/RPN_calculator_algorithm#C但是在我的程序中我会有矩阵的转置等。所以我可能必须添加一些if in switch case???
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_NAME ?
Element elements[10];
.
- My writing functions aren't working, but my functions with showing on the screen works perfect
怎么可能,writeX和showX函数完全一样,其实showX(x)
可以定义作为 writeX(stdout, x)
- In this algorithm I dont have unary operations ...
坦率地说,逆波兰表示法实现起来非常简单,您可以自己从头开始做,这样做您会学到更多 ;-)
无论 n 一个 nnary 运算符从入栈(当然要检查至少有n个元素否则报错),计算结果,然后push结果,trivial