Skip to content
Snippets Groups Projects
Commit 5ded2c31 authored by Florian Burgener's avatar Florian Burgener
Browse files

Initial commit

parents
Branches main
No related tags found
No related merge requests found
tests
calculator
*.o
copy.sh
Makefile 0 → 100644
TARGET = calculator
LIBS = -lm
CC = gcc
CFLAGS = -g -Wall -Wextra -pedantic -fsanitize=address -fsanitize=leak
.PHONY: default clean
default: $(TARGET)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $@
$(TARGET): main.o stack.o calculator.o
$(CC) main.o stack.o calculator.o $(CFLAGS) $(LIBS) -o $@
tests: calculator_tests.o stack.o calculator.o
$(CC) calculator_tests.o stack.o calculator.o $(CFLAGS) $(LIBS) -o $@
clean:
-rm -f *.o
-rm -f $(TARGET)
-rm -f tests
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h"
int32_t operators_length = 5;
char operators_symbol[] = {'+', '-', '*', '/', '^'};
int32_t operators_precedence[] = {1, 1, 2, 2, 3};
void print_stack(Stack *s) {
for (int32_t i = 0; i < s->top + 1; i += 1) {
printf("%s,", s->data[i]);
}
printf("\n");
}
int32_t get_operator_precedence(char operator) {
for (int32_t i = 0; i < operators_length; i += 1) {
if (operators_symbol[i] == operator) {
return operators_precedence[i];
}
}
return -1;
}
bool is_operator(char c) {
for (int32_t i = 0; i < operators_length; i += 1) {
if (operators_symbol[i] == c) {
return true;
}
}
return false;
}
char **infix_to_postfix(char *infix_expression[], int32_t infix_expression_length, int32_t *postfix_epxression_length) {
Stack operators;
stack_init(&operators, infix_expression_length);
Stack output;
stack_init(&output, infix_expression_length);
for (int32_t i = 0; i < infix_expression_length; i += 1) {
if (infix_expression[i][0] == '(') {
stack_push(&operators, infix_expression[i]);
} else if (infix_expression[i][0] == ')') {
while (true) {
char operator[100];
stack_pop(&operators, operator);
if (operator[0] == '(') {
break;
}
stack_push(&output, operator);
}
} else if (is_operator(infix_expression[i][0])) {
if (stack_is_empty(&operators)) {
stack_push(&operators, infix_expression[i]);
} else {
while (!stack_is_empty(&operators)) {
char operator[100];
stack_peek(&operators, operator);
int32_t precedence_1 = get_operator_precedence(operator[0]);
int32_t precedence_2 = get_operator_precedence(infix_expression[i][0]);
if (precedence_2 > precedence_1) {
break;
}
char tmp[100];
stack_pop(&operators, tmp);
stack_push(&output, tmp);
}
stack_push(&operators, infix_expression[i]);
}
} else {
stack_push(&output, infix_expression[i]);
}
}
while (!stack_is_empty(&operators)) {
char tmp[100];
stack_pop(&operators, tmp);
stack_push(&output, tmp);
}
char **output_str = (char **)malloc(sizeof(char *) * (output.top + 1));
for (int32_t i = 0; i < (output.top + 1); i += 1) {
output_str[i] = (char *)malloc(sizeof(char) * 100);
strcpy(output_str[i], output.data[i]);
}
*postfix_epxression_length = output.top + 1;
stack_destroy(&operators);
stack_destroy(&output);
return output_str;
}
double parse_postfix_epxression(char *postfix_expression[], int32_t postfix_expression_length) {
Stack output;
stack_init(&output, postfix_expression_length);
for (int32_t i = 0; i < postfix_expression_length; i += 1) {
if (!is_operator(postfix_expression[i][0])) {
stack_push(&output, postfix_expression[i]);
continue;
}
char operand_1[100];
char operand_2[100];
stack_pop(&output, operand_2);
stack_pop(&output, operand_1);
double result;
switch (postfix_expression[i][0]) {
case '+':
result = atof(operand_1) + atof(operand_2);
break;
case '-':
result = atof(operand_1) - atof(operand_2);
break;
case '*':
result = atof(operand_1) * atof(operand_2);
break;
case '/':
result = atof(operand_1) / atof(operand_2);
break;
case '^':
result = pow(atof(operand_1), atof(operand_2));
break;
}
char result_str[100];
sprintf(result_str, "%.15lf", result);
stack_push(&output, result_str);
}
char result_str[100];
stack_pop(&output, result_str);
stack_destroy(&output);
return atof(result_str);
}
#ifndef CALCULATOR_HEADER
#define CALCULATOR_HEADER
#include <stdint.h>
char **infix_to_postfix(char *infix_expression[], int32_t infix_expression_length, int32_t *postfix_epxression_length);
double parse_postfix_epxression(char *postfix_expression[], int32_t postfix_expression_length);
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "calculator.h"
const double EPSILON = 1e-10;
void test_1() {
// 7+2*3
char *infix_expression[] = {"7", "+", "2", "*", "3"};
int32_t infix_expression_length = 5;
int32_t postfix_expression_length;
char **postfix_expression = infix_to_postfix(infix_expression, infix_expression_length, &postfix_expression_length);
double result = parse_postfix_epxression(postfix_expression, postfix_expression_length);
assert(fabs(13 - result) <= EPSILON);
for (int32_t i = 0; i < postfix_expression_length; i += 1) {
free(postfix_expression[i]);
}
free(postfix_expression);
}
void test_2() {
// 8-5-2
char *infix_expression[] = {"8", "-", "5", "-", "2"};
int32_t infix_expression_length = 5;
int32_t postfix_expression_length;
char **postfix_expression = infix_to_postfix(infix_expression, infix_expression_length, &postfix_expression_length);
double result = parse_postfix_epxression(postfix_expression, postfix_expression_length);
assert(fabs(1 - result) <= EPSILON);
for (int32_t i = 0; i < postfix_expression_length; i += 1) {
free(postfix_expression[i]);
}
free(postfix_expression);
}
void test_3() {
// (7-5)/(2-(1-9)^(2^3))
char *infix_expression[] = {"(", "7", "-", "5", ")", "/", "(", "2", "-", "(", "1", "-", "9", ")", "^", "(", "2", "^", "3", ")", ")"};
int32_t infix_expression_length = 21;
int32_t postfix_expression_length;
char **postfix_expression = infix_to_postfix(infix_expression, infix_expression_length, &postfix_expression_length);
double result = parse_postfix_epxression(postfix_expression, postfix_expression_length);
assert(fabs(-0.00000011921 - result) <= EPSILON);
for (int32_t i = 0; i < postfix_expression_length; i += 1) {
free(postfix_expression[i]);
}
free(postfix_expression);
}
void test_4() {
// 2/(7-3*2)
char *infix_expression[] = {"2", "/", "(", "7", "-", "3", "*", "2", ")"};
int32_t infix_expression_length = 9;
int32_t postfix_expression_length;
char **postfix_expression = infix_to_postfix(infix_expression, infix_expression_length, &postfix_expression_length);
double result = parse_postfix_epxression(postfix_expression, postfix_expression_length);
assert(fabs(2 - result) <= EPSILON);
for (int32_t i = 0; i < postfix_expression_length; i += 1) {
free(postfix_expression[i]);
}
free(postfix_expression);
}
void test_5() {
// 3*(5-(7-1)*3)/2
char *infix_expression[] = {"3", "*", "(", "5", "-", "(", "7", "-", "1", ")", "*", "3", ")", "/", "2"};
int32_t infix_expression_length = 15;
int32_t postfix_expression_length;
char **postfix_expression = infix_to_postfix(infix_expression, infix_expression_length, &postfix_expression_length);
double result = parse_postfix_epxression(postfix_expression, postfix_expression_length);
assert(fabs(-19.5 - result) <= EPSILON);
for (int32_t i = 0; i < postfix_expression_length; i += 1) {
free(postfix_expression[i]);
}
free(postfix_expression);
}
void test_6() {
// 5^(3/2)+(5)^(2/3)
char *infix_expression[] = {"5", "^", "(", "3", "/", "2", ")", "+", "(", "5", ")", "^", "(", "2", "/", "3", ")"};
int32_t infix_expression_length = 17;
int32_t postfix_expression_length;
char **postfix_expression = infix_to_postfix(infix_expression, infix_expression_length, &postfix_expression_length);
double result = parse_postfix_epxression(postfix_expression, postfix_expression_length);
assert(fabs(14.1043576257 - result) <= EPSILON);
for (int32_t i = 0; i < postfix_expression_length; i += 1) {
free(postfix_expression[i]);
}
free(postfix_expression);
}
int main() {
printf("EPSILON = %.15lf\n", EPSILON);
test_1();
test_2();
test_3();
test_4();
test_5();
test_6();
}
main.c 0 → 100644
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "calculator.h"
int main() {
char input[256];
scanf("%s", input);
int32_t infix_expression_length = strlen(input);
char **infix_expression = (char **)malloc(sizeof(char *) * infix_expression_length);
for (int32_t i = 0; i < infix_expression_length; i += 1) {
infix_expression[i] = (char *)malloc(sizeof(char) * 100);
char tmp[100];
tmp[0] = input[i];
strcpy(infix_expression[i], tmp);
}
// for (int32_t i = 0; i < infix_expression_length; i += 1) {
// printf("%s ", infix_expression[i]);
// }
// printf("\n");
int32_t postfix_expression_length;
char **postfix_expression = infix_to_postfix(infix_expression, infix_expression_length, &postfix_expression_length);
for (int32_t i = 0; i < infix_expression_length; i += 1) {
free(infix_expression[i]);
}
free(infix_expression);
// for (int32_t i = 0; i < postfix_expression_length; i += 1) {
// printf("%s ", postfix_expression[i]);
// }
// printf("\n");
double result = parse_postfix_epxression(postfix_expression, postfix_expression_length);
printf("%.15lf\n", result);
for (int32_t i = 0; i < postfix_expression_length; i += 1) {
free(postfix_expression[i]);
}
free(postfix_expression);
return EXIT_SUCCESS;
}
stack.c 0 → 100644
#include "stack.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
void stack_init(Stack *s, int32_t size) {
s->size = size;
s->top = -1;
s->data = (char **)malloc(sizeof(char *) * s->size);
for (int32_t i = 0; i < s->size; i += 1) {
s->data[i] = (char *)malloc(sizeof(char) * 100);
}
}
bool stack_is_empty(Stack *s) {
return s->top == -1;
}
void stack_push(Stack *s, char *value) {
if (s->size == s->top + 1) {
return;
}
s->top += 1;
strcpy(s->data[s->top], value);
}
void stack_pop(Stack *s, char *value) {
if (stack_is_empty(s)) {
return;
}
stack_peek(s, value);
s->top -= 1;
}
void stack_peek(Stack *s, char *value) {
if (stack_is_empty(s)) {
return;
}
strcpy(value, s->data[s->top]);
}
void stack_destroy(Stack *s) {
for (int32_t i = 0; i < s->size; i += 1) {
free(s->data[i]);
}
s->size = -1;
s->top = -1;
free(s->data);
s->data = NULL;
}
stack.h 0 → 100644
#ifndef STACK_HEADER
#define STACK_HEADER
#include <stdbool.h>
#include <stdint.h>
typedef struct Stack {
int32_t size;
int32_t top;
char **data;
} Stack;
void stack_init(Stack *s, int32_t size);
bool stack_is_empty(Stack *s);
void stack_push(Stack *s, char *value);
void stack_pop(Stack *s, char *value);
void stack_peek(Stack *s, char *value);
void stack_destroy(Stack *s);
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment