commit
5625a31752
8 changed files with 1240 additions and 0 deletions
-
57README.md
-
91description.html
-
52src/LongStack.java
-
552src/TextIO.java
-
261test/Aout.java
-
227test/LongStackTest.java
-
BINtest/hamcrest-core-1.3.jar
-
BINtest/junit-4.12.jar
@ -0,0 +1,57 @@ |
|||
# README # |
|||
|
|||
See on kolmanda kodutöö failide hoidla, mida saab kasutada ainult algseks lugemiseks. |
|||
Töötamiseks looge endale isiklik repositoorium, näiteks privaatne 'fork' bitbucket serverisse, millest saate luua klooni oma arvutisse. |
|||
|
|||
## Näidete kasutamine käsurealt ## |
|||
#### Kompileerimine: #### |
|||
|
|||
``` |
|||
#!bash |
|||
|
|||
javac -cp src src/LongStack.java |
|||
``` |
|||
|
|||
#### Käivitamine: #### |
|||
|
|||
``` |
|||
#!bash |
|||
|
|||
java -cp src LongStack |
|||
``` |
|||
|
|||
|
|||
### Testide kasutamine ### |
|||
#### Testi kompileerimine: #### |
|||
|
|||
``` |
|||
#!bash |
|||
|
|||
javac -encoding utf8 -cp 'src:test:test/junit-4.12.jar:test/hamcrest-core-1.3.jar' test/LongStackTest.java |
|||
|
|||
``` |
|||
Sama Windows aknas (koolonite asemel peavad olema semikoolonid): |
|||
|
|||
``` |
|||
#!bash |
|||
|
|||
javac -encoding utf8 -cp 'src;test;test/junit-4.12.jar;test/hamcrest-core-1.3.jar' test/LongStackTest.java |
|||
|
|||
|
|||
``` |
|||
|
|||
#### Testi käivitamine: #### |
|||
|
|||
``` |
|||
#!bash |
|||
|
|||
java -cp 'src:test:test/junit-4.12.jar:test/hamcrest-core-1.3.jar' org.junit.runner.JUnitCore LongStackTest |
|||
``` |
|||
|
|||
Sama Windows aknas (koolonite asemel semikoolonid): |
|||
|
|||
``` |
|||
#!bash |
|||
|
|||
java -cp 'src;test;test/junit-4.12.jar;test/hamcrest-core-1.3.jar' org.junit.runner.JUnitCore LongStackTest |
|||
``` |
@ -0,0 +1,91 @@ |
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
|||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
|||
<html> |
|||
<head> |
|||
<title>i231.stack.v4</title> |
|||
</head> |
|||
<body> |
|||
Implement an abstract data type "Stack of long integers" (LIFO) using linkedlists. |
|||
String representation of a stack (provided by <code>toString</code> method) |
|||
must be ordered from bottom to top (tos is the last element). |
|||
<br> |
|||
List of compulsory operations: |
|||
<br> |
|||
Constructor for a new stack: <code>LongStack()</code> |
|||
<br> |
|||
Copy of the stack: <code>Object clone()</code> |
|||
<br> |
|||
Check whether the stack is empty: <code>boolean stEmpty()</code> |
|||
<br> |
|||
Adding an element to the stack: <code>void push (long a)</code> |
|||
<br> |
|||
Removing an element from the stack: <code>long pop()</code> |
|||
<br> |
|||
Arithmetic operation <code>s</code> ( <code>+ - * /</code> ) between two |
|||
topmost elements of the stack (result is left on top): |
|||
<code>void op (String s)</code> |
|||
<br> |
|||
Reading the top without removing it: <code>long tos()</code> |
|||
<br> |
|||
Check whether two stacks are equal: <code>boolean equals (Object o)</code> |
|||
<br> |
|||
Conversion of the stack to string (top last): <code>String toString()</code> |
|||
<br><br> |
|||
Write a method |
|||
<br><code> |
|||
public static long interpret (String pol) </code><br> |
|||
to calculate the value of an arithmetic expression <code>pol</code> in RPN |
|||
(Reverse Polish Notation) using this stack type. |
|||
Expression is a string which contains long integers (including negative and |
|||
multi-digit numbers) and arithmetic operations <code> + - * / </code> |
|||
separated by whitespace symbols. The result must be a long integer value of |
|||
the expression or throwing a RuntimeException in case the expression |
|||
is not correct. Expression is not correct if it contains illegal symbols, |
|||
leaves redundant elements on top of stack or causes stack underflow. |
|||
<br> |
|||
Example. <code>LongStack.interpret ("2 15 -")</code> should return |
|||
<code> -13</code> . |
|||
<br><br> |
|||
Realiseerida abstraktne andmetüüp "pikkade täisarvude magasin" (LIFO) ahela |
|||
(linkedlist) abil. Magasini sõnena esitamisel olgu tipp lõpus |
|||
(meetod <code>toString()</code> väljastab elemendid põhja poolt tipu poole). |
|||
<br> |
|||
Operatsioonide loetelu: |
|||
<br> |
|||
uue magasini konstruktor: <code>LongStack()</code> |
|||
<br> |
|||
koopia loomine: <code>Object clone()</code> |
|||
<br> |
|||
kontroll, kas magasin on tühi: <code>boolean stEmpty()</code> |
|||
<br> |
|||
magasini elemendi lisamine: <code>void push (long a)</code> |
|||
<br> |
|||
magasinist elemendi võtmine: <code>long pop()</code> |
|||
<br> |
|||
aritmeetikatehe s ( <code>+ - * /</code> ) magasini kahe pealmise elemendi |
|||
vahel (tulemus pannakse uueks tipuks): <code>void op (String s)</code> |
|||
<br> |
|||
tipu lugemine eemaldamiseta: <code>long tos()</code> |
|||
<br> |
|||
kahe magasini võrdsuse kindlakstegemine: <code>boolean equals (Object o)</code> |
|||
<br> |
|||
teisendus sõneks (tipp lõpus): <code>String toString()</code> |
|||
<br><br> |
|||
Koostada meetod signatuuriga |
|||
<br><code> |
|||
public static long interpret (String pol) </code><br> |
|||
aritmeetilise avaldise pööratud poola kuju (sulgudeta postfikskuju, |
|||
Reverse Polish Notation) <code>pol</code> interpreteerimiseks |
|||
(väljaarvutamiseks) |
|||
eelpool defineeritud pikkade täisarvude magasini abil. Avaldis on antud stringina, |
|||
mis võib sisaldada pikki täisarve (s.h. negatiivseid ja mitmekohalisi) ning |
|||
tehtemärke <code> + - * / </code>, mis on eraldatud tühikutega (whitespace). |
|||
Tulemuseks peab olema avaldise väärtus pika täisarvuna või erindi (RuntimeException) |
|||
tekitamine, kui avaldis ei ole korrektne. Korrektne ei ole, kui avaldises |
|||
esineb lubamatuid sümboleid, kui avaldis jätab magasini üleliigseid elemente |
|||
või kasutab magasinist liiga palju elemente. |
|||
<br> |
|||
Näit. <code>LongStack.interpret ("2 15 -")</code> peaks tagastama väärtuse |
|||
<code> -13</code> . |
|||
</body> |
|||
</html> |
@ -0,0 +1,52 @@ |
|||
|
|||
public class LongStack { |
|||
|
|||
public static void main (String[] argum) { |
|||
// TODO!!! Your tests here! |
|||
} |
|||
|
|||
LongStack() { |
|||
// TODO!!! Your constructor here! |
|||
} |
|||
|
|||
@Override |
|||
public Object clone() throws CloneNotSupportedException { |
|||
return this; // TODO!!! Your code here! |
|||
} |
|||
|
|||
public boolean stEmpty() { |
|||
return false; // TODO!!! Your code here! |
|||
} |
|||
|
|||
public void push (long a) { |
|||
// TODO!!! Your code here! |
|||
} |
|||
|
|||
public long pop() { |
|||
return 0; // TODO!!! Your code here! |
|||
} // pop |
|||
|
|||
public void op (String s) { |
|||
// TODO!!! |
|||
} |
|||
|
|||
public long tos() { |
|||
return 0; // TODO!!! Your code here! |
|||
} |
|||
|
|||
@Override |
|||
public boolean equals (Object o) { |
|||
return true; // TODO!!! Your code here! |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return null; // TODO!!! Your code here! |
|||
} |
|||
|
|||
public static long interpret (String pol) { |
|||
return 0; // TODO!!! Your code here! |
|||
} |
|||
|
|||
} |
|||
|
@ -0,0 +1,552 @@ |
|||
|
|||
/* |
|||
The file defines a class TextIO, which provides a simple interface |
|||
to Java's standard console input and output. This class defines |
|||
several static methods for reading and writing |
|||
values of various type. |
|||
|
|||
This class will only work with standard, interactive applications. |
|||
When it is used in such an application, System.out and System.in |
|||
should not be used directly, since the TextIO class thinks it has |
|||
exclusive control of System.out and System.in. (Actually, using |
|||
System.out will probably not cause any problems, but don't use |
|||
System.in.) |
|||
|
|||
To use this class in your program, simply include the compiled class |
|||
file TextIO.class in the same directory with the class file for your |
|||
main program. (If you are using a development environment such as |
|||
CodeWarrior or Visual J++, you can include the source file, |
|||
TextIO.java in your project.) You can then use all the public static methods |
|||
from the TextIO class in your program. (In your programs, the names |
|||
of the methods must be prefaced with "TextIO." For example, you should |
|||
use the name TextIO.getln() rather than simply getln().) |
|||
|
|||
(This class is for use with my on-line introductory java textbook, |
|||
which is available at http://math.hws.edu/eck/cs124/notes/index.html.) |
|||
|
|||
Written by: David Eck |
|||
Department of Mathematics and Computer Science |
|||
Hobart and William Smith Colleges |
|||
Geneva, NY 14456 |
|||
Email: eck@hws.edu |
|||
WWW: http://math.hws.edu/eck/ |
|||
|
|||
July 16, 1998 |
|||
|
|||
Modified February, 2000; getChar() now skips blanks and CR's, and getAnyChar() |
|||
can be used to read the next char even if it's a blank or CR. |
|||
|
|||
*/ |
|||
import java.io.*; |
|||
|
|||
public class TextIO { |
|||
|
|||
// *************************** I/O Methods ********************************* |
|||
|
|||
// Methods for writing the primitive types, plus type String, |
|||
// to the console, with no extra spaces. |
|||
// |
|||
// Note that the real-number data types, float |
|||
// and double, a rounded version is output that will |
|||
// use at most 10 or 11 characters. If you want to |
|||
// output a real number with full accuracy, use |
|||
// "TextIO.put(String.valueOf(x))", for example. |
|||
|
|||
public static void put(int x) { put(x,0); } // Note: also handles byte and short! |
|||
public static void put(long x) { put(x,0); } |
|||
public static void put(double x) { put(x,0); } // Also handles float. |
|||
public static void put(char x) { put(x,0); } |
|||
public static void put(boolean x) { put(x,0); } |
|||
public static void put(String x) { put(x,0); } |
|||
|
|||
|
|||
// Methods for writing the primitive types, plus type String, |
|||
// to the console,followed by a carriage return, with |
|||
// no extra spaces. |
|||
|
|||
public static void putln(int x) { put(x,0); newLine(); } // Note: also handles byte and short! |
|||
public static void putln(long x) { put(x,0); newLine(); } |
|||
public static void putln(double x) { put(x,0); newLine(); } // Also handles float. |
|||
public static void putln(char x) { put(x,0); newLine(); } |
|||
public static void putln(boolean x) { put(x,0); newLine(); } |
|||
public static void putln(String x) { put(x,0); newLine(); } |
|||
|
|||
|
|||
// Methods for writing the primitive types, plus type String, |
|||
// to the console, with a minimum field width of w, |
|||
// and followed by a carriage return. |
|||
// If output value is less than w characters, it is padded |
|||
// with extra spaces in front of the value. |
|||
|
|||
public static void putln(int x, int w) { put(x,w); newLine(); } // Note: also handles byte and short! |
|||
public static void putln(long x, int w) { put(x,w); newLine(); } |
|||
public static void putln(double x, int w) { put(x,w); newLine(); } // Also handles float. |
|||
public static void putln(char x, int w) { put(x,w); newLine(); } |
|||
public static void putln(boolean x, int w) { put(x,w); newLine(); } |
|||
public static void putln(String x, int w) { put(x,w); newLine(); } |
|||
|
|||
|
|||
// Method for outputting a carriage return |
|||
|
|||
public static void putln() { newLine(); } |
|||
|
|||
|
|||
// Methods for writing the primitive types, plus type String, |
|||
// to the console, with minimum field width w. |
|||
|
|||
public static void put(int x, int w) { dumpString(String.valueOf(x), w); } // Note: also handles byte and short! |
|||
public static void put(long x, int w) { dumpString(String.valueOf(x), w); } |
|||
public static void put(double x, int w) { dumpString(realToString(x), w); } // Also handles float. |
|||
public static void put(char x, int w) { dumpString(String.valueOf(x), w); } |
|||
public static void put(boolean x, int w) { dumpString(String.valueOf(x), w); } |
|||
public static void put(String x, int w) { dumpString(x, w); } |
|||
|
|||
|
|||
// Methods for reading in the primitive types, plus "words" and "lines". |
|||
// The "getln..." methods discard any extra input, up to and including |
|||
// the next carriage return. |
|||
// A "word" read by getlnWord() is any sequence of non-blank characters. |
|||
// A "line" read by getlnString() or getln() is everything up to next CR; |
|||
// the carriage return is not part of the returned value, but it is |
|||
// read and discarded. |
|||
// Note that all input methods except getAnyChar(), peek(), the ones for lines |
|||
// skip past any blanks and carriage returns to find a non-blank value. |
|||
// getln() can return an empty string; getChar() and getlnChar() can |
|||
// return a space or a linefeed ('\n') character. |
|||
// peek() allows you to look at the next character in input, without |
|||
// removing it from the input stream. (Note that using this |
|||
// routine might force the user to enter a line, in order to |
|||
// check what the next character is.) |
|||
// Acceptable boolean values are the "words": true, false, t, f, yes, |
|||
// no, y, n, 0, or 1; uppercase letters are OK. |
|||
// None of these can produce an error; if an error is found in input, |
|||
// the user is forced to re-enter. |
|||
// Available input routines are: |
|||
// |
|||
// getByte() getlnByte() getShort() getlnShort() |
|||
// getInt() getlnInt() getLong() getlnLong() |
|||
// getFloat() getlnFloat() getDouble() getlnDouble() |
|||
// getChar() getlnChar() peek() getAnyChar() |
|||
// getWord() getlnWord() getln() getString() getlnString() |
|||
// |
|||
// (getlnString is the same as getln and is only provided for consistency.) |
|||
|
|||
public static byte getlnByte() { byte x=getByte(); emptyBuffer(); return x; } |
|||
public static short getlnShort() { short x=getShort(); emptyBuffer(); return x; } |
|||
public static int getlnInt() { int x=getInt(); emptyBuffer(); return x; } |
|||
public static long getlnLong() { long x=getLong(); emptyBuffer(); return x; } |
|||
public static float getlnFloat() { float x=getFloat(); emptyBuffer(); return x; } |
|||
public static double getlnDouble() { double x=getDouble(); emptyBuffer(); return x; } |
|||
public static char getlnChar() { char x=getChar(); emptyBuffer(); return x; } |
|||
public static boolean getlnBoolean() { boolean x=getBoolean(); emptyBuffer(); return x; } |
|||
public static String getlnWord() { String x=getWord(); emptyBuffer(); return x; } |
|||
public static String getlnString() { return getln(); } // same as getln() |
|||
public static String getln() { |
|||
StringBuffer s = new StringBuffer(100); |
|||
char ch = readChar(); |
|||
while (ch != '\n') { |
|||
s.append(ch); |
|||
ch = readChar(); |
|||
} |
|||
return s.toString(); |
|||
} |
|||
|
|||
|
|||
public static byte getByte() { return (byte)readInteger(-128L,127L); } |
|||
public static short getShort() { return (short)readInteger(-32768L,32767L); } |
|||
public static int getInt() { return (int)readInteger((long)Integer.MIN_VALUE, (long)Integer.MAX_VALUE); } |
|||
public static long getLong() { return readInteger(Long.MIN_VALUE, Long.MAX_VALUE); } |
|||
|
|||
public static char getAnyChar(){ return readChar(); } |
|||
public static char peek() { return lookChar(); } |
|||
|
|||
public static char getChar() { // skip spaces & cr's, then return next char |
|||
char ch = lookChar(); |
|||
while (ch == ' ' || ch == '\n') { |
|||
readChar(); |
|||
if (ch == '\n') |
|||
dumpString("? ",0); |
|||
ch = lookChar(); |
|||
} |
|||
return readChar(); |
|||
} |
|||
|
|||
public static float getFloat() { |
|||
float x = 0.0F; |
|||
while (true) { |
|||
String str = readRealString(); |
|||
if (str.equals("")) { |
|||
errorMessage("Illegal floating point input.", |
|||
"Real number in the range " + Float.MIN_VALUE + " to " + Float.MAX_VALUE); |
|||
} |
|||
else { |
|||
Float f = null; |
|||
try { f = Float.valueOf(str); } |
|||
catch (NumberFormatException e) { |
|||
errorMessage("Illegal floating point input.", |
|||
"Real number in the range " + Float.MIN_VALUE + " to " + Float.MAX_VALUE); |
|||
continue; |
|||
} |
|||
if (f.isInfinite()) { |
|||
errorMessage("Floating point input outside of legal range.", |
|||
"Real number in the range " + Float.MIN_VALUE + " to " + Float.MAX_VALUE); |
|||
continue; |
|||
} |
|||
x = f.floatValue(); |
|||
break; |
|||
} |
|||
} |
|||
return x; |
|||
} |
|||
|
|||
public static double getDouble() { |
|||
double x = 0.0; |
|||
while (true) { |
|||
String str = readRealString(); |
|||
if (str.equals("")) { |
|||
errorMessage("Illegal floating point input", |
|||
"Real number in the range " + Double.MIN_VALUE + " to " + Double.MAX_VALUE); |
|||
} |
|||
else { |
|||
Double f = null; |
|||
try { f = Double.valueOf(str); } |
|||
catch (NumberFormatException e) { |
|||
errorMessage("Illegal floating point input", |
|||
"Real number in the range " + Double.MIN_VALUE + " to " + Double.MAX_VALUE); |
|||
continue; |
|||
} |
|||
if (f.isInfinite()) { |
|||
errorMessage("Floating point input outside of legal range.", |
|||
"Real number in the range " + Double.MIN_VALUE + " to " + Double.MAX_VALUE); |
|||
continue; |
|||
} |
|||
x = f.doubleValue(); |
|||
break; |
|||
} |
|||
} |
|||
return x; |
|||
} |
|||
|
|||
public static String getWord() { |
|||
char ch = lookChar(); |
|||
while (ch == ' ' || ch == '\n') { |
|||
readChar(); |
|||
if (ch == '\n') |
|||
dumpString("? ",0); |
|||
ch = lookChar(); |
|||
} |
|||
StringBuffer str = new StringBuffer(50); |
|||
while (ch != ' ' && ch != '\n') { |
|||
str.append(readChar()); |
|||
ch = lookChar(); |
|||
} |
|||
return str.toString(); |
|||
} |
|||
|
|||
public static boolean getBoolean() { |
|||
boolean ans = false; |
|||
while (true) { |
|||
String s = getWord(); |
|||
if ( s.equalsIgnoreCase("true") || s.equalsIgnoreCase("t") || |
|||
s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("y") || |
|||
s.equals("1") ) { |
|||
ans = true; |
|||
break; |
|||
} |
|||
else if ( s.equalsIgnoreCase("false") || s.equalsIgnoreCase("f") || |
|||
s.equalsIgnoreCase("no") || s.equalsIgnoreCase("n") || |
|||
s.equals("0") ) { |
|||
ans = false; |
|||
break; |
|||
} |
|||
else |
|||
errorMessage("Illegal boolean input value.", |
|||
"one of: true, false, t, f, yes, no, y, n, 0, or 1"); |
|||
} |
|||
return ans; |
|||
} |
|||
|
|||
// ***************** Everything beyond this point is private ******************* |
|||
|
|||
// ********************** Utility routines for input/output ******************** |
|||
|
|||
private static InputStream in = System.in; // rename standard input stream |
|||
private static PrintStream out = System.out; // rename standard output stream |
|||
|
|||
private static String buffer = null; // one line read from input |
|||
private static int pos = 0; // position of next char in input line that has |
|||
// not yet been processed |
|||
|
|||
|
|||
private static String readRealString() { // read chars from input following syntax of real numbers |
|||
StringBuffer s=new StringBuffer(50); |
|||
char ch=lookChar(); |
|||
while (ch == ' ' || ch == '\n') { |
|||
readChar(); |
|||
if (ch == '\n') |
|||
dumpString("? ",0); |
|||
ch = lookChar(); |
|||
} |
|||
if (ch == '-' || ch == '+') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
while (ch == ' ') { |
|||
readChar(); |
|||
ch = lookChar(); |
|||
} |
|||
} |
|||
while (ch >= '0' && ch <= '9') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
} |
|||
if (ch == '.') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
while (ch >= '0' && ch <= '9') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
} |
|||
} |
|||
if (ch == 'E' || ch == 'e') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
if (ch == '-' || ch == '+') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
} |
|||
while (ch >= '0' && ch <= '9') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
} |
|||
} |
|||
return s.toString(); |
|||
} |
|||
|
|||
private static long readInteger(long min, long max) { // read long integer, limited to specified range |
|||
long x=0; |
|||
while (true) { |
|||
StringBuffer s=new StringBuffer(34); |
|||
char ch=lookChar(); |
|||
while (ch == ' ' || ch == '\n') { |
|||
readChar(); |
|||
if (ch == '\n') |
|||
dumpString("? ",0); |
|||
ch = lookChar(); |
|||
} |
|||
if (ch == '-' || ch == '+') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
while (ch == ' ') { |
|||
readChar(); |
|||
ch = lookChar(); |
|||
} |
|||
} |
|||
while (ch >= '0' && ch <= '9') { |
|||
s.append(readChar()); |
|||
ch = lookChar(); |
|||
} |
|||
if (s.equals("")){ |
|||
errorMessage("Illegal integer input.", |
|||
"Integer in the range " + min + " to " + max); |
|||
} |
|||
else { |
|||
String str = s.toString(); |
|||
try { |
|||
x = Long.parseLong(str); |
|||
} |
|||
catch (NumberFormatException e) { |
|||
errorMessage("Illegal integer input.", |
|||
"Integer in the range " + min + " to " + max); |
|||
continue; |
|||
} |
|||
if (x < min || x > max) { |
|||
errorMessage("Integer input outside of legal range.", |
|||
"Integer in the range " + min + " to " + max); |
|||
continue; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
return x; |
|||
} |
|||
|
|||
private static String realToString(double x) { |
|||
// Goal is to get a reasonable representation of x in at most |
|||
// 10 characters, or 11 characters if x is negative. |
|||
if (Double.isNaN(x)) |
|||
return "undefined"; |
|||
if (Double.isInfinite(x)) |
|||
if (x < 0) |
|||
return "-INF"; |
|||
else |
|||
return "INF"; |
|||
if (Math.abs(x) <= 5000000000.0 && Math.rint(x) == x) |
|||
return String.valueOf( (long)x ); |
|||
String s = String.valueOf(x); |
|||
if (s.length() <= 10) |
|||
return s; |
|||
boolean neg = false; |
|||
if (x < 0) { |
|||
neg = true; |
|||
x = -x; |
|||
s = String.valueOf(x); |
|||
} |
|||
if (x >= 0.00005 && x <= 50000000 && (s.indexOf('E') == -1 && s.indexOf('e') == -1)) { // trim x to 10 chars max |
|||
s = round(s,10); |
|||
s = trimZeros(s); |
|||
} |
|||
else if (x > 1) { // construct exponential form with positive exponent |
|||
long power = (long)Math.floor(Math.log(x)/Math.log(10)); |
|||
String exp = "E" + power; |
|||
int numlength = 10 - exp.length(); |
|||
x = x / Math.pow(10,power); |
|||
s = String.valueOf(x); |
|||
s = round(s,numlength); |
|||
s = trimZeros(s); |
|||
s += exp; |
|||
} |
|||
else { // constuct exponential form |
|||
long power = (long)Math.ceil(-Math.log(x)/Math.log(10)); |
|||
String exp = "E-" + power; |
|||
int numlength = 10 - exp.length(); |
|||
x = x * Math.pow(10,power); |
|||
s = String.valueOf(x); |
|||
s = round(s,numlength); |
|||
s = trimZeros(s); |
|||
s += exp; |
|||
} |
|||
if (neg) |
|||
return "-" + s; |
|||
else |
|||
return s; |
|||
} |
|||
|
|||
private static String trimZeros(String num) { // used by realToString |
|||
if (num.indexOf('.') >= 0 && num.charAt(num.length() - 1) == '0') { |
|||
int i = num.length() - 1; |
|||
while (num.charAt(i) == '0') |
|||
i--; |
|||
if (num.charAt(i) == '.') |
|||
num = num.substring(0,i); |
|||
else |
|||
num = num.substring(0,i+1); |
|||
} |
|||
return num; |
|||
} |
|||
|
|||
private static String round(String num, int length) { // used by realToString |
|||
if (num.indexOf('.') < 0) |
|||
return num; |
|||
if (num.length() <= length) |
|||
return num; |
|||
if (num.charAt(length) >= '5' && num.charAt(length) != '.') { |
|||
char[] temp = new char[length+1]; |
|||
int ct = length; |
|||
boolean rounding = true; |
|||
for (int i = length-1; i >= 0; i--) { |
|||
temp[ct] = num.charAt(i); |
|||
if (rounding && temp[ct] != '.') { |
|||
if (temp[ct] < '9') { |
|||
temp[ct]++; |
|||
rounding = false; |
|||
} |
|||
else |
|||
temp[ct] = '0'; |
|||
} |
|||
ct--; |
|||
} |
|||
if (rounding) { |
|||
temp[ct] = '1'; |
|||
ct--; |
|||
} |
|||
// ct is -1 or 0 |
|||
return new String(temp,ct+1,length-ct); |
|||
} |
|||
else |
|||
return num.substring(0,length); |
|||
|
|||
} |
|||
private static void dumpString(String str, int w) { // output string to console |
|||
for (int i=str.length(); i<w; i++) |
|||
out.print(' '); |
|||
for (int i=0; i<str.length(); i++) |
|||
if ((int)str.charAt(i) >= 0x20 && (int)str.charAt(i) != 0x7F) // no control chars or delete |
|||
out.print(str.charAt(i)); |
|||
else if (str.charAt(i) == '\n' || str.charAt(i) == '\r') |
|||
newLine(); |
|||
} |
|||
|
|||
private static void errorMessage(String message, String expecting) { |
|||
// inform user of error and force user to re-enter. |
|||
newLine(); |
|||
dumpString(" *** Error in input: " + message + "\n", 0); |
|||
dumpString(" *** Expecting: " + expecting + "\n", 0); |
|||
dumpString(" *** Discarding Input: ", 0); |
|||
if (lookChar() == '\n') |
|||
dumpString("(end-of-line)\n\n",0); |
|||
else { |
|||
while (lookChar() != '\n') |
|||
out.print(readChar()); |
|||
dumpString("\n\n",0); |
|||
} |
|||
dumpString("Please re-enter: ", 0); |
|||
readChar(); // discard the end-of-line character |
|||
} |
|||
|
|||
private static char lookChar() { // return next character from input |
|||
if (buffer == null || pos > buffer.length()) |
|||
fillBuffer(); |
|||
if (pos == buffer.length()) |
|||
return '\n'; |
|||
return buffer.charAt(pos); |
|||
} |
|||
|
|||
private static char readChar() { // return and discard next character from input |
|||
char ch = lookChar(); |
|||
pos++; |
|||
return ch; |
|||
} |
|||
|
|||
private static void newLine() { // output a CR to console |
|||
out.println(); |
|||
out.flush(); |
|||
} |
|||
|
|||
private static boolean possibleLinefeedPending = false; |
|||
|
|||
private static void fillBuffer() { // Wait for user to type a line and press return, |
|||
// and put the typed line into the buffer. |
|||
StringBuffer b = new StringBuffer(); |
|||
out.flush(); |
|||
try { |
|||
int ch = in.read(); |
|||
if (ch == '\n' && possibleLinefeedPending) |
|||
ch = in.read(); |
|||
possibleLinefeedPending = false; |
|||
while (ch != -1 && ch != '\n' && ch != '\r') { |
|||
b.append((char)ch); |
|||
ch = in.read(); |
|||
} |
|||
possibleLinefeedPending = (ch == '\r'); |
|||
if (ch == -1) { |
|||
System.out.println("\n*** Found an end-of-file while trying to read from standard input!"); |
|||
System.out.println("*** Maybe your Java system doesn't implement standard input?"); |
|||
System.out.println("*** Program will be terminated.\n"); |
|||
throw new RuntimeException("End-of-file on standard input."); |
|||
} |
|||
} |
|||
catch (IOException e) { |
|||
System.out.println("Unexpected system error on input."); |
|||
System.out.println("Terminating program."); |
|||
System.exit(1); |
|||
} |
|||
buffer = b.toString(); |
|||
pos = 0; |
|||
} |
|||
|
|||
private static void emptyBuffer() { // discard the rest of the current line of input |
|||
buffer = null; |
|||
} |
|||
|
|||
|
|||
} // end of class TextIO |
@ -0,0 +1,261 @@ |
|||
|
|||
/** Helper methods. |
|||
* Arrays converted to array expressions (toString(...)) |
|||
* and prettyprinting (toPrettyString(...)). |
|||
* @author Jaanus |
|||
*/ |
|||
public class Aout { |
|||
|
|||
/** Just testing. */ |
|||
public static void main (String[] args) { |
|||
System.out.println (toString (new String[] |
|||
{null, "", "0", "a\nb", " ", " ", "\t", "möäüÕga", "\"", "\\", "\'"})); |
|||
} // main |
|||
|
|||
/** Conversion for int[][] . */ |
|||
public static String toString (int[][] m) { |
|||
if (m == null) return "(int[][])null"; |
|||
StringBuffer sb = new StringBuffer(); |
|||
sb.append ("new int[][]{"); |
|||
for (int i=0; i < m.length; i++) { |
|||
if (i > 0) sb.append (", "); |
|||
if (m[i] == null) |
|||
sb.append ("null"); |
|||
else { |
|||
sb.append ("{"); |
|||
for (int j=0; j < m[i].length; j++) { |
|||
if (j > 0) sb.append (", "); |
|||
sb.append (String.valueOf (m[i][j])); |
|||
} // for j |
|||
sb.append ("}"); |
|||
} |
|||
} // for i |
|||
sb.append ("}"); |
|||
return sb.toString(); |
|||
} // toString int[][] |
|||
|
|||
/** Conversion for double[][] . */ |
|||
public static String toString (double[][] m) { |
|||
if (m == null) return "(double[][])null"; |
|||
StringBuffer sb = new StringBuffer(); |
|||
sb.append ("new double[][]{"); |
|||
for (int i=0; i < m.length; i++) { |
|||
if (i > 0) sb.append (", "); |
|||
if (m[i] == null) |
|||
sb.append ("null"); |
|||
else { |
|||
sb.append ("{"); |
|||
for (int j=0; j < m[i].length; j++) { |
|||
if (j > 0) sb.append (", "); |
|||
sb.append (String.valueOf (m[i][j])); |
|||
} // for j |
|||
sb.append ("}"); |
|||
} |
|||
} // for i |
|||
sb.append ("}"); |
|||
return sb.toString(); |
|||
} // toString double[][] |
|||
|
|||
/** Conversion for int[] . */ |
|||
public static String toString (int[] m) { |
|||
if (m == null) return "(int[])null"; |
|||
StringBuffer sb = new StringBuffer(); |
|||
sb.append ("new int[]{"); |
|||
for (int i=0; i < m.length; i++) { |
|||
if (i > 0) sb.append (", "); |
|||
sb.append (String.valueOf (m[i])); |
|||
} // for i |
|||
sb.append ("}"); |
|||
return sb.toString(); |
|||
} // toString int[] |
|||
|
|||
/** Conversion for double[] . */ |
|||
public static String toString (double[] m) { |
|||
if (m == null) return "(double[])null"; |
|||
StringBuffer sb = new StringBuffer(); |
|||
sb.append ("new double[]{"); |
|||
for (int i=0; i < m.length; i++) { |
|||
if (i > 0) sb.append (", "); |
|||
sb.append (String.valueOf (m[i])); |
|||
} // for i |
|||
sb.append ("}"); |
|||
return sb.toString(); |
|||
} // toString double[] |
|||
|
|||
/** Conversion for int . */ |
|||
public static String toString (int n) { |
|||
return String.valueOf (n); |
|||
} // toString int |
|||
|
|||
/** Conversion for double . */ |
|||
public static String toString (double d) { |
|||
return String.valueOf (d); |
|||
} // toString double |
|||
|
|||
/** Conversion for String . */ |
|||
public static String toString (String s) { |
|||
if (s == null) |
|||
return "null"; |
|||
StringBuffer tmp = new StringBuffer(); |
|||
for (int k=0; k < s.length(); k++) { |
|||
char c = s.charAt (k); |
|||
switch (c) { |
|||
case '\n': { tmp.append ("\\n"); break; } |
|||
case '\t': { tmp.append ("\\t"); break; } |
|||
case '\b': { tmp.append ("\\b"); break; } |
|||
case '\f': { tmp.append ("\\f"); break; } |
|||
case '\r': { tmp.append ("\\r"); break; } |
|||
case '\\': { tmp.append ("\\\\"); break; } |
|||
case '\'': { tmp.append ("\\\'"); break; } |
|||
case '\"': { tmp.append ("\\\""); break; } |
|||
// TODO!!! add more escapes if needed |
|||
default: tmp.append (c); |
|||
} // switch |
|||
} // for k |
|||
return "\"" + tmp.toString() + "\""; |
|||
} // toString String |
|||
|
|||
/** Conversion for String[] . */ |
|||
public static String toString (String[] m) { |
|||
if (m == null) |
|||
return "(String[])null"; |
|||
StringBuffer sb = new StringBuffer(); |
|||
sb.append ("new String[]{"); |
|||
for (int i=0; i < m.length; i++) { |
|||
if (i > 0) |
|||
sb.append (", "); |
|||
sb.append (toString (m[i])); |
|||
} // for i |
|||
sb.append ("}"); |
|||
return sb.toString(); |
|||
} // toString String[] |
|||
|
|||
/** Double number as string with the given length. |
|||
* @param d argument |
|||
* @param len length |
|||
* @return d as string |
|||
*/ |
|||
public static String fString (double d, int len) { |
|||
if (len<1) |
|||
return ""; |
|||
// pad on ruum punkti ja v6imaliku miinusm2rgi jaoks |
|||
int pad = 1 + ((d<0)?1:0); |
|||
// loga on t2isosa numbrikohtade arv |
|||
int loga = (int)Math.max (0., Math.log10 (Math.abs (d))) + 1; |
|||
// kk on punkti j2rel olevate kohtade arv |
|||
int kk = (int)Math.max (len-pad-loga, 0); |
|||
String fs = "%" + String.valueOf (len) + "." + |
|||
String.valueOf (kk) + "f"; |
|||
String res = ""; |
|||
try { |
|||
res = String.format ((java.util.Locale)null, fs, d); |
|||
} catch (IllegalArgumentException e) { |
|||
res = String.valueOf (d); |
|||
} // try |
|||
return res; |
|||
} // fString |
|||
|
|||
/** Prettyprint for double[][] . |
|||
* @param m array to print |
|||
* @param fs format string for element |
|||
* @return m array as multiline string |
|||
*/ |
|||
public static String toPrettyString (double[][] m, String fs) { |
|||
String nl = System.getProperty ("line.separator"); |
|||
if (m == null) |
|||
return "nullpointer instead of this matrix" + nl; |
|||
// throw new NullPointerException ("(double[][])null"); // alternative |
|||
if (m.length == 0) |
|||
return "this matrix is empty" + nl; |
|||
StringBuffer sb = new StringBuffer(nl); |
|||
for (int i=0; i < m.length; i++) { |
|||
if (m[i] == null) |
|||
sb.append ("nullpointer instead of this row" + nl); |
|||
else { |
|||
if (m[i].length == 0) |
|||
sb.append ("this row is empty"); |
|||
else { |
|||
for (int j=0; j < m[i].length; j++) { |
|||
String elem = ""; |
|||
if (fs == null || fs.length() < 1) { |
|||
// TODO!!! keera siit, kui tahad pilti muuta |
|||
elem = fString (m[i][j], 6) + "\t"; |
|||
} else { |
|||
try { |
|||
elem = String.format ((java.util.Locale)null, |
|||
fs, m[i][j]) + " "; // remove space if needed |
|||
} catch (IllegalArgumentException e) { |
|||
elem = fString (m[i][j], 6) + "\t"; |
|||
} // try |
|||
} |
|||
sb.append (elem); |
|||
} // for j |
|||
} // nonempty row |
|||
sb.append (nl); |
|||
} // non-null row |
|||
} // for i |
|||
return sb.toString(); |
|||
} // toPrettyString double[][] |
|||
|
|||
/** Version of double[][] prettyprint without format string. */ |
|||
public static String toPrettyString (double[][] m) { |
|||
return toPrettyString (m, null); |
|||
} // toPrettyString double[][] |
|||
|
|||
/** Prettyprint for int[][] . |
|||
* @param m array to print |
|||
* @param fs format string for element |
|||
* @return m array as a multiline string |
|||
*/ |
|||
public static String toPrettyString (int[][] m, String fs) { |
|||
String nl = System.getProperty ("line.separator"); |
|||
if (m == null) |
|||
return "nullpointer instead of this matrix" + nl; |
|||
// throw new NullPointerException ("(double[][])null"); // alternative |
|||
if (m.length == 0) |
|||
return "this matrix is empty" + nl; |
|||
StringBuffer sb = new StringBuffer(nl); |
|||
for (int i=0; i < m.length; i++) { |
|||
if (m[i] == null) |
|||
sb.append ("nullpointer instead of this row" + nl); |
|||
else { |
|||
if (m[i].length == 0) |
|||
sb.append ("this row is empty"); |
|||
else { |
|||
for (int j=0; j < m[i].length; j++) { |
|||
String elem = ""; |
|||
if (fs == null || fs.length() < 1) |
|||
fs = "%5d"; // TODO!!! keera siit, kui vaja |
|||
try { |
|||
elem = String.format ((java.util.Locale)null, |
|||
fs, m[i][j]) + " "; // remove space if needed |
|||
} catch (IllegalArgumentException e) { |
|||
elem = String.valueOf (m[i][j]) + "\t"; |
|||
} // try |
|||
sb.append (elem); |
|||
} // for j |
|||
} // nonempty row |
|||
sb.append (nl); |
|||
} // non-null row |
|||
} // for i |
|||
return sb.toString(); |
|||
} // toPrettyString int[][] |
|||
|
|||
/** Version of int[][] prettyprint without format string. */ |
|||
public static String toPrettyString (int[][] m) { |
|||
return toPrettyString (m, null); |
|||
} // toPrettyString int[][] |
|||
|
|||
/** Prettyprint for String[] . */ |
|||
public static String toPrettyString (String[] m) { |
|||
String nl = System.getProperty ("line.separator"); |
|||
if (m == null) return "(String[])null"; |
|||
StringBuffer sb = new StringBuffer(); |
|||
for (int i=0; i < m.length; i++) { |
|||
sb.append (toString (m[i]) + nl); |
|||
} // for i |
|||
return sb.toString(); |
|||
} // toPrettyString String[] |
|||
|
|||
} // Aout |
|||
|
@ -0,0 +1,227 @@ |
|||
|
|||
import static org.junit.Assert.*; |
|||
import org.junit.Test; |
|||
|
|||
/** Testklass. |
|||
* @author jaanus |
|||
*/ |
|||
public class LongStackTest { |
|||
|
|||
@Test (timeout=1000) |
|||
public void testNewStack() { |
|||
LongStack m = new LongStack(); |
|||
assertTrue ("new stack must be empty;", m.stEmpty()); |
|||
m.push (1); |
|||
m.pop(); |
|||
assertTrue ("stack must be empty after one push and one pop; ", m.stEmpty()); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testLIFO() { |
|||
LongStack m = new LongStack(); |
|||
m.push (6); |
|||
m.push (-3); |
|||
long i1 = m.pop(); |
|||
long i2 = m.pop(); |
|||
assertTrue ("After two pushes and two pops stack must be empty;", |
|||
m.stEmpty()); |
|||
assertTrue ("LIFO order must hold: 6 -3 returns -3 first;", |
|||
(i1 == -3) && (i2 == 6)); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testOp() { |
|||
long tt = 0; |
|||
LongStack m = new LongStack(); |
|||
m.push (5); |
|||
m.push (3); |
|||
m.op ("+"); |
|||
tt = m.pop(); |
|||
assertTrue ("5 + 3 must be 8; ", tt==8); |
|||
assertTrue ("push push op pop must not grow the stack; ", m.stEmpty()); |
|||
m.push (2147483649L); |
|||
m.push (2147483648L); |
|||
m.op ("+"); |
|||
tt = m.pop(); |
|||
assertTrue ("2147483649 + 2147483648 must be 4294967297; ", |
|||
tt==4294967297L); |
|||
m.push (5); |
|||
m.push (3); |
|||
m.op ("-"); |
|||
tt = m.pop(); |
|||
assertTrue ("5 - 3 must be 2; ", tt==2); |
|||
assertTrue ("push push op pop must not grow the stack; ", m.stEmpty()); |
|||
m.push (5); |
|||
m.push (3); |
|||
m.op ("*"); |
|||
tt = m.pop(); |
|||
assertTrue ("5 * 3 must be 15; ", tt==15); |
|||
assertTrue ("push push op pop must not grow the stack; ", m.stEmpty()); |
|||
m.push (51); |
|||
m.push (3); |
|||
m.op ("/"); |
|||
tt = m.pop(); |
|||
assertTrue ("51 / 3 must be 17; ", tt==17); |
|||
assertTrue ("push push op pop must not grow the stack; ", m.stEmpty()); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testTos() { |
|||
LongStack m = new LongStack(); |
|||
m.push (2); |
|||
m.push (5); |
|||
long k = m.tos(); |
|||
long k2 = m.pop(); |
|||
assertEquals ("5 must be on top ", 5, k); |
|||
assertEquals ("tos must not change the top;", 5, k2); |
|||
long k3 = m.pop(); |
|||
assertEquals ("tos must not change the stack;", 2, k3); |
|||
assertTrue ("tos must not pop;", m.stEmpty()); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testEquals() { |
|||
LongStack m1 = new LongStack(); |
|||
LongStack m2 = new LongStack(); |
|||
assertTrue ("two empty stacks must be equal;", m1.equals(m2)); |
|||
m1.push (1); |
|||
m2.push (1); |
|||
assertTrue ("1 in both stacks - stacks must be equal; ", m1.equals(m2)); |
|||
m1.push (0); |
|||
assertFalse ("1 0 and just 1 must not be equal;", m1.equals(m2)); |
|||
m2.push (3); |
|||
assertFalse ("1 0 and 1 3 must not be equal;", m1.equals(m2)); |
|||
m1.pop(); |
|||
m2.pop(); |
|||
assertTrue ("1 in stacks with different history, stacks must be equal;", |
|||
m1.equals(m2)); |
|||
m1.pop(); |
|||
assertFalse ("first empty, second contains 1, must not be equal;", |
|||
m1.equals(m2)); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testPopEmpty() { |
|||
LongStack m = new LongStack(); |
|||
m.pop(); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testOpUnderflow() { |
|||
LongStack m = new LongStack(); |
|||
m.push (4); |
|||
m.op ("+"); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testClone() { |
|||
LongStack m1 = new LongStack(); |
|||
m1.push (5); |
|||
m1.push (4); |
|||
LongStack m2 = null; |
|||
try { |
|||
m2 = (LongStack)m1.clone(); |
|||
} catch (CloneNotSupportedException e) {}; |
|||
assertNotSame ("clone must differ from original;", m2, m1); |
|||
assertEquals ("clone must be equal to original;", m2, m1); |
|||
m1.pop(); |
|||
m1.push (6); |
|||
assertFalse ("clone must be independent;", m1.equals(m2)); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testToString() { |
|||
LongStack m = new LongStack(); |
|||
assertNotNull ("empty stack must be ok;", m.toString()); |
|||
m.push (-8); |
|||
m.push (7); |
|||
String s1 = m.toString().substring (0, 3); |
|||
m.push (2); |
|||
String s2 = m.toString().substring (0, 3); |
|||
assertEquals ( |
|||
"top must be the last element; toString from bottom must start with -8 7 ", |
|||
s1, s2); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testTosUnderflow() { |
|||
LongStack m = new LongStack(); |
|||
m.tos(); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testInterpret() { |
|||
String s = "1"; |
|||
assertEquals ("expression: " + s, 1, LongStack.interpret (s)); |
|||
s = "2 5 -"; |
|||
assertEquals ("expression: " + s, -3, LongStack.interpret (s)); |
|||
s = "35 10 -3 + /"; |
|||
assertEquals ("expression: " + s, 5, LongStack.interpret (s)); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testInterpretStackbalance() { |
|||
String s = "35 10 -3 + / 2"; |
|||
LongStack.interpret (s); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testInterpretIllegalArg1() { |
|||
String s = "35 10 -3 + x 2"; |
|||
LongStack.interpret (s); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testInterpretIllegalArg2() { |
|||
String s = "35 y 10 -3 + - +"; |
|||
LongStack.interpret (s); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testInterpretUnderflow() { |
|||
String s = "35 10 + -"; |
|||
LongStack.interpret (s); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testInterpretNull() { |
|||
String s = null; |
|||
LongStack.interpret (s); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testInterpretEmpty() { |
|||
String s = ""; |
|||
LongStack.interpret (s); |
|||
} |
|||
|
|||
@Test (expected=RuntimeException.class) |
|||
public void testInterpretOpfirst() { |
|||
String s = "- 3 2"; |
|||
LongStack.interpret (s); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testInterpretLong() { |
|||
String s = "1 -10 4 8 3 - + * +"; |
|||
assertEquals ("expression: " + Aout.toString (s), -89, |
|||
LongStack.interpret (s)); |
|||
s = "156 154 152 - 3 + -"; |
|||
assertEquals ("expression: " + Aout.toString (s), 151, |
|||
LongStack.interpret (s)); |
|||
} |
|||
|
|||
@Test (timeout=1000) |
|||
public void testInterpretTokenizer() { |
|||
String s = "1 2 +"; |
|||
assertEquals ("expression: " + Aout.toString (s), 3, |
|||
LongStack.interpret (s)); |
|||
s = " \t \t356 \t \t"; |
|||
assertEquals ("expression: " + Aout.toString (s), 356, |
|||
LongStack.interpret (s)); |
|||
s = "\t2 \t5 + \t"; |
|||
assertEquals ("expression: " + Aout.toString (s), 7, |
|||
LongStack.interpret (s)); |
|||
} |
|||
} |
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue