#include #include #include //#include "math_graphics.h" #include #include #include "m_string.h" enum TokenKind { ENDOFINPUT, INTEGER, KOMMA, PLUS, MINUS, MUL, DIV, MODULO, LPAREN, RPAREN, POW, SQRT, SIN, COS, TAN, ATAN, ATAN2, ANS }; //Definition Token struct Token { TokenKind kind = ENDOFINPUT; double floatValue; long intValue; }; //Erkennen ob Leerzeichen, Zeilenumbruch, Tabulator etc. bool isWhitespace(char c) { if (c == ' ' || c == '\n' || c == '\t' || c == '\r') { return true; } return false; } //Wenn Whitsepace weitergehen void eatWhitespace(String &s) { while (isWhitespace(s[0])) { advance(s); } } bool isNumber(char c) { if ('0' <= c && c <= '9') { return true; } return false; } long parseInteger(String inputString) { long integerValue = 0; for (int currentPosition = 0; currentPosition < inputString.length; currentPosition++) { integerValue = integerValue * 10 + inputString[currentPosition] - '0'; } return integerValue; } double parseFloat(String inputString) { double floatValue = 0.0; int currentPosition = 0; for (; currentPosition < inputString.length; currentPosition++) { if (inputString[currentPosition] == '.') { currentPosition++; break; } floatValue = floatValue * 10.0 + (inputString[currentPosition] - '0'); } double floatValue2 = 0.0; for (int currentPosition2 = inputString.length - 1; currentPosition2 >= currentPosition; currentPosition2--) { floatValue2 = floatValue2 / 10.0 + (inputString[currentPosition2] - '0'); } return floatValue + (floatValue2 / 10); } //Funktion zur Erkennung neuer Token Token getNextToken(String &inputString) { Token token = {}; eatWhitespace(inputString); if (!inputString.length) { return token; } if (isNumber(inputString[0])) { String start = inputString; advance(inputString); while (isNumber(inputString[0])) { advance(inputString); } if (inputString[0] == '.') { token.kind = KOMMA; advance(inputString); while (isNumber(inputString[0])) { advance(inputString); } start.length = inputString.data - start.data; token.floatValue = parseFloat(start); } else { start.length = inputString.data - start.data; token.kind = INTEGER; token.intValue = parseInteger(start); } //Token für mathematische Operatoren //ergänzt werden müssen: "atan2" } else if (inputString[0] == '+') { token.kind = PLUS; advance(inputString); } else if (inputString[0] == '-') { token.kind = MINUS; advance(inputString); } else if (inputString[0] == '*') { token.kind = MUL; advance(inputString); } else if (inputString[0] == '/') { token.kind = DIV; advance(inputString); } else if (inputString[0] == '%') { token.kind = MODULO; advance(inputString); } else if (inputString[0] == '(') { token.kind = LPAREN; advance(inputString); } else if (inputString[0] == ')') { token.kind = RPAREN; advance(inputString); } else if (inputString[0] == '^') { token.kind = POW; advance(inputString); } else if (starts_with(inputString, "atan2"_str)) { token.kind = ATAN2; advance(inputString, 5); } else if (starts_with(inputString, "atan"_str)) { token.kind = ATAN; advance(inputString, 4); } else if (starts_with(inputString, "sqrt"_str)) { token.kind = SQRT; advance(inputString, 4); } else if (starts_with(inputString, "sin"_str)) { token.kind = SIN; advance(inputString, 3); } else if (starts_with(inputString, "cos"_str)) { token.kind = COS; advance(inputString, 3); } else if (starts_with(inputString, "tan"_str)) { token.kind = TAN; advance(inputString, 3); } else if (starts_with(inputString, "ans"_str)) { token.kind = ANS; advance(inputString, 3); } return token; } double parseExpression(String &string); Token token = {}; double ans = 0; jmp_buf Rechner; #define expect(k) if(token.kind != (k)) { printf("Unexpected Token"); exit(0); } token = getNextToken(input); double parseExpressionOperand(String& input) { if (token.kind == INTEGER) { long value = token.intValue; token = getNextToken(input); return value; } else if (token.kind == KOMMA) { double value = token.floatValue; token = getNextToken(input); return value; } else if (token.kind == LPAREN) { token = getNextToken(input); double expression = parseExpression(input); expect(RPAREN); return expression; } else if (token.kind == SQRT) { token = getNextToken(input); return sqrt(parseExpressionOperand(input)); } else if (token.kind == SIN) { token = getNextToken(input); return sin(parseExpressionOperand(input)); } else if (token.kind == COS) { token = getNextToken(input); return cos(parseExpressionOperand(input)); } else if (token.kind == TAN) { token = getNextToken(input); return tan(parseExpressionOperand(input)); } else if (token.kind == ATAN) { token = getNextToken(input); return atan(parseExpressionOperand(input)); } else if (token.kind == ATAN2) { printf("Coming soon!"); return 0; } else if (token.kind == ANS) { token = getNextToken(input); return ans; } printf("Unexpected Token.\n"); longjmp(Rechner, 0); return 0; } double parseExpressionUnary(String& input) { if (token.kind == MINUS) { token = getNextToken(input); return -parseExpressionUnary(input); } return parseExpressionOperand(input); } double parseExpressionPower(String& input) { double expression = parseExpressionUnary(input); while (token.kind == POW) { token = getNextToken(input); expression = pow(expression, parseExpressionUnary(input)); } return expression; } double parseExpressionMultiplicative(String& input) { double expression = parseExpressionPower(input); while (token.kind == MUL || token.kind == DIV) { if (token.kind == MUL) { token = getNextToken(input); expression = expression * parseExpressionPower(input); } else if (token.kind == DIV) { token = getNextToken(input); expression = expression / parseExpressionPower(input); } } return expression; } double parseExpressionAdditive(String& input) { double expression = parseExpressionMultiplicative(input); while (token.kind == PLUS || token.kind == MINUS) { if (token.kind == PLUS) { token = getNextToken(input); expression = expression + parseExpressionMultiplicative(input); } else if (token.kind == MINUS) { token = getNextToken(input); expression = expression - parseExpressionMultiplicative(input); } } return expression; } double parseExpression(String &input) { return parseExpressionAdditive(input); } void write_entire_file(const char* filename, String s){ FILE* file = fopen(filename, "w"); fwrite(s.data, s.length, 1, file); fclose(file); } String helpstring = R"( Taschenrechner --- Help Operator: - Addition 'Ausdruck' + 'Ausdruck' - Subtraktion 'Ausdruck' - 'Ausdruck' - Multiplikation 'Ausdruck' * 'Ausdruck' - Division 'Ausdruck' / 'Ausdruck' - Potenzen 'Ausdruck' ^ 'Ausdruck' Klammern: ('Ausdruck' + 'Ausdruck') * 'Ausdruck' ('Ausdruck' + 'Ausdruck') * ('Ausdruck' - 'Ausdruck') 'Ausdruck' - (('Ausdruck' + 'Ausdruck') * 'Ausdruck') / 'Ausdruck' Trigonometrie: - Wurzel sqrt 'Ausdruck' ODER sqrt('Ausdruck') - Sinus/Cosinus/Tangens sin/cos/tan 'Ausdruck' ODER sin('Ausdruck') Letzte Antwort kann mittels 'ans' genutzt werden. Beispiel: - 4 + 5 9 - ans * 2 18 )"_str; int main() { SetConsoleOutputCP(65001); write_entire_file("Help.txt", helpstring); while (true) { setjmp(Rechner); printf("Was möchten Sie berechnen? Für Hilfe 'help' eingeben!\n"); char buffer[1024]; String input = { 1024, buffer }; fgets(buffer, 1024, stdin); input.length = strlen(buffer); if (starts_with(input, "help"_str) || starts_with(input, "Help"_str)) { printf("%s", helpstring.data); continue; } token = getNextToken(input); ans = parseExpression(input); printf("%g\n", ans); } return 0; }