CSE 109 Final Examination Friday 5 May 2006 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>> 1. Questions 1 and 2 deal with different parts of the same problem. Read both questions before starting. Expressions like *&*a.b()->c.gg().e.f are syntactically correct in C++ and satisfy the following syntax diagrams for A, where () denotes ovals and [] denotes boxes. X A +-('&')--[A]--+ --[Y]----+------------------> ------|-('*')--[A]--|---> ^ | +--('->')--+ +--[X]--------+ | +-->| |--[Y]-+ Y +-----------------+ | +--('.')---+ | ----(Ident)----| |--> +-<----------------<-----+ +--('(')--(')')---+ (where, although not relevant to this question, Ident is a sequence of one or more lower case letters). Write a class CParse that gets tokens from a lexical analyzer of type Flex (see question 2) that returns one of the Flex constants AMPERSAND(0), SPLAT(1), IDENT(2), PERIOD(3), ARROW(4), LPAR(5), RPAR(6), EOLN(7), and JUNK(8). The method parse() should determine whether a sequence of tokens from one line of a file satisfies the above syntax. If the line does, then parse() does nothing; if it does not, parse() diagnoses the first error. The following (sloppy) code shows how CParse would be used. int main() {ifstream f("cparse.dat"); CParse p(f); p.parse(); } <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #ifndef CPARSE_H #define CPARSE_H class CParse {public: CParse(istream &in=cin); void parse(); private: void A(); void X(); void Y(); int tok; Flex f; static void check(bool b,char*mess); }; CParse::CParse(istream &in):f(in) {} void CParse::parse() {tok=f.next(); A(); check(tok==Flex::EOLN,"<--End of line expected\n"); } void CParse::A() {switch(tok) {case Flex::AMPERSAND: case Flex::SPLAT: tok=f.next(); A(); break; default: X(); } } void CParse::X() {Y(); while(tok==Flex::PERIOD || tok==Flex::ARROW) {tok=f.next(); Y(); } } void CParse::Y() {check(tok==Flex::IDENT," Ident, '*', or '&' expected"); tok=f.next(); if(tok==Flex::LPAR) {tok=f.next(); check(tok==Flex::RPAR," ')' expected"); tok=f.next(); } } void CParse::check(bool b, char *mess) {if(!b) {cout<<"<-- ERROR: "<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2. Write a class Flex that acts as a lexical analyzer for CParse above. Class Flex can assume that the header for the class Scan we developed for p3 is stored in scan.h. Calls to the Flex method next() should echo to the console each character it gets from Scan. Note that an Ident is a sequence of one or more lowercase letters. Also, recall that scan has the following methods: Scan(istream &in=cin); char next(); void newLine(); void reset(); bool good()const; A (sloppy) program that uses Flex might look like: int main() {int sym; ifstream f("flex.dat"); Flex flex(f); sym=flex.next(); while(sym!=Flex::EOLN) {cout<='a' && ch<='z') {while(ch>='a'&&ch<='z') {cout<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 3. Write a C program (compiled with "gcc -xc") that writes out a message to the console stating whether two strings entered on the command line name the same file or name two files with duplicate contents or name two files with different contents. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #include void check(int b,char *messa,char *messb,char *messc); int dup(char*a,char*b); int main(int ct,char**arg) {check(ct==3,"Usage: ",arg[0]," "); if(strcmp(arg[1],arg[2])==0) printf("Same file\n"); else if(dup(arg[1],arg[2])) printf("Duplicate files\n"); else printf("Neither the same file nor duplicate files\n"); } void check(int b,char *messa,char *messb,char *messc) {if(!b) {fprintf(stderr,"%s%s%s\n",messa,messb,messc); exit(1); } } int dup(char*a,char*b) {FILE *fa,*fb; char ach,bch; fa=fopen(a,"r"); check(fa!=NULL," Failure to open '",a,"'"); fb=fopen(b,"r"); check(fb!=NULL," Failure to open '",b,"'"); ach=getc(fa); bch=getc(fb); while(!feof(fa) && !feof(fb) && ach==bch) {ach=getc(fa); bch=getc(fb); } return feof(fa) && feof(fb); } >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 4. Before answering this question read question 5, a related question. Write the declaration and definition (code) for the class LUAcc which is meant to store information for LTS user accounts: the first name, the last name, and the user identifier. It should have sufficient functionality so that the code below produces the indicated output. Your class need only store the first 15 characters of a name, discarding the rest, and can assume all user identifiers have six or fewer characters. LUAcc x("Tom", "Mix", "TM203"); cout<=0 && var<=2,"Bad choice in set()"); switch(var) {case 0: copy(fname,c,15); break; case 1: copy(lname,c,15); break; case 2: copy(email,c,6); break; } } const char * LUAcc::get(int var)const {check(var>=0 && var<=2,"Bad choice in set()"); switch(var) {case 0: return fname; case 1: return lname; case 2: return email; } return ""; //keep the compiler happy } void LUAcc::check(bool b, char *mess) {if(!b) {cerr<<"ERROR: "<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 5. Write a subclass of LUAcc, called LUAX, which adds the ability to store upto 10 aliases for the user ID (an improvement of LTS's policy of enabling one alias). The class LUAX should have sufficient functionality so that the code below produces the indicated output. Your class need only store the first nine characters of an alias, discarding the rest (similar to unix on the department machines which only uses the first eight characters of a password). LUAX y("Tom", "Mix", "TM204"); y+="Hellion"; y+="Filly"; cout<0) out<<", "; out<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 6. Write the template for a class ShowRay which is intended to save the reference to an array of some type and then display (parts of) the array to the screen in various formats. The code below indicates how the templated class should behave. int y[10]; ShowRay sy(y); for(int j=0;j<10;j++) y[j]=j*j+6; sy.show(3,6,'[',']','|');//show y[3]..y[6] surrounded by [] and separated by | //[ 15| 22| 31| 42] sy.show(6,7,'{','}',','); //show y[6], y[7], surrounded by by {} and separated by , //{ 42, 55} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #include using namespace std; template class ShowRay {public: ShowRay(X * r); void show(int j, int k,char left='[', char right=']',char sep=','); private: X *ray; }; template ShowRay::ShowRay(X *r):ray(r){} template void ShowRay::show(int j, int k, char left, char right, char sep) {cout<j) cout<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 7. Write the MACH1 code that would be generated by an assembler for MCASM programs when the assembler parses and generates code for the MCASM program below. read x read y write x-x*y halt end Hint: Recall the MACH1 code: read(0), write(1), load(2), store(3), clear(4), add(5), sub(6), mult(7), div(8), addi(9), subi(10), multi(11), divi(12), lte(13), gte(14), halt(15). <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 0 0 0 3 19 1 read x 0 0 2 3 20 3 read y 2 19 4 3 511 5 push x 2 19 6 3 510 7 push x 2 20 8 3 509 9 push x 2 510 10 load copy of x from stack 7 509 11 mult by stack copy of y 3 510 12 push x*y onto stack 2 511 13 load copy of x from stack 6 510 14 subtract x*y 3 511 15 store x-x*y on stack 2 511 16 1 0 17 write x-x*y 15 0 E >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 8. Write out the output that occurs at the "dashed lines" for the C++ program below. #include using namespace std; class A {public: A(int j=0):val(j){} virtual void x(){val++;} void y(){val+=2;} void z(){x(); y();} int val; }; class B: public A {public: B(int j=5){} void x(){val+=3;} void y(){val+=4;} }; void x(int a, int *b, int **c) {a=42; *b=6; *c=b; (**c)+=5; } int main() {A a(5); a.z(); cout<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>