实验程序是用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; }