Introduction:
I am trying to create a controllable loop for a program and I use a flag for such thing. Although redundant to the question, the program takes any number and says if it is integer or decimal, if decimal shows up the decimal and float part.
At the bottom of it, I manage the while's flag . If true, the loop restarts, if false, end the program.
Problem: If I input n or N, it does what it has to do. But, if I input s or S. It does not.
I used:
My try at not using that many if statements in the next:
bool = !(scan.hasNext("N") || scan.hasNext("n"));
bool = (scan.hasNext("S") || scan.hasNext("s"));
The full code if someone has a better solution or helps anyone:
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
int ent = 0;
double dec = 0;
boolean bool = true;
while(bool == true){
System.out.print("Introduce un numero: ");
if (scan.hasNextInt() == true)
{
ent = scan.nextInt();
System.out.println("El numero es entero");
}
else {dec = scan.nextFloat();
System.out.println("El numero es decimal");
//System.out.print();
String realNumber = Double.toString(dec);
String[] mySplit = realNumber.split("\\.");
BigDecimal entero = new BigDecimal(mySplit[0]);
BigDecimal real = new BigDecimal(realNumber);
BigDecimal fraction = real.subtract(entero);
System.out.println(String.format("Entero : %s\nDecimales: %s", entero.toString(),fraction.toString().substring(0,4)));
}
System.out.println("Quieres continuar? S/s o N/n");
bool = !(scan.hasNext("N") || scan.hasNext("n"));
bool = (scan.hasNext("S") || scan.hasNext("s"));
}
}
}
I expect that if I input s or S. It starts again asking me a number not "java.util.InputMismatchException"
You're using this form of hasNext():
/**
* Returns true if the next token matches the pattern constructed from the
* specified string. The scanner does not advance past any input.
*
* <p> An invocation of this method of the form <tt>hasNext(pattern)</tt>
* behaves in exactly the same way as the invocation
* <tt>hasNext(Pattern.compile(pattern))</tt>.
*
* #param pattern a string specifying the pattern to scan
* #return true if and only if this scanner has another token matching
* the specified pattern
* #throws IllegalStateException if this scanner is closed
*/
public boolean hasNext(String pattern) {
return hasNext(patternCache.forName(pattern));
}
which is used to get input with a specific Pattern.
You only want to get the user's response as "S" or "N", so use nextLine():
System.out.println("Quieres continuar? S/s o N/n");
boolean gotit = false;
while (!gotit) {
String response = scan.nextLine().toLowerCase().trim();
bool = response.equals("s");
gotit = (response.equals("n") || response.equals("s"));
}
Related
Perhaps i wasn't clear enough. I apologize. I tried condensing and adding images in this edit to make it more clear.
50 Seed Value, 1200 RNG Value.
60 Seed Value, 1200 RNG Value.
In the examples above (for clarity instead of writing it all out), you can see the outputs you get for 50 vs 60. It's not the distinct values I'm concerned. It's the display now. As you can see, the number gets bigger since I put in a new seed value. I want it to display what the 50 seed value is, but have the properties of whatever seed value I put in.
If I put in for example 60, I want to get:
H1 T1 H1 T1 HHH3 TTTTT5 H1 T1 HHHH4 T1 HH2 T1 H1 T1 H1 T1 H1 T1 H1 TTT3 H1 TTT3 H1 TTTT4 H1 T1 HHH3 TT2 H1 T... (just like with the 50 seed value).
BUT it would get 35 distinct values instead of the 30. Let me know if I can be clearer I apologize for being so confusing.
import java.util.Scanner;
import java.util.Random;
public class CoinFlipAnalyzer{
private static final Scanner
stdIn = new Scanner(System.in);
public static void main (String[] args){
// Integer Values:
int totalNumberOfRuns = 0;
int run = 1;
// Boolean Values:
boolean theCoin;
boolean tempVal = false;
// Gathering the Users Input:
System.out.println("Welcome to the coin flip analyzer.\n"
+ "How many flips?");
int numberOfFlips = stdIn.nextInt();
System.out.println("What do you want to seed the random number generator with?");
int rngSeed = stdIn.nextInt();
Random rng = new Random(rngSeed); // Initiates the Random Number Generator.
System.out.println();
// Loop and Array to Decide Whether the Value is Heads or Tail.
long[] runLength = new long[numberOfFlips];
for (int i = 0; i < numberOfFlips; i++) {
theCoin = rng.nextBoolean(); // As requested, I used the nextBoolean expression.
if (theCoin != tempVal) {
if (i > 0) {
System.out.print(run + " ");
}
runLength[run - 1]++;
totalNumberOfRuns++;
run = 1;
}
else {
run++;
}
if (theCoin) {
System.out.print("H");
tempVal = true;
}
else {
System.out.print("T");
tempVal = false;
}
}
System.out.print("...");
System.out.println();
System.out.println("There were a total of " + totalNumberOfRuns +
" distinct runs in the simulation.\nTheir breakdown follows:");
System.out.println();
I think I understand the requirement. In essence, there is some desired width, and if the number of outputs exceeds the width, then print using an ellipses.
There is the StringUtils from Apache Commons that has an 'Abbreviate' method.
public static String abbreviate(String str,
int maxWidth)
Abbreviates a String using ellipses. This will turn "Now is the time for all good men" into "Now is the time for..."
To use this (or the other suggestion below), I would remove the immediate output that is being generated in the run, and instead build a String. One could build a char[] as well, but here we will go with a String (or a StringBuilder). There is another advantage to so doing -- it is generally a good practice to separate some of the logic from the output. Plus it would be more testable.
So, if one can use the StringUtils.abbreviate(...), then take the result from the doFlips(...) and pass it to the method, and the result will be done.
/*
* moved the flipping into a method; allow it to build the
* results rather than immediately outputting them
*/
private static StringBuilder doFlips(int numberOfFlips, Random rng)
{
long[] runLength = new long[numberOfFlips];
boolean theCoin;
boolean tempVal = false;
int run = 1;
int totalNumberOfRuns = 0;
// Here we will collect the output; use better name in production
StringBuilder sb = new StringBuilder();
for (int i = 0; i < numberOfFlips; i++) {
theCoin = rng.nextBoolean(); // As requested, I used the nextBoolean
// expression.
if (theCoin != tempVal) {
if (i > 0) {
sb.append(run);
sb.append(" ");
}
runLength[run - 1]++;
totalNumberOfRuns++;
run = 1;
}
else {
run++;
}
if (theCoin) {
sb.append("H");
tempVal = true;
}
else {
sb.append("T");
tempVal = false;
}
}
return sb;
}
If one cannot use the library, it is easy enough to write a chop method:
/**
* Chop the input StringBuilder and give "..." at
* maxOutput.
*
* NOTE: no error checking
*/
private static String ourChop(StringBuilder sb, int maxOutput)
{
if (sb.length() <= maxOutput) {
return sb.toString();
}
// we chop everything past maxOutput - 3
sb.setLength(maxOutput - 3);
sb.append("...");
return sb.toString();
}
So, we can then do the following:
public static void main(String[] args)
{
int seed = 1200;
int maxOutput = 25;
// 50 flips, 25 length max, including ... if needed
StringBuilder res = doFlips(50, new Random(seed));
System.out.println(ourChop(res, maxOutput));
res = doFlips(60, new Random(seed));
System.out.println(ourChop(res, maxOutput));
And we get this output (at 25):
H1 T1 H1 T1 HHH3 TTTTT...
H1 T1 H1 T1 HHH3 TTTTT...
Now, if the goal is to align to the max output of some given run, then one would need to collect all of the runs (50, 60, etc.), and then find the particular value (say the shortest of the outputs; note that in theory in a truly random setting, 60 could have a shorter output than 50, but not when using the same seed). One could then use that determined value to chop to a given output length.
If I have misunderstood the approach, I apologize.
I'm relatively new to java and learning OOP and I have a project to make a number converter that can convert a value of any base to decimal, or a decimal value to any base.
I've tested decimal to a different base and that's working fine for me, but the decimal to base [2, 8, whatever] isn't working. Any help?
public class NumberConverter
{
private int decimal; // always stores the decimal equivalent, regardless of base
private int base;
private String strValue;
/** default set to base 10 w/ a value of 0 */
public NumberConverter()
{
decimal = 0;
base = 10;
strValue="0";
}
/** base 10 value is used to set decimal, base and strValue
* note: toBaseX can do this for you also */
public NumberConverter(int value)
{
decimal = value;
base = 10;
strValue = "" + value;
}
/** sets the strValue and base based on parameters
* strValue is only stored in uppercase
* decimal is set here as well provided newValue is valid */
public NumberConverter(int newValue, int newBase)
{
decimal = 0;
strValue = newValue + "";
base = newBase;
}
//**** Accessor Methods ****//
public String getValue()
{
return strValue;
}
public int getBase()
{
return base;
}
public int getDecimal()
{
return decimal;
}
/** sets the strValue and base based on parameters
* decimal is set here as well, with a call to baseXToDec() */
public void setValue(String newValue, int newBase)
{
strValue = newValue;
base = newBase;
if (isValid())
decimal = baseXToDec();
else
decimal = 0;
}
public boolean isValid()
{
boolean valid = true;
for (int i=0; i<strValue.length()-1; i++)
{
if ((strValue.charAt(i)>47 && strValue.charAt(i)<58) || (strValue.charAt(i)>64 && strValue.charAt(i)<71))
valid = true;
else
valid = false;
}
return valid;
}
/** base of this object is set to x and strValue is the String value in base x
* strValue is also returned, just for good measure
* #param x the number base to convert to */
public String toBaseX(int x)
{
String strResult = "", strRev;
base = x;
int div = decimal, mod;
if (decimal == 0)
return "0";
while(div != 0)
{
mod = div % x;
if (mod > 10)
strResult += (char)(mod+55);
else
strResult += (char)(mod+48);
div = div / x;
}
strRev = reverseString(strResult);
strValue = strRev;
return strRev;
}
/** take the currently stored strValue and calculate and return the decimal value */
public int baseXToDec()
{
int exponent = strValue.length()-1;
for (int i=0; i<strValue.length(); i++)
{
// update result
decimal += (strValue.charAt(i) * Math.pow(base, exponent));
// decrement exponent
exponent--;
}
base = 10;
strValue = "" + decimal;
return decimal;
}
/** this is a helper method only
* the integer value of digit is returned
* -1 is the return value for an error
* #param ch a valid digit for the given number base */
private int charToValue(char ch)
{
}
/** This is a helper method that returns strRev as a reversed version
* #param strFwd the string to be reversed */
private String reverseString(String strResult)
{
String strRev = "";
for ( int i = strResult.length() - 1 ; i >= 0 ; i-- )
strRev= strRev + strResult.charAt(i);
return strRev;
}
/** a String with the current base and value is returned */
public String toString()
{
String result = "In base " + getBase() + " the value is "+ getValue() + ".\n";
return result;
}
}
strValue.charAt(i) this is the problem: it returns a character code for the digit, not the integer value it represents. For example, the code for character '0' is 48 etc. You need to convert it into the actual integer value before you can use it like that.
One (non-portable, and frowned upon) way is to subtract 48 (or '0'), as suggested in the comment. This relies on the fact that the digits in ASCII are coded sequentially, so 49 would be '1', 50 - '2' etc. It'll do what you want.
A (slightly) better way is Character.getNumericValue(strValue.charAt(i)).
It'll do the same thing behind the curtain, but will also work in exotic languages (like Indian, Easter Arabic etc.), that use different symbols for digits. Not that your little program will ever need that, just a good practice to adopt for the future.
Edit: same applies to isValid() function as well. Character.isDigit() is a better option thаn explicitly looking at character codes. You could also potentially simplify it by replacing the whole thing with strValue.matches("\\d+"); (\\d is a regex code for "digit", so this returns true when your string contains only digits.
I believe you are trying re-invent the wheel here. Java already has pretty easy implementation.
Integer.toString(number, base) method will help you to convert to another base.
Example:
System.out.println(Integer.toString(10, 5));
Look Integer.parseInt() method also where ever needed.
I haven't gotten around to isValid yet; subtracting the value of 0 as suggested and using a separate local variable did give me the correct output.
public int baseXToDec()
{
int decVal = 0, exponent = strValue.length()-1;
for (int i=0; i<strValue.length(); i++)
{
// update result
decVal += ((strValue.charAt(i)-'0') * Math.pow(base, exponent));
// decrement exponent
exponent--;
}
base = 10;
strValue = "" + decVal;
decimal = decVal;
return decimal;
}
Your method isValid contains true if the last char is valid and false if the last char is not valid.
Change it:
public boolean isValid()
{
for (int i=0; i<strValue.length()-1; i++)
{
if (!((strValue.charAt(i)>47 && strValue.charAt(i)<58) || (strValue.charAt(i)>64 && strValue.charAt(i)<71)))
return false;
}
return true;
}
I used the following code in my class with the intention of doing one round of recursion (specifically creating an object within an object of the same type). Well, that one round of recursion is now like 200 rounds of recursion... So that messes a lot of stuff up. The following code is where I call the recursion:
//Find Solute
try{if(iterations == 0){ //RECONDITION::: iterations is equal to zero at start of program and is static!
remaining = Whitespace.removePreceding(remaining);
String unused = remaining.substring(0);
InterpretInput solute = new InterpretInput(remaining);
solute.begin();
solute.fixSoluteAmount();
soluteAmount = solute.getSolventAmount();
isSolution = true;
++iterations;
}}catch(Exception ex){
}
finally{
System.out.println("Debugging point D");
findNumber();
fixSolventAmount();
fixSoluteAmount();
}
You'll find "Debugging point D" above, this is printed a ton of times so it apparently is going after the recursion with a bunch of objects, and the rest of the code is screwed up because of this. I just need someone experienced to point out how this is flawed as one iteration of recursion.
If you need the entire class, I'll also copy / paste that bellow, but it's almost 200 lines... so yeah... (I know I shouldn't make classes that long but this object needed a lot of stuff in it).
import java.util.ArrayList;
public class InterpretInput {
/**
* #param remaining - The string that was input, what's left to analyze
*/
/** Variables */
private String remaining; //The string input by the user, containing what's left to analyze
private static int iterations = 0;
//Solvent Info
private double solventAmount; //The amount of the solvent expressed as final in MOLES
private M solventAmountMeas; //The measurement used in solventAmount
private double solventConc; //The concentration of the solvent
private M solventConcMeas; //The measurement used in solventConc
private E[] solventCompound; //The compound of the solvent
private E[] water = {E.H, E.H, E.O};
//Solute Info
private double soluteAmount; //The amount of solute in the solution
//Type of Data
private boolean isElement = false; //Determines if the information input is only an element
private boolean hasAmount = false; //Determines if the information input has an amount of solvent
private boolean isSolution = false; //determines if the information input is a solution
private int identificationNumber;
/** Constructor */
public InterpretInput (String remain){
remaining = remain;
}
/** Mutator Methods
* #throws Exception */
public void begin() throws Exception{
//Find Measurement
FindMeasurements measureObject = new FindMeasurements(remaining);
while (measureObject.exists() == true){
measureObject.determineNumber();
measureObject.determineMeasurement();
double solventAmountTemp = measureObject.getAmount();
M solventAmountMeasTemp = measureObject.getMeasurement();
if( (solventAmountMeasTemp.getType()) == 3 ){
isSolution = true;
solventConc = solventAmountTemp;
solventConcMeas = solventAmountMeasTemp;
}else{
hasAmount = true;
solventAmount = solventAmountTemp;
solventAmountMeas = solventAmountMeasTemp;
}
remaining = measureObject.getRemaining();
}
//Find Compound
FindCompound comp = new FindCompound(remaining);
comp.getCompound();
solventCompound = comp.getValue();
remaining = comp.getRemaining();
if (solventCompound.length == 1)
isElement = true;
//Find Solute
try{if(iterations == 0){
remaining = Whitespace.removePreceding(remaining);
String unused = remaining.substring(0);
InterpretInput solute = new InterpretInput(remaining);
solute.begin();
solute.fixSoluteAmount();
soluteAmount = solute.getSolventAmount();
isSolution = true;
++iterations;
}}catch(Exception ex){
}
finally{
System.out.println("Debugging point D");
findNumber();
fixSolventAmount();
fixSoluteAmount();
}
}
public void fixSoluteAmount() throws Exception {
fixSolventAmount();
}
public void fixSolventAmount() throws Exception {
switch (identificationNumber){ //VIEW findNumber TO SEE INDEX OF THESE CASES
case 1:{
//In this situation, there would be nothing to change to begin with
break;
}
case 2:{
//In this situation, there would be nothing to change to begin with
break;
}
case 3:{
solventAmount *= solventAmountMeas.ofBase();
switch (solventAmountMeas.getType()){
case 1:{ //volume
if (!solventCompound.equals(water))
throw new Exception();
else{
solventAmount *= 1000; //Convert 1000g for every 1L
double molarMass = 0;
for (E e : solventCompound)
molarMass += e.atomicMass();
solventAmount /= molarMass; //convert to moles
}
}
case 2:{ //mass
double molarMass = 0;
for (E e : solventCompound)
molarMass += e.atomicMass();
solventAmount /= molarMass; //convert to moles
}
}
}
case 4:{
if(solventAmountMeas.equals(M.m)){
throw new Exception(); //I AM TAKING OUT THIS FEATURE, IT WILL BE TOO DIFFICULT TO IMPLEMENT
//BASICALLY, YOU CANNOT USE MOLALITY IN THIS PROGRAM ANYMORE
}
}
case 5:{
if(solventAmountMeas.equals(M.m))
throw new Exception(); //I AM TAKING OUT THIS FEATURE, IT WILL BE TOO DIFFICULT TO IMPLEMENT
//BASICALLY, YOU CANNOT USE MOLALITY IN THIS PROGRAM ANYMORE
double molarMass = 0;
for (E e : solventCompound)
molarMass += e.atomicMass();
solventAmount /= molarMass; //convert to moles
}
}
}
public void findNumber(){
/**
* 1 = Element
* 2 = Compound
* 3 = measured amount of compound
* 4 = specific concentration of solution
* 5 = Measured amount of specific concentration of solution
* */
if(isElement==true)
identificationNumber = 1;
else if(isSolution == false && hasAmount == false)
identificationNumber = 2;
else if(isSolution == false && hasAmount == true)
identificationNumber = 3;
else if(isSolution == true && hasAmount == false)
identificationNumber = 4;
else
identificationNumber = 5;
}
/** Accessory Methods */
public double getSolventAmount(){
return solventAmount;
}
public double getSoluteAmount(){
return soluteAmount;
}
public double getConcentration(){
return solventConc;
}
public E[] returnCompound(){
return solventCompound;
}
}
Your Begin function appears to call itself prior to incrementing the iterations variable. This will cause an infinite recursion. See my HERE notes in the code below.
//Find Solute
try{if(iterations == 0){
remaining = Whitespace.removePreceding(remaining);
String unused = remaining.substring(0);
InterpretInput solute = new InterpretInput(remaining);
// HERE - calls itself again, prior to incrementing
// iterations variable
solute.begin();
solute.fixSoluteAmount();
soluteAmount = solute.getSolventAmount();
isSolution = true;
// HERE - iterations is incremented, but too late
++iterations;
}}catch(Exception ex){
}
To resolve the recursion issue, you should increment iterations prior to the begin call.
The code here is pretty messy; it's a little difficult to figure out what the goal is. What are you trying to do with the string in InterpretInput, and why does it take such a complex solution (recursively built objects) as opposed to a loop or even just a recursive method?
Beyond that, however, it doesn't appear that there should be any way for your recursion to break. The only valid way for it to do so is if iterations != 0, which is never true because the ONLY time iterations is ever incremented is after the recursive call. Thus, I think the only reason the program terminates at all is that you overflow the stack, but the exception is caught by the empty catch block. Try printing something out in that block; I bet that's where the code is going even if you don't expect it to.
When running below program, I cannot reach the end of the main function...
I am new to Java, and cannot find its defects. I need your help. Thanks.
import java.util.*;
class Schedule {
public String day;
private int startTime, endTime;
public Schedule(String input_day, int input_start, int input_end) {
day = input_day;
startTime = input_start;
endTime = input_end;
}
/* clashWith: to check whether this schedule clash with a Schedule called otherSchedule
* PRE-Condition : input must be of Schedule type
* POST-Condition : return true if two Schedule clash, return false if not.
*/
public boolean clashWith(Schedule otherSchedule) {
if(this.day != otherSchedule.day || this.endTime <= otherSchedule.startTime || this.startTime >= otherSchedule.endTime)
return false;
return true;
}
}
class Module {
String code;
Schedule lecture, tutorial, lab;
public Module(String input_code, Schedule input_lecture, Schedule input_tutorial, Schedule input_lab) {
code = input_code;
lecture = input_lecture;
tutorial = input_tutorial;
lab = input_lab;
}
/* count: to count number of classes(lecture, tutorial, and lab of only this Module) on day.
* For example: when day = "Monday", lecture is on Monday, tutorial is on Monday
* but lab is on Tuesday, then return 2. (lecture and tutorial are on Monday).
* PRE-Condition :
* POST-Condition :
*/
public int count(String day) {
int num = 0;
if(lecture.day == day)
num++;
if(tutorial.day == day)
num++;
if(lab.day == day)
num++;
return num;
}
/* clashWith: to check whether this module clash with a Module called otherModule
* PRE-Condition :
* POST-Condition :
*/
public boolean clashWith(Module otherModule) {
if(lecture.clashWith(otherModule.lecture) || lecture.clashWith(otherModule.tutorial) || lecture.clashWith(otherModule.lab) )
return true;
if(tutorial.clashWith(otherModule.lecture) || tutorial.clashWith(otherModule.tutorial) || tutorial.clashWith(otherModule.lab))
return true;
if(lab.clashWith(otherModule.lecture) || lab.clashWith(otherModule.tutorial) || lab.clashWith(otherModule.lab))
return true;
return false;
}
}
class Timetable {
Vector<Module> listOfModule;
/* checkClash: to check whether otherModule clash with one of
* the modules in our timetable list.
* PRE-Condition :
* POST-Condition :
*/
public boolean checkClash(Module otherModule) {
for(Module c: listOfModule)
if(c.clashWith(otherModule))
return true;
return false;
}
/* add: to add a new module to the timetable list.
* PRE-Condition :
* POST-Condition :
*/
public void add(Module module) {
listOfModule.add(module);
}
/* count: to count number of classes on day.
* PRE-Condition :
* POST-Condition :
*/
public int count(String day) {
int count_day=0;
for(Module c: listOfModule)
count_day += c.count(day);
return count_day;
}
}
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int num_operation;
String code ;
Timetable userTimetable = new Timetable();
num_operation = input.nextInt();
for(int i=0;i<num_operation;i++) {
if(input.next() == "MODULE") {
code = input.next();
String day;
int start, end;
Schedule getLecSche = new Schedule(input.next(),input.nextInt(),input.nextInt());
Schedule getTutSche = new Schedule(input.next(),input.nextInt(),input.nextInt());
Schedule getLabSche = new Schedule(input.next(),input.nextInt(),input.nextInt());
Module userModule = new Module(code, getLecSche, getTutSche, getLabSche);
System.out.println("Reached line 162");
if(!userTimetable.checkClash(userModule)) {
userTimetable.add(userModule);
System.out.println("Added");
}
else
System.out.println("Clashed");
}
else if(input.next() == "COUNT") {
code = input.next();
System.out.println(userTimetable.count(code));
}
}
}
}
Found it. You're using == to compare Strings. That only compares the object reference.
Use this instead:
if (input.next().equals("MODULE"))
//...
if(input.next().equals("COUNT"))
It is also worth mentioning that this will not catch "Count", "cOunT", "Module", "module", or "mOdulE" - you may want to use equalsIgnoreCase() instead.
In Timetable, you are never assigning a value to listOfModule:
Vector<Module> listOfModule;
Which causes a NullPointerException. You need to assign a new object to that reference:
Vector<Module> listOfModule = new Vector<Module>();
I think the problem is with input.next() here.
public String next()
Finds and returns the next complete token from this scanner. A
complete token is preceded and followed by input that matches the
delimiter pattern. This method may block while waiting for input to
scan, even if a previous invocation of hasNext() returned true.
UPDATE :
Removing the confusion for downvoters input.next() above is from statement if(input.next() == "MODULE") {
I was given the assignment to "implement and test a language “recognizer” object, provided to you through a Java interface defined at the end of this document. A language recognizer accepts strings of characters and determines whether or not they are in the language."
The language is as follows:
L = {a*b} union {ab*}, or restated in English, L is the set of all strings of either (1) zero or more as (a*) followed by a b, or (2) an a followed by zero or more bs (b*).
I've made some progress, but I'm stuck.
Here's the interface:
/** The Recognizer interface provides a recognizer for the
* language L below.
*
* Let Sigma = {a,b} = the input character set.
*
* Let L = {ab*} union {a*b} be the language (set of
* legal strings) recognized by this recognizer.
*
* Let S = s1s2...sn be the string of n characters already
* input by this recognizer.
*
* Recognizer constructor must ensure: S' = < >
*/
interface Recognizer {
/**
* require: c in Sigma
*
* ensure: S' = S ^ c
*
* param c
*/
public void nextChar(char c);
/**
* Checks if input string S is in language L.
*
* return (S in L)
*/
public boolean isIn();
/**
* ensure: S' = < >
*/
public void reset();
}
Here's my structure:
import java.util.*;
public class LanguageVector implements Recognizer {
int element = 0;
int a = 0;
int b = 0;
Vector<Character> v = new Vector<Character>();
public void nextChar(char c) {
v.add(c);
}
public boolean isIn(){
boolean isTrue = true;
for(int i=0;i<v.size();i++) {
if (v.size() == 1){
if (v.firstElement() == 'a' || v.firstElement() =='b'){
isTrue = true;
}
else
isTrue = false;
}
else if (v.firstElement() == 'a'){
if (v.lastElement() == 'a')
isTrue = false;
else if (v.lastElement() == 'b')
while (v.elementAt(element)== 'a' ){
a++;
element++;
System.out.println(element);
}
while (v.elementAt(element)== 'b'){
b++;
element++;
System.out.println(element);
}
if (v.elementAt(element)!= 'b'){
isTrue = false;
}
else if (a > 1 && b > 1){
isTrue = false;
}
else
isTrue = true;
}
else if (v.firstElement() == 'b'){
isTrue = false;
}
else
isTrue = false;
}
return isTrue;
}
public void reset(){
v.clear();
}
}
And here's my testing class:
import java.util.*;
public class LanguageTester {
/**
* #param args
*/
public static void main(String[] args) {
Recognizer r = new LanguageVector();
r.nextChar('a');
r.nextChar('a');
r.nextChar('a');
r.nextChar('b');
if (r.isIn())
System.out.println("string is in L");
else
System.out.println("string is not in L");
System.out.println("End of test");
r.reset();
}
}
When I run, I get the following output:
1
2
3
Exception in thread "main" 4
java.lang.ArrayIndexOutOfBoundsException: 4 >= 4
at java.util.Vector.elementAt(Unknown Source)
at LanguageVector.isIn(LanguageVector.java:34)
at LanguageTester.main(LanguageTester.java:18)
Why is this happening?
Also, how can I use user input, turn it into a vector, and use that within this structure now?
Forgive me if this question is too lengthy, I wasn't sure how to narrow it down without leaving important details out. Thanks
When it occurs?
Out of bounds exception is occurred when you try to access an array with index that exceeded its length. maximum index of a java array is (length -1)
for example:
String [] stringArray = new String[10];
stringArray[10]
// the code above will produce an out of bounds exception, because the it bigger than length -1, which is 10 - 1 = 9.
If you don't know the size or length of an array, you can know it from stringArray.length.
How to handle it?
You should make sure that your program doesn't access an array with index bigger than length - 1.
example:
for(int i=0;i<stringArray.lenght;i++) {
//write your code here
}
the above code will guarantee that stringArray will never be accessed beyond its maximum index.
Your Case
In your case, 4 >= 4 itself says you are trying to access 5th element i.e. elementAt(4) however size of your Vector of 4.
Array is based on 0 index i.e. if your length is 4 you will have data at as Vector[0], Vector[1], Vector[2], Vector[3].
Also read this for more info...
The problem is in the isIn() method. You're not checking whether the element variable is still below v.size(). You just continue incrementing it so the next time that the application accesses v.elementAt(element); the variable element is bigger than the size of v, so it's an ArrayOutofBounds exception.