Prosty kalkulator
Cel
Napisanie programu, który pozwoli wpisać użytkownikowi wyrażenie matematyczne, aby je obliczył i wypisał wynik na ekranie. Przykładowo: .
Ze względu na fakt, że zapis może zawierać białe znaki, ale nie musi to dane będą początkowane interpretowane jako ciąg znaków, a dopiero potem program będzie szukał operatorów oraz liczb.
Implementacja
Funkcja pomocnicza
getChar() to funkcja pomocnicza, której działanie polega na pobraniu i usunięciu pierwszego znaku z wyrażenia. Pomoże to nam iterować każdy znak w wyrażeniu dokładnie raz. Jest ona używana przede wszystkim do usunięcia nawiasów z obliczanego wyrażenia.
1 2 3 4 5 | char getChar(string &s) { char t = s[0]; s = s.substr(1, s.length()); return t; } |
1 2 3 4 5 | static char getChar(string s) { char t = s[0]; s = s.Substring(1, s.Length); return t; } |
Wybieranie wyrażeń
Z kolei do pobierania liczby z łańcucha znaków służy funkcja retrieveNum(), której zadanie polega na pobieraniu liczby z łańcucha znaków. Jej działanie opiera się na fakcie, że cyfry są reprezentowane w tablicy ASCII od 48 do 57.
1 2 3 4 5 6 7 8 9 10 11 12 | int retrieveNum(string &s) { int num = 0; if (s[0] == 40) { num = result(s.substr(s.find("(") + 1, s.find(")") - 1)); s = s.substr(s.find(")") + 1); return num; } while (s[0] >= 48 && s[0] <= 57) { num = num * 10 + (getChar(s) - 48); } return num; } |
1 2 3 4 5 6 7 8 9 10 11 12 | static int retrieveNum(string s) { int num = 0; if (s[0] == 40) { num = result(s.Substring(s.IndexOf("(") + 1, s.IndexOf(")") - 1)); s = s.Substring(s.IndexOf(")") + 1); return num; } while (s[0] >= 48 && s[0] <= 57) { num = num * 10 + (getChar(s) - 48); } return num; } |
(2.) Przyjmij, że wczytana liczba to 0. (3. - 7.) W przypadku, gdy zostanie wykryty nawias to (4.) najpierw oblicz wyrażenie w nawiasie. (8.) Jednak, gdy wczytujesz liczby to (9.) dołączaj kolejne cyfry do zmiennej num dopóki (8.) wczytujesz cyfry. (11.) Na koniec zwróć zmienną num.
Wykonywanie działań
Ostatnia funkcja result() spaja cały kod w całość. Za argument przyjmujemy tu wprowadzony łańcuch znaków. Przyjmujemy aktualną wartość wyrażenia równą pierwszemu czynnikowi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | int result(string s) { int w = retrieveNum(s); while (s.length() > 0 && s[0] != 61) { switch (getChar(s)) { case 42: w *= retrieveNum(s); break; case 43: w += retrieveNum(s); break; case 45: w -= retrieveNum(s); break; case 47: w /= retrieveNum(s); break; } } return w; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | static int result(string s) { int w = retrieveNum(s); while (s.Length > 0 && s[0] != 61) { switch (getChar(s)) { case '*': w *= retrieveNum(s); break; case '+': w += retrieveNum(s); break; case '-': w -= retrieveNum(s); break; case '/': w /= retrieveNum(s); break; } } return w; } |
Następnie w pętli, aż do osiągnięcia znaku równości "=" lub do osiągnięcia długości 0 wprowadzonego wyrażenia sprawdzamy pierwszy znak, który będzie rozpoznany jako operator, a następnie przy użyciu funkcji switch określamy co ma zrobić program. Liczbę po operatorze otrzymujemy poprzez wywołanie funkcji retrieveNum().
Na sam koniec funkcja zwraca wartość numeryczną podanego wyrażenia. Takie rozwiązanie pozwala na rekurencyjne wywoływanie funkcji obliczającej co wykorzystujemy pzry obliczaniu wartości w nawiasach.
Testowanie programu
Poniższa funkcja main() wczytuje od użytkownika wyrażenie do obliczenia, a następnie oblicza jego wartość i wypisuje je na ekran.
1 2 3 4 5 6 7 | int main() { string s = ""; cin >> s; cout << result(s) << endl; system("PAUSE"); return 0; } |
1 2 3 4 5 6 | static void Main(string[] args) { Console.WriteLine("Wpisz wyrażenie:"); string s = Console.ReadLine(); Console.WriteLine("Wynik to {0}", result(s)); Console.ReadKey(); } |
Uwaga: Należy zauważyć, że program uwzględnia tylko podstawowe operatory i nie przestrzega zasad wykonywania działań.