Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Background: The code for class ScanSupport given at the end of the notes for Lec

ID: 3587116 • Letter: B

Question

Background: The code for class ScanSupport given at the end of the notes for Lecture 10 on Sept. 26 raises some questions: Consider writing a nextFloat method to add to ScanSupport. A preliminary version of this would be very similar to nextName except that the final two lines would be:

a) ScanSupport has no tools equivalent to the hasNext methods of the scanner. If there is no next name on the current input line, what does nextName()return? (This has an impact on the pattern you use and it is the origin of an error in the above code.) (0.5 points)

b) Give a declaration for the pattern named number above that recognizes 10, 9.12, 87. and .6345 (for example), as well as handling the possibility that there is no floating point number before the end of line. (0.5 points)

c) Fix the code given above so that it returns Float.NaN if there is no next floating point number on the current input line. (That's a special floatvalue that represents something that is not a number. If you have a float named f, f.isNaN() tests to see if the value is not a number.)

Explanation / Answer

Answers are given below. If it helped, please don't forget to rate it. Thank you.

Answer A)

Since the pattern name is defined as "[a-zA-Z0-9_]*", it will allow to match even an empty string. So an empty string is returned when there is no name in current input line. This is the error and we can fix it by changing the pattern for name as "[a-zA-Z0-9_]+" which means atleast 1 allowed character should be present. If we make this modification to name pattern, then when skip() is called, and there is no next name, a NoSuchElementException will be thrown

Answer for B and C

Using the behaviour of skip() which throws NoSuchElementException when a pattern is not found, we have the following code for nextNumber() which returns the next floating point number if one is present and Float.NaN when none is present.

import java.util.NoSuchElementException;

import java.util.Scanner;

import java.util.regex.Pattern;

/** Support methods for scanning

* @see Errors

*/

public class ScanSupport {

/** Pattern for identifers

*/

private static final Pattern name

= Pattern.compile( "[a-zA-Z0-9_]*" );

  

/** Pattern for numbers

* there are 2 groups defining the pattern. A floating number could match any of the 2 groups

* 1st group ([0-9]+(\.[0-9]*)?) matches 1 or more digits followed by an optional fractional part (i.e. a decimal point followed by zero or more digits)

* 2nd group matches only fractional part i.e a decimal point followed by 1 or more digits

* a double slash i.e. \. is used since . is Java Regex pattern character to match any character. We need to escape it to indicate it is the real decimal period

*/

private static final Pattern number

= Pattern.compile( "([0-9]+(\.[0-9]*)?)|(\.[0-9]+)" );

  

  

/** Pattern for whitespace excluding things like newline

*/

private static final Pattern whitespace

= Pattern.compile( "[ ]*" );

/** Get next name without skipping to next line (unlike sc.Next())

* @param sc the scanner from which end of line is scanned

* @return the name, if there was one, or an empty string

*/

public static String nextName( Scanner sc ) {

sc.skip( whitespace );

// the following is weird code, it skips the name

// and then returns the string that matched what was skipped

sc.skip( name );

return sc.match().group();

}

/** Get next number without skipping to next line (unlike sc.Next())

* @param sc the scanner from which end of line is scanned

* @return the number, if there was one, or an Float.NaN

*/

public static Float nextNumber( Scanner sc ) {

sc.skip( whitespace );

// the following is weird code, it skips the number

// and then returns the string that matched what was skipped

try

{

sc.skip( number );

return Float.parseFloat(sc.match().group());

}catch(NoSuchElementException e) //did not find a floating point number pattern

{

return Float.NaN;

}

  

}

/** Advance to next line and complain if is junk at the line end

* @see Errors

* @param message gives a prefix to give context to error messages

* @param sc the scanner from which end of line is scanned

*/

public static void lineEnd( Scanner sc, String message ) {

sc.skip( whitespace );

String lineEnd = sc.nextLine();

if ( (!lineEnd.equals( "" ))

&& (!lineEnd.startsWith( "--" )) ) {

Errors.warn(

message +

" followed unexpected by '" + lineEnd + "'"

);

}

}

}

A Test program to check the implementation of the correctness of nextNumber() is given below. This is just for verfication purpose and not asked in question.

import java.util.Scanner;

public class TestScanSupport {

public static void main(String[] args) {

String str = "10 9.12 87. .6345 ";

Scanner s = new Scanner(str);

System.out.println( ScanSupport.nextNumber(s)); //should return 10

System.out.println( ScanSupport.nextNumber(s)); //return 9.12

System.out.println( ScanSupport.nextNumber(s)); //return 87.

System.out.println( ScanSupport.nextNumber(s)); //return .6345

System.out.println( ScanSupport.nextNumber(s)); //return NaN since no more floating point number

System.out.println( ScanSupport.nextNumber(s)); //return NaN since no more floating point number

System.out.println("done");

}

}

output

10.0
9.12
87.0
0.6345
NaN
NaN
done