java Scanner.hasNext() usage - java

public static void main(String args[]){
Scanner in = new Scanner(System.in);
String a = in.next();
if (in.hasNext()) {
System.out.println("OK")
} else {
System.out.println("error");
}
}
What I want is:
if the user type in a String with more than one word, print "OK".
if the user type in a String with only one word, print "error".
However, it doesn't work well. When I type a single word as an input, it doesn't print "error" and I don't know why.

Read a line and then check whether there are more than one word.
String a = in.nextLine();
if( a.trim().split("\\s").length> 1 ){
System.out.println("OK");
} else {
System.out.println("error");
}

Your condition resolves true, if you have any kind of new input. Try something like contains(" ") for testing your input to contain spaces. If you want to make sure the input doesn't just contain spaces but also some other characters, use trim() before.

hasNext() is a blocking call. Your program is going to sit around until someone types a letter, and then go to the System.out.println("OK"); line. I would recommend using an InputStreamReader passing in System.in to the constructor, and then reading the input and determining its length from there. Hope it helps.

From Scanner#hasNext() documentation
Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.
So in case of only one word scanner will wait for next input blocking your program.
Consider reading entire line with nextLine() and checking if it contains few words.
You can do it same way you are doing now, but this time create Scanner based on data from line you got from user.
You can also use line.trim().indexOf(" ") == -1 condition to determine if String doesn't contain whitespace in the middle of words.

Scanner#hasNext() is going to return a boolean value indicating whether or not there is more input
and as long as the user has not entered end-of-file indicator, hasNext() is going to return true
The end-of-file indicator is a system-dependent keystroke combination
which the user enters to indicate that there’s no more data to input.
on UNIX/Linux/Mac OS X it's ctrl + d,,, On Windows it's ctrl + z
look at this simple example to see how to use it
// Fig. 5.9: LetterGrades.java
// LetterGrades class uses the switch statement to count letter grades.
import java.util.Scanner;
public class LetterGrades
{
public static void main(String[] args)
{
int total = 0; // sum of grades
int gradeCounter = 0; // number of grades entered
int aCount = 0; // count of A grades
int bCount = 0; // count of B grades
int cCount = 0; // count of C grades
int dCount = 0; // count of D grades
int fCount = 0; // count of F grades
Scanner input = new Scanner(System.in);
System.out.printf("%s%n%s%n %s%n %s%n",
"Enter the integer grades in the range 0–100.",
"Type the end-of-file indicator to terminate input:",
"On UNIX/Linux/Mac OS X type <Ctrl> d then press Enter",
"On Windows type <Ctrl> z then press Enter");
// loop until user enters the end-of-file indicator
while (input.hasNext())
{
int grade = input.nextInt(); // read grade
total += grade; // add grade to total
++gradeCounter; // increment number of grades
// increment appropriate letter-grade counter
switch (grade / 10)
{
case 9: // grade was between 90
case 10: // and 100, inclusive
++aCount;
break; // exits switch
case 8: // grade was between 80 and 89
++bCount;
break; // exits switch
case 7: // grade was between 70 and 79
++cCount;
break; // exits switch
case 6: // grade was between 60 and 69
++dCount;
break; // exits switch
default: // grade was less than 60
++fCount;
break; // optional; exits switch anyway
} // end switch
} // end while
// display grade report
System.out.printf("%nGrade Report:%n");
// if user entered at least one grade...
if (gradeCounter != 0)
{
// calculate average of all grades entered
double average = (double) total / gradeCounter;
// output summary of results
System.out.printf("Total of the %d grades entered is %d%n",
gradeCounter, total);
System.out.printf("Class average is %.2f%n", average);
System.out.printf("%n%s%n%s%d%n%s%d%n%s%d%n%s%d%n%s%d%n",
"Number of students who received each grade:",
"A: ", aCount, // display number of A grades
"B: ", bCount, // display number of B grades
"C: ", cCount, // display number of C grades
"D: ", dCount, // display number of D grades
"F: ", fCount); // display number of F grades
} // end if
else // no grades were entered, so output appropriate message
System.out.println("No grades were entered");
} // end main
} // end class LetterGrades
and the output will be something like this
Enter the integer grades in the range 0–100.
Type the end-of-file indicator to terminate input:
On UNIX/Linux/Mac OS X type <Ctrl> d then press Enter
On Windows type <Ctrl> z then press Enter
99
92
45
57
63
71
76
85
90
100
^Z
Grade Report:
Total of the 10 grades entered is 778
Class average is 77.80
Number of students who received each grade:
A: 4
B: 1
C: 2
D: 1
F: 2
Resources Learning Path: Professional Java Developer
and Java™ How To Program (Early Objects), Tenth Edition

Related

While Loops in Java Problems

Now we are learning about while loops - here is the challenge. "the program should repeatedly prompts the user to enter a number. Keep a running total of the numbers the user enters and also keep a count of the number of entries the user makes. The program should stop whenever the user enters something that is not an integer. When the user has finished, print the number of entries the user has typed and their sum."
"A sample interaction with this program might look like this:
Program: Enter an integer to continue or a non-integer value to finish. Then press return.
User: 2
Program: Enter an integer to continue or a non-integer value to finish. Then press return.
User: 6
Program: Enter an integer to continue or a non-integer value to finish. Then press return.
User: 89
Program: Enter an integer to continue or a non-integer value to finish. Then press return.
User: q
Program: You entered 3 integers. The sum of your entries is 97."
Here's what I have so far.
import java.util.Scanner;
public class InputSequence
{
public static void main (String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println ("Enter an integer to continue or a non-integer value to finish. Then press return.");
int sum = 0;
int total = 0;
while (scan.hasNextInt())
{
scan.next();
System.out.println ("Enter an integer to continue or a non-integer value to finish. Then press return.");
int input = scan.nextInt();
sum = input + input;
total = total + 1;
}
System.out.println ("You entered " + total + " integers. The sum of your entries is " + sum);
}
}
I'm just a bit confused because my interaction seems to skip the system.out.println every 2nd time in the while loop and then doesn't count the first input into the total. I believe the sum also doesn't always calculate correctly. Also, if I input a lot of integers then a non-integer to end the program I will receive an error rather than the end message. However, let's say I put in two integers then a string, I will get the end message.
Your problem is in the usage in scan.next() that can be removed and should show the System.out.println correctly.
.next() method is a generic method of nextInt() which returns a String instead.
Another thing you can do is to switch from a while loop to do while to prevent you from repeating this line twice:
System.out.println ("Enter an integer to continue or a non-integer value to finish. Then press return.");
an example would be:
Scanner scan = new Scanner(System.in);
int sum = 0;
int total = 0;
do {
System.out.println ("Enter an integer to continue or a non-integer value to finish. Then press return.");
int input = scan.nextInt();
sum = sum + input;
total = total + 1;
} while (scan.hasNextInt());
System.out.println ("You entered " + total + " integers. The sum of your entries is " + sum);
}

Why gets my code after end of file statement ignored?

I'm currently trying an example from my textbook on learning java, but my code after an EoF statement just gets ignored by the compiler.
package lettergrades;
import java.util.Scanner;
public class LetterGrades {
public static void main(String[] args) {
int total = 0;
int gradeCounter = 0;
int aCount = 0;
int bCount = 0;
int cCount = 0;
int dCount = 0;
int fCount = 0;
Scanner input = new Scanner(System.in);
System.out.printf("%s%n%s%n %s%n %s%n", "Enter the integer grades in the range 0-100", "Type the end-of-file indicator to terminate input", "on unix type <ctrl> d then press Enter","On windows type <Ctrl> z then press enter");
while (input.hasNext()){
int grade = input.nextInt();
total += grade;
++gradeCounter;
switch (grade/10){
case 9:
case 10:
++aCount;
break;
case 8:
++bCount;
break;
case 7:
++cCount;
break;
case 6:
++dCount;
break;
default:
++fCount;
break;
}
}
System.out.printf("%nGrade Report:%n");
if (gradeCounter !=0){
double average = (double) total/gradeCounter;
System.out.printf("total of the %d grades entered is %d%n", gradeCounter, total);
System.out.printf("Class average is %.2f%n", average);
System.out.printf("%n%s%n%s%d%n%s%d%n%s%d%n%s%d%n%s%d%n", "Number of students that received each grade","A: ", aCount, "B: ", bCount , "C: ", cCount, "D: ", dCount, "F: ", fCount);
}
else
System.out.println("No grades were entered");
}
}
This is the output i get :
Enter the integer grades in the range 0-100
Type the end-of-file indicator to terminate input
on unix type <ctrl> d then press Enter
On windows type <Ctrl> z then press enter
But when i input ctrl D and press enter, nothing happens. Why don't the printf and if statements work?
As e.g. #FredLarson is reporting, it's working fine for most. You're relying on EOF character resulting in sysin being closed, which will in turn cause scanner's hasNext() to return false.
Evidently, on your system, that isn't working. If you're running this inside an IDE's 'console', they often don't let you close sysin or work differently from the command line.
You can try to figure out which voodoo key combo ends things, but there is an alternative.
Instead of EOF, or in addition to EOF, make another symbol that ends inputs. Perhaps 0, or 'END'. In the later case you can no longer rely on nextInt, you'd have to call next, check if it is END, if yes, stop accepting input, and if not, toss it through Integer.parseInt to end up with a numeric value.
Now you no longer have to mention various platforms in your console messages, and you avoid these issues.

GPA calculator assistance

Hi I was wondering if I could get some help with a GPA calculator.
What it needs to do is:
The input will consist of a sequence of terms, e.g., semesters.
The input for each term will consist of grades and credits for courses taken within that term.
For each term, the user will type in an integer that represents the number of courses
taken within that term.
Each course is specified by a String letter grade and an int number of credits, in that order, separated by white space. 5. If the user types in -1 for the number of courses taken in a term, then the program must print a final overall summary and then terminate.
DO NOT prompt for any input. Thus, after you run your program in BlueJ, type Ctrl-T to force the Terminal window to pop up.
As always, follow the input / output format depicted in the Sample runs section.
Shown below is the error message I get and the code I have, thank you for any assistance in advance or tips I could try.
Terminal window and error message:
import java.util.Scanner;
/*
*
*
*/
public class Prog2 {
public static void main(String args[]) {
Scanner numberInput = new Scanner(System.in);
int numberofClasses = numberInput.nextInt();
Scanner input = new Scanner(System.in);
String [] grade = new String[5];
int [] credit = new int [5];
double totalCredit = 0.0;
double realGrade = 0.0;
double result = 0.0;
while (numberofClasses > 0)
{
for (int x = 0; x < numberofClasses; x++ )
{
grade[x] = input.next();
credit[x] = input.nextInt();
}
for(int x=0;x < numberofClasses; x++ ){
if(grade[x].equals("A+")){
realGrade=4.0;
}
else if(grade[x].equals("A")){
realGrade=4.0;
}
else if(grade[x].equals("A-")){
realGrade=3.67;
}
else if(grade[x].equals("B+")){
realGrade=3.33;
}
else if(grade[x].equals("B")){
realGrade=3.00;
}
else if(grade[x].equals("B-")){
realGrade=2.67;
}
else if(grade[x].equals("C+")){
realGrade=2.33;
}
else if(grade[x].equals("C")){
realGrade=2.00;
}
else if(grade[x].equals("C-")){
realGrade=1.33;
}
result = result+realGrade*credit[x];
totalCredit=totalCredit+credit[x];
}
System.out.println("Summary for term:");
System.out.println("----------------------------------");
System.out.println("Term total grade points: " + result);
System.out.println("Term total credits:" + totalCredit);
System.out.println("GPA:"+result/totalCredit);
}
// This block is getting used later please ignore
System.out.println("Final Summary:");
System.out.println("----------------------------------");
System.out.println(" Overall terms");
System.out.println(" Total grade points: " + result);// this needs to be all );
System.out.println(" Total credits" + totalCredit);//This needs to be all );
System.out.println("Cumulative GPA:"+result/totalCredit);
}
}
When your while loop ends, numberofClasses still contains the value that was entered before the while loop started the first time. Specifically, after you output the line:
GPA=3.0588...
you hit the end of the loop, then return to:
while (numberofClasses > 0)
which is true. The next "3" that you enter doesn't go into numberofClasses, it is picked up by
grade[x] = input.next();
Then the "A" is picked up by
credit[x] = input.nextInt();
which throws an exception since it's not an integer.
All you need to do is ask for the number of classes again at the end of the while loop:
System.out.println("GPA:"+result/totalCredit);
numberofClasses = numberInput.nextInt();
}
Output:
5
A 3
B 2
C 4
A 5
C 3
Summary for term:
----------------------------------
Term total grade points: 52.0
Term total credits:17.0
GPA:3.0588235294117645
3
A 3
B 5
C 1
Summary for term:
----------------------------------
Term total grade points: 81.0
Term total credits:26.0
GPA:3.1153846153846154
i recommend looking into whether your compiler or IDE has a "debug" feature. It is a very helpful tool, and lets you watch how your program goes through your code
Just a tip...
When you ask for input, print what you're asking for first. When I launched your program I had no idea what to do. Try adding System.out.println("input number of classes you took");before you prompt for that number.
Here is what is wrong. (If you printed what you're asking for first, this would be more apparent).
after your program displays the stats, you enter 5. Yet your program is actually still on this line grade[x] = input.next(); on line 22 i believe.
when you enter 5, your scanner is expecting a letter. and an exception is thrown.
you need to consider how you escape this loop here. while (numberofClasses > 0) perhaps use an if statement? otherwise your program loops for forever, never asking for a new class number

Why is my for loop printing 2 of my prompts at one time while using (scanner).nextLine();

Is there a problem in my while or for loops by chance or am I missing something? First run through works fine but on the second I get this:
Enter course NAME: class name
Enter course HOURS: 4
Enter course GRADE: 4.0
You have entered class: jeff graves, class hours: 4 and, class grade 4.0
Do you want to continue:
y
Enter course NAME: Enter course HOURS:
It works just fine using (scanner).next(); but then I can only take one word from the user and it will throw an error from the nextInt when it rolls over.
public class GetGrades { //open class GetGrades
public static void main(String[] args) {
/**creating new instance of scanner named input to read user input*/
Scanner input = new Scanner(System.in); // create new instance of scanner object
boolean repeat = true; //boolean value for while loop holding array input
String s; // create string to store user input value for exiting loops
/** create 3 arrays to store course name, hours, and grades*/
String[] name = new String[20]; //type string array for class name
int[] hours = new int[20]; // type int array for class hours
float[] grade = new float[20]; //type float array for class grade
outerloop: // set break point for nested for loops exit on user input
while(repeat != false) {// while loop with boolean value to let user exit array input
for (int i=0; i<name.length; i++) { //for loop for name array
System.out.print("Enter course NAME: "); //prompt user for input
name[i] = input.nextLine(); //read next line value and store in array name
System.out.print("Enter course HOURS: "); //prompt user for input
hours[i] = input.nextInt(); //read the next int and store in array hours
System.out.print("Enter course GRADE: "); //prompt user for input
grade[i] = input.nextFloat(); //read the next float value and store in array grade
/**Print line to console summing um what the user has entered*/
System.out.println("You have entered class: " + name[i] + ", class hours: " + hours[i] +
" and, class grade " + grade[i]);
/**prompt user if wanted to enter more grades, break loop on n or N*/
System.out.println("Do you want to continue:");
s = input.next();
if ( s.equals("y") || s.equals("Y")) { //open if statement
repeat = true;
} else { //close if and open else
break outerloop;
} //close else statement
}//close for loop with i as count
}//close while
input.next() will read the next word. input.nextLine() will read up until the next time you press enter.
This means that when you write "y" and hit enter, you've input both a word "y", as well as the next enter, filling in both prompts at the same time and causing the next prompt to be written.
You can simply replace your next() with nextLine() when you ask to continue:
System.out.println("Do you want to continue:");
s = input.next();
becomes
System.out.println("Do you want to continue:");
s = input.nextLine();
thereby reading both the "y" and the enter. The next prompt is now free to accept new input.
When you input the grade, for example 12.3 and enter, "input.nextFloat();" will only take "12.3" but not "enter", so "enter" will be taken by the next scanner.
In my opinion,
first, change "s = input.next()" to "s = input.nextLine()", but it will take the "enter" of previous scanner "grade[i] = input.nextFloat();", so, second, put it into a while loop as a condition. like this
while((s = input.nextLine()).equals("")) {}
therefore, it won't stop til get the expect input.
try this..
System.out.print("Do you want to continue:");
while((s = input.nextLine()).equals("")) {}
if (s.equals("y") || s.equals("Y")) { // open if statement
repeat = true;
} else { // close if and open else
break outerloop;
} // close else statement

How do I keep track the number of times a specific input was entered by the user?

My program should ask the user to enter some grades. After the input is finished, the program has to show which grade was entered how many times (or in another word, how many times each grade was entered).
For example, if the user enters grade 3 two times, thats menas total 2 students has got the grade 3. If the grade F is entered 3 times, that means 3 students has got the failing grade F, and so on....
The final output should look something like this:
Example output:
grade F= 3 students
grade 3= 2 studnets
and so on....
...........................
...........................
Now my problem is with keeping track of each grade and print them out telling how many times (also means how many students got each specific grade) each of the grade was entered. I can't come up with idea to solve it.
My code:
package studentgrade;
import java.util.*;
public class StudentGrade {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("How many total grade you want to enter (Depending on the total number of students)? ");
int totalStudents = input.nextInt();
String grade[] = new String[totalStudents];
//asking user to enter grade
for (int i = 0; i < totalStudents; i++) {
System.out.println("Enter grade " + (i + 1) + ": ");
System.out.println("Choose only between grade 3 and F:\n");
grade[i] = input.next();
if (grade[i] == "3") {//3 defines the only passing grade
//Store that into a variable
} else if (grade[i].equalsIgnoreCase("F")) {//F defines the failing grade
//Store that into a variable
}//else{
//System.out.println("Invalid input. Try again");
//}
}
//Now print out which grade was entered how many times
}
}
Define, at the top, a variable resembling each grade and set them to 0, and then, each time in the "if" statement, add one to the corresponding variable. variable++.
At the end, use
System.out.println("Grade 3: " + variable3);
System.out.println("Grade F: " + variableF);
Also, use .equals method to compare two strings in the if statement
If you don't need the sort of introduced values, simply create an array with your needed size n (don't see exactly what means from 3 to F).
int[] grade = new int[n];
If all inputs where numbers you can make direct:
grade[input.next()] ++;
Then, as all inputs are not int you can solve it with a switch
switch(input.next()) {
case "3":
grade[0] ++;
case "2":
grade[1] ++;
....
case "F":
grade[n-1] ++;
}
This is a good use for a Map. Right now your only storing the inputs 3 and F but if you wanted to adapt this program to have more grades this would scale perfectly and it is a clean and neat solution.
// the map to store how many times a grade was entered
private static final Map<String, Integer> gradeSumMap = new HashMap<String, Integer>();
public static void addToGradeSum(String key, int num) {
if(gradeSumMap.get(key) == null) {
gradeSumMap.put(key, num);
} else {
gradeSumMap.put(key, gradeSumMap.get(key) + num);
}
}
public static void printGradeSumMap() {
for(String key : gradeSumMap.keySet()) {
System.out.println("grade " + key + " = " + gradeSumMap.get(key));
}
}
// this needs to also be .equals or .equalsIgnoreCase
if (grade[i].equals("3")) {
addToGradeSum(grade[i], 1);
} else if (grade[i].equalsIgnoreCase("F")) {
addToGradeSum(grade[i], 1);
}
then just call printGradeSumMap() when you want to print it

Categories