I have a big problem. My teacher told me that I must write a program. I must use reverse polish notation for operations on vectors, matrices, scalars etc. For example, when you calculate, you write 4+5-6. In RPN, you will write this, in this way 45+6-. https://www.prodevelopertutorial.com/given-an-expression-in-reverse-polish-notation-evaluate-it-and-get-the-output-in-c/ I must write output into the file and show on the screen
But my program will be much more difficult.
+ adding
- subtraction
* multiplication
/ division
T transpose of an array
. scalar product
x vector product
D determinant
R inverse matrix
This is my data file
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
You see that I must create structs that have shortcut M/V/S, name of the element, dimension (dimX and Y for Matrices), and values. Later I will add in this data file operations like
matrix_A
matric_B
*
This is my file with io functions 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
This is my main program. 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;
}
MY file with the arithmetic operation. operation_m.c is empty because I'm not started with writing these functions because I have a problem. I want to use algorithm like that https://rosettacode.org/wiki/Parsing/RPN_calculator_algorithm#C But my case is more complicated because I am not using numbers and I have more operations (not only +,-,*,=)
I have 3 problems right now
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() (I haven't written this functions yet, but I will). I have an Idea. I want to connect name with a shortcut. So my program will find that I want to multiplicate matrices not for example scalar and matrix. I have my objects here - array of elements
Element elements[10];
for (int i = 0; i < 6; i++) {
readElement(wz, &elements[i]);
}
so I must know how to use a proper element from this array, so how to do that?
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()
you need a dictionary associating name (char*
) to Element, because you will have very probably few definitions there is no performance problem and it is useless to use complex structures and to implement a map using hashing, or balanced tree etc.
Then having for instance a binary operation the valid case is to have at least 2 Element pushed in the stack and you just have to check their type to decide what function to call. Note you can also use 0, 1, 2 for the type allowing to use an array of pointer to function.
Are the type of the operand must be the same ? It may be allowed to multiply/add/divide/substract a vector/matrix by a scalar for instance, applying the operation on each cell ?
In Vector the attribute keyWordV, in Scalar the attribute keyWordS is useless, in Matrix the attribute keyWordM is useless.
It is also useless to have the attribute name in Vector/Scalar/Matrix, you just need to have it in Element at the same level of type (out of the union
)
To use fixed size array in Vector/Scalar/Matrix is practical but that use more memory than necessary and what you will do if a number of element is greater than MAX_ARRAY_DIM or if a name is greater than MAX_NAME ?
Same for Element elements[10];
.
- My writing functions aren't working, but my functions with showing on the screen works perfect
how is it possible, the writeX and showX functions are exactly the same and in fact showX(x)
can be defined as writeX(stdout, x)
- In this algorithm I dont have unary operations ...
Frankly the reverse polish notation is so simple to implement you can do that by yourself from scratch, and doing that you will learn more ;-)
Whatever n an nnary operator pops its n operand(s) from the stack (of course check there are at least n element else indicate the error), computes the result, then pushes the result, trivial