package uk.ac.nesc.rph.myCalc5; /* *************************** PREAMBLE ********************* * A modified version of MyCalculator4 in which * the input commands are read from, and their results written to, * named files. * There is an optional second command line argument which is the name * of a working directory (relative to the user's home directory) within which * the input and output files reside. If this argument is omitted * the working directory is the home directory. * The names of the files relative to the working directory are * input on the standard input. * There are two additional methods: one for obtaininng the input file name and * the other for obtaining the output file name. * The changed parts of the main method have comments //!!! * ********************** END ******************************* * ********************** PREAMBLE ****************************************8 */ import java.io.*; // /** Provides Exception for IntegerVariable Interface*/ class uninitialized extends Exception {static final long serialVersionUID = 2; } /** This is for any class whose instances maintain an integer value * which can be manipulated through its set and get methods*/ interface IntegerVariable { int get()throws uninitialized; int set(int value);} /** Maintains a running integer value, initially 0, which can be incremented and reSet * and accessed using methods incr, reSet and get respectively * @author Richard Hopkins * */ class Accumulator { int total; static int uses=0; //to keep count of number of accumulator operations public Accumulator(){total=0;} //constructor public int incr(int i){++uses; total= total+i ; return total;}//increment public int reSet(int r){uses++; return total=r;} public int get(){return total;} } /** Maintains a running integer value which can be incremented, decremented, set * and accessed using methods incr, decr, set and get respectively. * @author Richard Hopkins * */ class AccMKII extends Accumulator implements IntegerVariable { public AccMKII(int initialTotal) //new constructor {total=initialTotal;} public AccMKII() //re-implemented constructor {this(0);} public int decr(int i) // new operation {uses++;total=total-i;return total;} public int incr(int i) //re-implemented operation {return this.decr(-i) ;} public int set(int r) //new operation {uses+=1;return total=r;} } class userQuit extends Exception //exception for MyCalculator {static final long serialVersionUID = 2; }; class UIError extends Exception // exception for MyCalculator {static final long serialVersionUID = 2; String anErrorMess = "No Comment"; UIError(String s){anErrorMess=s;} public String getMessage() {return anErrorMess;} } /** This application provides a number of accumulator objects (class AccMKII), * and implements an input language for operating on them. * This version now has file input and output. * @author Richard Hopkins * */ public class MyCalculator5 { //!! static File setUpInFile( String SandBox, //name of working directory BufferedReader br) //source of user input throws IOException { File fIn; //result file String in1; while (true) { System.out.println("type input file name (default in.txt)"); in1=br.readLine(); if (in1.length()<1) in1="in.txt"; if (in1.indexOf("..")>-1) {System.out.println("'..' parent selector not allowed - try again");continue;} fIn= new File(SandBox,in1); if (!(fIn.exists())) {System.out.println("Input file - " +fIn.getAbsolutePath()+" - non-existent, try again"); continue;} if (fIn.isDirectory()) {System.out.println("Input file - " +fIn.getAbsolutePath()+" - is a directory/folder, try again"); continue;} if (!(fIn.canRead())) {System.out.println("Input file - " +fIn.getAbsolutePath()+" - can't read, try again"); continue;} System.out.println("Input file - "+fIn.getAbsolutePath()); break;} return fIn; }// end SetUpInFile static File setUpOutFile( String SandBox, //name of working directory BufferedReader br) //source of user input throws IOException { File fOut; //The result file String in1; while (true) {System.out.println("type output file name (default out.txt)"); in1=br.readLine(); if (in1.length()<1) in1="out.txt"; if (in1.indexOf("..")>-1) {System.out.println("'..' parent selector not allowed - try again");continue;} fOut= new File(SandBox,in1); try { if (fOut.createNewFile()) {System.out.println("output file created - "+fOut.getAbsolutePath()); break;} {System.out.println("Output file - "+fOut.getAbsolutePath()+ "- exists. type \"y\" if OK to overwrite"); String in2=br.readLine(); if (in2.length()>0 && (in2.toCharArray())[0]=='y') {System.out.println("using existing file"); break;} System.out.println("try again"); continue;} }catch (IOException ioErr) {System.out.println("output file exception - "+fOut.getAbsolutePath()+ ioErr.getMessage()); continue;} } return fOut;} //ed of SetUpOutFile public static void main(String[] args) throws IOException { // ****** Initialisation int size; // try{size= Integer.parseInt(args[0]);}//size of accumulator array catch (java.lang.NumberFormatException e1) {System.out.println("MyCalculator4: Argument error"); return;} if (size>26) size=26; else if (size < 1) // {System.out.println("MyCalculator4: Argument error"); return;} Accumulator [] accs = new Accumulator [size]; for ( int i=0 ; i 1 ? home+File.separator+args[1]: home); fIn = setUpInFile(SandBox,br); fOut = setUpOutFile(SandBox,br); System.out.println("thank you - we can now proceed"); FileReader fr = new FileReader(fIn); BufferedReader fileInputter = new BufferedReader(fr); FileWriter fw = new FileWriter(fOut); PrintWriter fileOutputter = new PrintWriter(fw); // ****** Main Loop // *** Reading Input Command char c1, c2, c3; //The three input characters for a command String input; //The whole input line //!!! char [] ca; // The characters to be processed int p1, p2=0; //The two parameters of a command boolean isLiteral=false; //whether parameter 2 is a literal //!! while ((input =fileInputter.readLine())!= null) { //!!! ca=input.toCharArray(); try { if (ca.length<3) throw new UIError("Input less than 3 characters");// c1= ca[0]; c2=ca[1]; c3=ca[2];// char[]ca3={c1,c2,c3}; ca=ca3;// select the first three characters p1= c1-'A'; //the index of the accumulator identifed by first param if (p1<0 || p1>=size)throw new UIError("Input 1 out of range"); // if (('A' <= c3) && (c3 <= 'Z')) {p2= c3-'A'; isLiteral=false; if (p2>=size)throw new UIError("Input 3 out of range"); // } else if (('0' <= c3) && (c3 <= '9')) {p2= c3-'0' ; isLiteral=true;} else throw new UIError("Input 3 out of range"); // if (!(c2=='+' || c2=='-' || c2== '?' || c2=='=')) // throw new UIError("Input 2 out of range"); // *** Doing the requested action int v2, v3=0; //values of second operand and result boolean show=false; // whether there is a result to show AccMKII target = (AccMKII) accs[p1]; v2=(isLiteral ? p2 : accs[p2].get()); switch (c2){ case '+' : v3=target.incr(v2); show=true; break; case '-' : v3=target.decr(v2); show=true; break; case '=' : v3=target.set(v2); show=true; break; case '?' : String s = ""; do { s=s+"["+c1+"]="+accs[p1].get()+" "; p1++; c1++; }while (p1 <= p2); fileOutputter.println(s); show = false; break; } if (show) fileOutputter.println(String.copyValueOf(ca)+"//"+ Accumulator.uses+")----------> ["+c1+"]= "+v3); //!!! }catch (UIError e1) // {fileOutputter.println("**ERROR//" +String.copyValueOf(ca)+ //!!! "// input error: "+e1.getMessage()); System.out.println("**ERROR//" +String.copyValueOf(ca)+ //!!! "// input error: "+e1.getMessage());} fileOutputter.flush(); }// end of main loop; System.out.println("Done"); fileInputter.close(); fileOutputter.close(); //!! } } // end of Class MyCalculator5