-
Notifications
You must be signed in to change notification settings - Fork 0
/
Interpreter.cpp
207 lines (142 loc) · 4.08 KB
/
Interpreter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <string.h>
#include <iostream>
class Thousand;
class Hundred;
class Ten;
class One;
class RNInterpreter {
public:
RNInterpreter(); // ctor for client
explicit RNInterpreter(int)
: thousands{ nullptr }
, hundreds{ nullptr }
, tens{ nullptr }
, ones{ nullptr } {}
// ctor for subclasses, avoids infinite loop
auto Interpret(char*) const -> int; // interpret() for client
virtual auto Interpret(char* input, int& total) -> void
{
// for internal use
auto index = 0;
if (!strncmp(input, nine(), 2)) {
total += 9 * multiplier();
index += 2;
} else if (!strncmp(input, four(), 2)) {
total += 4 * multiplier();
index += 2;
} else {
if (input[0] == five()) {
total += 5 * multiplier();
index = 1;
} else index = 0;
for (auto end = index + 3; index < end; index++)
if (input[index] == one()) total += 1 * multiplier();
else break;
}
strcpy(input, &input[index]);
} // remove leading chars processed
virtual ~RNInterpreter() = default;
protected:
// cannot be pure virtual because client asks for instance
virtual auto one() -> char { return 0; }
virtual auto four() -> char* { return nullptr; }
virtual auto five() -> char { return 0; }
virtual auto nine() -> char* { return nullptr; }
virtual auto multiplier() -> int { return 0; }
private:
RNInterpreter* thousands;
RNInterpreter* hundreds;
RNInterpreter* tens;
RNInterpreter* ones;
};
class Thousand
: public RNInterpreter {
public:
// provide 1-arg ctor to avoid infinite loop in base class ctor
explicit Thousand(int) : RNInterpreter(1) {}
protected:
virtual auto one() -> char override { return 'M'; }
virtual auto four() -> char* override { return ""; }
virtual auto five() -> char override { return '\0'; }
virtual auto nine() -> char* override { return ""; }
virtual auto multiplier() -> int override { return 1000; }
public:
~Thousand() override = default;
};
class Hundred
: public RNInterpreter {
public:
explicit Hundred(int)
: RNInterpreter(1) {}
protected:
virtual auto one() -> char override { return 'C'; }
virtual auto four() -> char* override { return "CD"; }
virtual auto five() -> char override { return 'D'; }
virtual auto nine() -> char* override { return "CM"; }
virtual auto multiplier() -> int override { return 100; }
public:
~Hundred() override = default;
};
class Ten
: public RNInterpreter {
public:
explicit Ten(int)
: RNInterpreter(1) {}
protected:
virtual auto one() -> char override { return 'X'; }
virtual auto four() -> char* override { return "XL"; }
virtual auto five() -> char override { return 'L'; }
virtual auto nine() -> char* override { return "XC"; }
virtual auto multiplier() -> int override { return 10; }
public:
virtual ~Ten() override = default;
};
class One
: public RNInterpreter {
public:
explicit One(int)
: RNInterpreter(1) {}
protected:
virtual char one() override { return 'I'; }
virtual char* four() override { return "IV"; }
virtual char five() override { return 'V'; }
virtual char* nine() override { return "IX"; }
virtual int multiplier() override { return 1; }
public:
virtual ~One() override = default;
};
RNInterpreter::RNInterpreter() :
thousands(new Thousand(1)),
hundreds(new Hundred(1)),
tens(new Ten(1)),
ones(new One(1))
{
// use 1-arg ctor to avoid infinite loop
}
auto RNInterpreter::Interpret(char* input) const -> int
{
auto total = 0;
thousands->Interpret(input, total);
hundreds->Interpret(input, total);
tens->Interpret(input, total);
ones->Interpret(input, total);
return strcmp(input, "") ? 0 : total; // if input was invalid, return 0
}
auto main() -> int
{
using std::cout;
using std::cin;
using std::endl;
char input[20];
RNInterpreter interpreter;
cout << "Enter Roman Numeral: ";
while (cin >> input) {
cout << "interpretation is: "
<< interpreter.Interpret(input)
<< "\nEnter Roman Numeral: ";
}
getchar();
return EXIT_SUCCESS;
}