实验程序是用vc6编译,一定注意文件扩展名为c,不是cpp,在下载:
注意事项和遇到的问题都已经在实现程序注释中,如下:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "include/stack.h"
#include "include/ap.h"
#include "include/fmt.h"
#include <limits.h>
#include "include/mem.h"
#include "include/seq.h"
#include "include/mp.h"
#pragma comment(lib, "libcii.lib")
Seq_T sp;
int ibase = 10;
int obase = 10;
struct {
char *fmt;
MP_T (*add)(MP_T, MP_T, MP_T);
MP_T (*sub)(MP_T, MP_T, MP_T);
MP_T (*mul)(MP_T, MP_T, MP_T);
MP_T (*div)(MP_T, MP_T, MP_T);
MP_T (*mod)(MP_T, MP_T, MP_T);
} s = { "%D\n",
MP_add, MP_sub, MP_mul, MP_div, MP_mod },
u = { "%U\n",
MP_addu, MP_subu, MP_mulu, MP_divu, MP_modu },
*f = &s;
MP_T pop(void) {
if (Seq_length(sp) > 0)
return Seq_remhi(sp);
else {
Fmt_fprint(stderr, "?stack underflow\n");
return MP_new(0);
}
}
int main(int argc, char *argv[]) {
int c;
sp = Seq_new(0);
Fmt_register('D', MP_fmt);
Fmt_register('U', MP_fmtu);
while ((c = getchar()) != EOF) {
MP_T x = NULL, y = NULL, z = NULL;
TRY
switch (c) {
default:
if (isprint(c))
Fmt_fprint(stderr, "?'%c'", c);
else
Fmt_fprint(stderr, "?'\\%03o'", c);
Fmt_fprint(stderr, " is unimplemented\n");
break;
case ' ': case '\t': case '\n': case '\f': case '\r':
break;
case 'c': while (Seq_length(sp) > 0) {
MP_T x = Seq_remhi(sp);
FREE(x);
} break;
case 'q': while (Seq_length(sp) > 0) {
MP_T x = Seq_remhi(sp);
FREE(x);
}
Seq_free(&sp);
return EXIT_SUCCESS;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
char buf[512];
z = MP_new(0);
{
int i = 0;
for ( ; strchr(&"zyxwvutsrqponmlkjihgfedcba9876543210"[36-ibase],
tolower(c)); c = getchar(), i++)
if (i < (int)sizeof (buf) - 1)
buf[i] = c;
if (i > (int)sizeof (buf) - 1) {
i = (int)sizeof (buf) - 1;
Fmt_fprint(stderr,
"?integer constant exceeds %d digits\n", i);
}
buf[i] = '\0';
if (c != EOF)
ungetc(c, stdin);
}
MP_fromstr(z, buf, ibase, NULL);
break;
}
case '+': y = pop(); x = pop();
z = MP_new(0); (*f->add)(z, x, y); break;
case '-': y = pop(); x = pop();
z = MP_new(0); (*f->sub)(z, x, y); break;
case '*': y = pop(); x = pop();
z = MP_new(0); (*f->mul)(z, x, y); break;
case '/': y = pop(); x = pop();
z = MP_new(0); (*f->div)(z, x, y); break;
case '%': y = pop(); x = pop();
z = MP_new(0); (*f->mod)(z, x, y); break;
case '&': y = pop(); x = pop();
z = MP_new(0); MP_and(z, x, y); break;
case '|': y = pop(); x = pop();
z = MP_new(0); MP_or (z, x, y); break;
case '^': y = pop(); x = pop();
z = MP_new(0); MP_xor(z, x, y); break;
case '!': z = pop(); MP_not(z, z); break;
case '~': z = pop(); MP_neg(z, z); break;
case 'i': case 'o': {
long n;
x = pop();
n = MP_toint(x);
if (n < 2 || n > 36)
Fmt_fprint(stderr, "?%d is an illegal base\n",n);
else if (c == 'i')
ibase = n;
else
obase = n;
if (obase == 2 || obase == 8 || obase == 16)
f = &u;
else
f = &s;
break;
}
case 'p':
Fmt_print(f->fmt, z = pop(), obase);
break;
case 'f': {
int n = Seq_length(sp);
while (--n > 0)
Fmt_print(f->fmt, Seq_get(sp, n), obase);
break;
}
case '<': { long s;
y = pop();
z = pop();
s = MP_toint(y);
if (s < 0 || s > INT_MAX) {
Fmt_fprint(stderr,
"?%d is an illegal shift amount\n", s);
break;
}; MP_lshift(z, z, s); break; }
case '>': { long s;
y = pop();
z = pop();
s = MP_toint(y);
if (s < 0 || s > INT_MAX) {
Fmt_fprint(stderr,
"?%d is an illegal shift amount\n", s);
break;
}; MP_rshift(z, z, s); break; }
case 'k': {
long n;
x = pop();
n = MP_toint(x);
if (n < 2 || n > INT_MAX)
Fmt_fprint(stderr,
"?%d is an illegal precision\n", n);
else if (Seq_length(sp) > 0)
Fmt_fprint(stderr, "?nonempty stack\n");
else
MP_set(n);
break;
}
case 'd': {
MP_T x = pop();
z = MP_new(0);
Seq_addhi(sp, x);
MP_addui(z, x, 0);
break;
}
}
EXCEPT(MP_Overflow)
Fmt_fprint(stderr, "?overflow\n");
EXCEPT(MP_Dividebyzero)
Fmt_fprint(stderr, "?divide by 0\n");
END_TRY;
if (z)
Seq_addhi(sp, z);
FREE(x);
FREE(y);
}
while (Seq_length(sp) > 0) {
MP_T x = Seq_remhi(sp);
FREE(x);
}
Seq_free(&sp);
return EXIT_SUCCESS;
}