CSE 109 FINAL EXAMINATION Wednesday 10 December 2008 ==============================SUGGESTED ANSWERS===================== 1. Write a program that expects the names of three files (other than the name of the executable file) on the command line, that copies the contents of the first file into the third file, and then copies the contents of the second file into the third file. The third file should end up with the contents of the first file, followed by the contents of the second file. =========================================================================== #include #include using namespace std; void check(bool b, char *mess){ if(!b){ cerr<<"ERROR: "< #include using namespace std; class Lex{ public: Lex(istream&in); char next(); private: istream *fin; }; Lex::Lex(istream &in):fin(&in){} char Lex::next(){ char ch; ch=fin->get(); cout<good()) return '#'; switch (ch){ case 'a': case 'A': return 'a'; case 'b': case 'B': return 'b'; case 'c': case 'C': return 'c'; default: return '#'; } } =========================================================================== 3. Assume that you have the class Lex from question 2. Write a function parse() (that calls other functions and) determines whether the contents of a file satisfy the syntax of the diagrams for EXP below. In the diagrams I use parentheses, (), to indicate circles, and square brackets, [], to indicate rectangles. Next to the diagrams is a sample call to parse(). Note that if the syntax is violated you should write an error message and exit the program so that the last line of main() will only execute if the parse succeeds. void check(bool b,char *mess){ if(!b){ EXP ----->(a)---(b)--[A]-+ cerr<<"ERROR: "< } | | } +-(c)------+ int main(){ A ifstream f("aFile"); -->(a)--(b)-----------------+ check(f.good(),"Failure to open 'aFile'"); | ^ | | Lex lex(f); | | | | char ch; | +-[EXP]-(b)<--+ | ch=lex.next(); | | parse(lex,ch); +--(a)--->[A]--------| cout<<"Successful parse\n"; V } =========================================================================== void parse(Lex &lex,char& ch); void EXP(Lex &lex,char &ch); void A(Lex &lex,char &ch); void B(Lex &lex,char& ch); void parse(Lex &lex,char &ch){EXP(lex,ch);} void EXP(Lex &lex,char &ch){ check(ch=='a'," 'a' expected"); ch=lex.next(); switch(ch){ case 'a': case 'b': ch=lex.next(); A(lex,ch); break; case 'c': ch=lex.next(); break; default: check(false,"'a', 'b', or 'c' expected"); } check(ch=='#',"'#' expected"); ch=lex.next(); } void A(Lex &lex,char &ch){ check(ch=='a'," 'a' expected"); ch=lex.next(); switch(ch){ case 'a': ch=lex.next(); A(lex,ch); break; case 'b': ch=lex.next(); while(ch=='b'){ ch=lex.next(); EXP(lex,ch); } break; default: check(false," 'a' or 'b' expected"); } } =========================================================================== 4. Write the STKM code that would be generated by a program that used the techniques discussed in class to generate code for programming assignment #7 and that had the following STKMASM++ program as input. read x write 2+(x-3)*(x-4/x) halt end 7 Recall the opcodes for STKM: Read(10), Write(11), Push(20), Pop(21), Add(30), Sub(31), Div(32), Mul(33), Branch(40), BranchLess(41), BranchEqual(42), Halt(43). =========================================================================== 10016 read x 20017 push 2 20016 push x 20018 push 3 31000 sub 3 20016 push x 20019 push 4 20016 push x 32000 div x 31000 sub 4/x 33000 mul x-4/x 30000 add (x-3)*(x-4/x) 21000 pop 11000 write zero 43000 halt 0 x [16] 2 [17] 3 [18] 4 [19] END 7 =========================================================================== 5. Write a C (not C++) program that (1) when stored in prog.cc will compile and run with the command "gcc -xc prog.cc"; (2) reads in from the console 20 ints, stores them in an array, and then displays them in reverse order on the screen; and (3) has a main program that calls one function to fill the array and calls a second function to write out the array. =========================================================================== void getData(int x[]); void display(int x[]); int main(){ int data[20]; getData(data); display(data); } void getData(int x[]){ int j; for(j=0;j<20;j++) scanf(" %d ",&x[j]); } void display(int x[]){ int j; for(j=19;j>=0;j--) printf(" %d",x[j]); } =========================================================================== 6. Write the template for a class that implements the ADT for a "safe variable." A safe variable requires that a value be assigned to it before it is accessed. Your template need only have the functionality needed for the program below to compile and run as indicated. int main(){ Safe d; //cout< #include using namespace std; template class Safe{ public: Safe(); void set(const X &d); X get()const; template friend ostream & operator<<(ostream &out,const Safe & s); protected: X data; bool good; static void check(bool b, char *mess); }; template Safe::Safe():good(false){} template void Safe::set(const X &d){ data=d; good=true; } template X Safe::get()const{ check(good," Undefined variable"); return data; } template ostream & operator<<(ostream &out,const Safe & s){ s.check(s.good," Undefined variable"); out<<"Safe("< void Safe::check(bool b, char *mess){ if(!b){ cerr<<"ERROR: "< from question 6, write the declaration and definition for a subclass, SafeBool, of Safe, that has the functionality needed for the program below to compile and to produce the indicated output. int main(){ SafeBool a(true), b(a), c; c.set(false); cout<child[0]==NULL && rt->child[1]==NULL)) return true; if(rt->child[0]==NULL) return rt->key<=rt->child[1]->key && inOrder(rt->child[1]); if(rt->child[1]==NULL) return rt->key>=rt->child[0]->key && inOrder(rt->child[0]); return rt->key>=rt->chuild[0]->key && rt->key<=rt->chuild[1]->key && inOrder(rt->child[0]) && inOrder(rt->child[1]); } ============================================================================