Week 7: Lecture/tutorial examples
rational number class with exception handling
class Rational {
int num, denom;
Rational(int num, int denom) {
if (denom == 0)
throw new ArgumentException("zero denominator");
this.num = num; this.denom = denom;
}
public static Rational parse(string s) {
string[] a = s.Split('/');
if (a.Length != 2)
throw new ArgumentException("rational must contain one slash");
if (!int.TryParse(a[0], out int num) || !int.TryParse(a[1], out int denom))
throw new ArgumentException("can't parse numerator or denominator");
return new Rational(num, denom);
}
public override string ToString() => @"${num}/${denom}";
public Rational reciprocal() {
if (num == 0)
throw new DivideByZeroException();
return new Rational(denom, num);
}
public static void allReciprocal() {
StreamReader reader;
try {
reader = new StreamReader("numbers");
} catch (FileNotFoundException) {
WriteLine("can't find input file!");
return;
}
try {
while (ReadLine() is string s) {
try {
WriteLine(parse(s).reciprocal());
} catch (ArgumentException e) {
WriteLine("warning: " + e.Message);
} catch (DivideByZeroException) {
WriteLine("warning: can't take reciprocal of zero");
}
}
} finally {
reader.Close();
}
}
}
representing algebraic expressions, continued
abstract class Expression {
static void error() => throw new Exception("parse error");
static char next(TextReader r) {
int i = r.Read();
if (i == -1) error();
return (char) i;
}
// grammar:
//
// digit = '0' | '1' | ... | '9'
// op = '+' | '-' | '*' | '/'
// expr = digit +
// | '(' expr op expr ')'
static Expression parse(TextReader r) {
char c = next(r);
if (char.IsDigit(c)) {
string s = "";
while (char.IsDigit((char) r.Peek()))
s += (char) r.Read();
return new IntExpr(int.Parse(s));
}
if (c != '(') error();
Expression e = parse(r);
char op = next(r);
if ("+-*/".IndexOf(op) < 0)
error();
Expression f = parse(r);
if (next(r) != ')') error();
return new OpExpr(e, op, f);
}
public static Expression parse(string s) => parse(new StringReader(s));
public abstract int depth();
}
class IntExpr : Expression {
public int i;
public IntExpr(int i) { this.i = i; }
public override int depth() => 0;
}
class OpExpr : Expression {
public char op;
public Expression left, right;
public OpExpr(Expression left, char op, Expression right) {
this.left = left; this.op = op; this.right = right;
}
public override int depth() =>
Max(left.depth(), right.depth()) + 1;
}
appending to a linked list, recursively
class Node {
public readonly int i;
public Node next;
public Node(int i, Node next) { this.i = i; this.next = next; }
}
class Linked {
Node head;
public void insert(int i) {
head = new Node(i, head);
}
static void append(int i, ref Node n) {
if (n == null)
n = new Node(i, null);
else append(i, ref n.next);
}
public void append(int i) => append(i, ref head);
}