1 #include "../../st.h"
2
3 class Roman_int{
4 public:
5 int as_int(string s);
6 int re_int(){return i;}
7 char re_kind(){return ch;}
8 Roman_int()
9 :i(0){}
10 Roman_int(char c)
11 :ch(c),i(0){}
12 Roman_int(char c,int ii)
13 :ch(c),i(ii){}
14 private:
15 int i;
16 char ch;
17 };
18
19 string as_roman(int i)
20 {
21 if(i<1||i>>3999)
22 error("over range 1~3999");
23 string digits[10] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
24 string tens[10] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
25 string hundreds[10] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
26 string thousands[4] = {"", "M", "MM", "MMM"};
27
28 string ss="";
29 ss+=thousands[i/1000];
30 ss+=hundreds[i%1000/100];
31 ss+=tens[i%100/10];
32 ss+=digits[i%10];
33
34 return ss;
35 }
36
37 int Roman_int::as_int(string s)
38 {
39 int b[100];
40 int sum=0;
41 int i1=0,sum1=0;
42 for(i1=0;i1<s.size();i1++)
43 {
44 switch(s[i1])
45 {
46 case 'I':b[i1]=1,sum1++;continue;
47 case 'V':b[i1]=5,sum1++;continue;
48 case 'X':b[i1]=10,sum1++;continue;
49 case 'L':b[i1]=50,sum1++;continue;
50 case 'C':b[i1]=100,sum1++;continue;
51 case 'D':b[i1]=500,sum1++;continue;
52 case 'M':b[i1]=1000,sum1++;continue;
53 default: break;
54 }
55 }
56 if(sum1==1)
57 sum=b[0];
58 else
59 {
60 sum=0;
61 for(i1=0;i1<sum1;i1++)
62 {
63 if(b[i1]>=b[i1+1])
64 sum=sum+b[i1];
65 else
66 {
67 sum=sum+(b[i1+1]-b[i1]);
68 i1++;
69 }
70 }
71 }
72 i=sum;
73 return sum;
74 }
75
76 istream& operator>>(istream&is,Roman_int&ri)
77 {
78 string s;
79 is>>s;
80 ri.as_int(s);
81 return is;
82 }
83
84 ostream& operator<<(ostream&os,Roman_int&ri)
85 {
86 return os<<ri.re_int();
87 }
88
89 class Token_stream{
90 public:
91 Token_stream();
92 Roman_int get();
93 Roman_int get(istream&);
94 void putback(Roman_int ri);
95 private:
96 bool full;
97 Roman_int buffer;
98 };
99
100 Token_stream::Token_stream()
101 :full(false),buffer(0)
102 {
103 }
104
105 void Token_stream::putback(Roman_int t)
106 {
107 if(full) error("putback() into a full buffer");
108 buffer=t;
109 full=true;
110 }
111
112 Roman_int Token_stream::get(istream&ifs)
113 {
114 if(full){
115 full=false;
116 return buffer;
117 }
118 char ch;
119 ifs>>ch;
120 switch(ch){
121 case ';': case 'q': case '(': case ')': case '{':
122 case '}': case '+': case '-': case '*': case '/':
123 return Roman_int(ch);
124 case 'I': case 'V': case 'X':
125 case 'C': case 'D': case 'M':
126 {
127 string s="";
128 s+=ch;
129 while(ifs>>ch)
130 {
131 if(ch=='I'||ch=='V'||ch=='X'||ch=='C'||ch=='D'||ch=='M')
132 s+=ch;
133 else
134 {
135 ifs.putback(ch);
136 break;
137 }
138 }
139 Roman_int r('8');
140 r.as_int(s);
141 return r;
142 }
143 case 'f':
144 while(cin.get(ch)&&isalpha(ch))
145 ;
146 cin.putback(ch);
147 return Roman_int('f');
148 case 't':
149 while(cin.get(ch)&&isalpha(ch))
150 ;
151 cin.putback(ch);
152 return Roman_int('t');
153 default:
154 error("bad token");
155 }
156 }
157
158 Token_stream ts;
159 double expression(istream&ifs);
160
161 double primary(istream&ifs)
162 {
163
164 Roman_int t=ts.get(ifs);
165 switch(t.re_kind()){
166 case '(':
167 {
168 int d=expression(ifs);
169 t=ts.get(ifs);
170 if(t.re_kind()!=')')
171 error("')'expected");
172 return d;
173 }
174 case '8':
175 return t.re_int();
176 default:
177 error("primary expected",t.re_kind());
178 }
179 }
180
181 double primary1(istream&ifs)
182 {
183 Roman_int t=ts.get(ifs);
184 while(true)
185 {
186 switch(t.re_kind()){
187 case '{':
188 {
189 double d=expression(ifs);
190 t=ts.get(ifs);
191 if(t.re_kind()!='}')
192 error("'}'expected");
193 return d;
194 }
195 default:
196 ts.putback(t);
197 return primary(ifs);
198 }
199 }
200 }
201
202 double term(istream&ifs)
203 {
204 double left=primary1(ifs);
205 Roman_int t=ts.get(ifs);
206
207 while(true){
208 switch(t.re_kind()){
209 case '*':
210 left*=primary1(ifs);
211 t=ts.get(ifs);
212 break;
213 case '/':
214 {
215 double d=primary1(ifs);
216 if(d==0)
217 error ("divide by 0");
218 left /=d;
219 t=ts.get(ifs);
220 break;
221 }
222 default:
223 ts.putback(t);
224 return left;
225 }
226 }
227 }
228
229 double expression(istream&ifs)
230 {
231 double left=term(ifs);
232 Roman_int t=ts.get(ifs);
233 while(true){
234 switch(t.re_kind()){
235 case '+':
236 left+=term(ifs);
237 t=ts.get(ifs);
238 break;
239 case '-':
240 left-=term(ifs);
241 t=ts.get(ifs);
242 break;
243 default:
244 ts.putback(t);
245 return left;
246 }
247 }
248 }
249
250 int main()
251 {
252 try{
253 double val=0;
254 Roman_int t;
255 while(cin)
256 {
257 t=ts.get(cin);
258
259
260 if(t.re_kind()=='f')
261 {
262 double val1=0;
263 string s;
264 cin>>s;
265 ifstream ifs(s.c_str());
266 if(!ifs)
267 error("can not open input file1",s);
268 t=ts.get(cin);
269 if(t.re_kind()=='t')
270 {
271 cin>>s;
272 ofstream ofs(s.c_str());
273 if(!ofs)
274 error("can not open output file1",s);
275 while(ifs)
276 {
277 t=ts.get(ifs);
278 while(t.re_kind()==';')
279 t=ts.get(ifs);
280 if(t.re_kind()=='q')
281 break;
282 ts.putback(t);
283 ofs<<as_roman(expression(ifs))<<endl;
284 }
285 }
286 }
287 else
288 {
289
290 while(t.re_kind()==';')
291 t=ts.get(cin);
292 if(t.re_kind()=='q')
293 {
294 keep_window_open("~~");
295 return 0;
296 }
297 ts.putback(t);
298 cout<<as_roman(expression(cin))<<endl;
299 }
300 }
301 return 0;
302
303 }
304
305 catch(exception&e){
306 cerr<<e.what()<<endl;
307 while(1);
308 return 1;
309 }
310
311 catch(...){
312 cerr<<"exception\n";
313 while(1);
314 return 2;
315 }
316
317 }