2024-01-05 12:04
BullseyeCoverage 9.6.4
calc/ CalcCore.cpp
1 // Calculator core logic
2
3 #include "CalcCore.h"
4 #include <assert.h>
5 #include <math.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 // Perform unit tests
11 void CalcCore::unitTest()
12 {
13 CalcCore core;
14 core.apply();
15 assert(strcmp(core.display(), "0") == 0);
16 core.addNumber(1.2);
17 assert(strcmp(core.display(), "1.2") == 0);
18 core.apply(Operation::add);
19 core.addNumberChar('3');
20 core.addNumberChar('.');
21 core.addNumberChar('4');
22 assert(strcmp(core.display(), "3.4") == 0);
23 core.apply();
24 assert(strcmp(core.display(), "4.6") == 0);
25 core.apply(Operation::divide);
26 core.addNumber(0);
27 core.apply();
28 assert(strcmp(core.display(), "divide by zero") == 0);
29 core.clear();
30 core.addNumber(1);
31 core.apply(Operation::add);
32 core.addNumber(9);
33 core.apply(Operation::sqrt);
34 assert(strcmp(core.display(), "3") == 0);
35 core.apply();
36 assert(strcmp(core.display(), "4") == 0);
37 }
38
39 // Enter the next character of a number
40 void CalcCore::addNumberChar(char c)
41 {
42 strncat_s(m_input, sizeof(m_input), &c, 1);
43 m_displayOperand = strtod(m_input, nullptr);
44 }
45
46 // Apply any pending operation
47 void CalcCore::apply()
48 {
49 if (m_operation != Operation::none) {
50 compute();
51 }
52 m_enteredOperand = 0;
53 m_input[0] = 0;
54 }
55
56 // Apply any pending operation and prepare for another operation
57 void CalcCore::apply(Operation operation)
58 {
59 switch (operation) {
60 case Operation::negate:
61 m_displayOperand = -m_displayOperand;
62 break;
63 case Operation::pow2:
64 m_displayOperand *= m_displayOperand;
65 break;
66 case Operation::sqrt:
67 m_displayOperand = sqrt(m_displayOperand);
68 break;
69 default:
70 if (m_operation != Operation::none) {
71 compute();
72 }
73 m_enteredOperand = m_displayOperand;
74 m_operation = operation;
75 break;
76 }
77 m_input[0] = 0;
78 }
79
80 void CalcCore::clear()
81 {
82 m_input[0] = 0;
83 m_displayOperand = 0.0;
84 m_enteredOperand = 0.0;
85 m_error = nullptr;
86 m_operation = Operation::none;
87 }
88
89 // Compute the pending operation
90 void CalcCore::compute()
91 {
92 switch (m_operation) {
93 case Operation::add:
94 m_displayOperand = m_enteredOperand + m_displayOperand;
95 break;
96 case Operation::subtract:
97 m_displayOperand = m_enteredOperand - m_displayOperand;
98 break;
99 case Operation::multiply:
100 m_displayOperand = m_enteredOperand * m_displayOperand;
101 break;
102 case Operation::divide:
103 if (m_displayOperand == 0) {
104 m_error = "divide by zero";
105 } else {
106 m_displayOperand = m_enteredOperand / m_displayOperand;
107 }
108 break;
109 default:
110 m_error = "unknown operation";
111 break;
112 }
113 }
114
115 // Get the display output
116 const char* CalcCore::display() const
117 {
118 const char* s = m_error;
119 if (m_error == nullptr) {
120 snprintf(m_output, sizeof(m_output), "%g", m_displayOperand);
121 s = m_output;
122 }
123 return s;
124 }